Skip to content
Back to work

Case study

FORGE

Mentor-driven learning platform with proof-of-work verification

  • Next.js
  • TypeScript
  • Prisma
  • PostgreSQL
  • NextAuth v5
  • KaTeX

01

The problem

I kept skipping days on my own learning and lying to myself about it. Streak apps don't work because they're trivially fakeable, you tap 'yes I studied' and move on. I wanted a lock screen that would actually grill me on what I claimed to have done, the way a good coach would. The app's job is not to be liked. It's to be the friend who says 'that's not enough, what specifically did you build?' when you try to coast. If I succeed I uninstall it; if I fail I keep it.

02

How it fits together

A week does not close on a claim. The proof-of-work engine matches it against real commits and a reachable deployment, and only then can a mentor sign it off.Drag sideways if it runs past the edge

03

What I read before writing code

  • Studied behavioural-economics literature on commitment devices: Dean Karlan's stickK, Beeminder's monetary penalties, Forest's tree-killing. Pattern: the apps that work make failure expensive in a way you actually feel. Apps that just track without consequence are noise.
  • Read interrogation methodology, not literally, but the structure: how a good cross-examination works (Reid technique critique, NIJ structured interviewing). What makes it hard to fake is asking for SPECIFICS the liar doesn't have. 'What did you build?' is gameable. 'What was the bug, what did you try first, why didn't it work?' isn't.
  • Studied Apple Screen Time and Android's Focus Mode. Both have the same flaw: they're disabled from inside themselves. If you can disable the constraint when willpower is low (which is exactly when you'd want to), the constraint is theatre. PIN-locking the settings is the fix.
  • Read about OpenRouter's routing model. Quality on a daily 200-token interrogation is fine across many models. Locking to one provider is paying for moat that doesn't exist.
  • Studied accountability-pod patterns from Nat Eliason, Tim Ferriss, and a few habit-tracking communities. External accountability beats internal accountability when willpower fails.

04

What I couldn't do

  • Has to be impossible to bypass casually, a checkbox isn't enough.
  • Has to feel earned to unlock, not annoying, otherwise you uninstall it within a week.
  • LLM cost per check-in had to stay near zero, since this fires every day, every user.
  • Has to work without the user opening the app, push notification at the lock-time.
  • Couldn't be coercive in a way that crosses ethical lines (no surveillance, no shaming).

05

The decisions that shaped it

  1. Decision 01

    An LLM interrogator, not a form.

    A form asks 'what did you do today?' and accepts any answer. The interrogator reads your claim and asks specific cross-examining follow-ups. Generic 'I studied React' gets pushed back: 'what specifically did you build, what was the bug, what would you do differently?' The system prompt is calibrated to reject vague claims and require specifics. Faking specifics is harder than just doing the work, that's the whole mechanism.

  2. Decision 02

    PIN-locked settings, not user-disable.

    If you can disable the app from inside the app, you will when willpower runs out at 11 PM after a bad day. Settings live behind a PIN you set up sober, can't change without re-entering. Same logic as ScreenTime parental controls, restrict your future self. The PIN is checked server-side; clearing app cache or reinstalling doesn't help.

  3. Decision 03

    OpenRouter, not major AI labs direct.

    OpenRouter routes to whatever model is cheapest while meeting quality bar. For a daily 200-token interrogation, GPT-4o-mini or Llama 3.3 70B is fine. I save 10x vs hardcoding to a single provider, and if one provider goes down the app keeps working. Provider neutrality is the right architecture for high-volume low-stakes calls.

  4. Decision 04

    Streak resets on skip, no make-ups, no buybacks.

    If you can buy back yesterday with twice the work today, you will gamble on it and skip more. Streak loss has to be permanent or it isn't a deterrent. Hard, but the whole point of accountability is the cost of failure.

  5. Decision 05

    Accountability pods, small groups (3-5), public skip notifications.

    Internal motivation is unreliable. External accountability is harder to fool. When you skip, your pod sees it. When they skip, you see it. Social pressure becomes the second deterrent layer behind the streak. Built this in (commit 7fbcdb2). It's opt-in because forced groups feel coercive.

  6. Decision 06

    Public build log, posts of what users built, opt-in.

    Showing the work IS the work. A public stream of 'today I built X' creates a soft pressure to have something interesting to post. Also doubles as marketing for the app, visitors see real users actually building things. Two-for-one motivational layer.

  7. Decision 07

    Grace days, but limited and visible.

    Pure no-skip is too brittle. Real life: travel, illness, family emergencies. I added 3 grace days per quarter, visible in the streak UI. Using them costs nothing but is visible to your pod. Skipping without grace days resets the streak. Grace makes the system humane without gaming it.

06

What broke and how I changed course

  • Original interrogator was too soft, accepted 'I studied for 2 hours' without follow-up. Tightened the system prompt: 'Reject any claim that lacks specifics. Ask for what was built, what failed, what was learned.' Pass rate dropped 40%, which was the point. Iteratively rewrote the prompt 6+ times to get the right level of skepticism.
  • First model was the model Sonnet, which was overkill and expensive for daily check-ins. Moved to OpenRouter with cheaper routing (Llama / Gemma / Mixtral, picked by cost-quality bid). Quality stayed identical, cost dropped 90%.
  • Tried camera-based proctoring, make the user appear on camera during interrogation to make lying harder. Removed it (commit b032662). Reasons: too invasive for the religious / privacy-conscious users I cared about, and it didn't actually prevent lying about what was DONE, only proved you were physically there. Wrong layer of accountability.
  • Added a leaderboard of streaks. Removed it (commit b032662). Public ranking turned the system into a competition and produced the wrong incentive: people gaming streak length over real work. Built it, lived with it, deleted it. Some features look good in mockups and bad in production.
  • Re-entry flow: when a user broke their streak, the original UX showed them a sad face and 'streak: 0'. Felt punishing in a demoralising way, not a productive way. Rewrote the re-entry as 'day 1 again, what's the first specific thing you'll build?' Reframes the failure as a fresh start without sugar-coating it (commit 7fbcdb2).
  • Initially required sign-up for every visit. Added a guest/demo mode (commit 12cdb83), users can try the interrogator without creating an account, the data is wiped on tab close. Lowered the activation barrier to 'click try', 10x more people actually use it once.

07

What I didn't know, and how I learned

  • I had not built a NextAuth v5 app before. Spent days on the new auth.config / middleware patterns. NextAuth v4, then v5 is a breaking redesign. Had to rebuild the whole auth surface around the new useSession hook + edge-friendly middleware.
  • I underestimated how aggressive my own willpower-bypass instincts would be. Built features assuming users would respect them; tested on myself; immediately broke them by uninstalling and reinstalling. Hardened them against my own future self. The PIN lock is there because I tried to disable it on day 3.
  • Prompt engineering for 'be skeptical without being cruel' is a delicate calibration. Overshoot and the app feels mean and people uninstall. Undershoot and it accepts anything. Eventually settled on a tone that's like a respectful old coach: 'I hear you. Tell me more. What was the actual bug you hit?'
  • Cron jobs on Vercel free tier max at one per day. I needed multiple, one for daily check-ins, one for streak-loss notifications, one for digest emails. Worked around it by triggering downstream crons from the daily one (chain pattern, same as VANTAGE).

08

What shipped

  • Daily lock-screen interrogation, ~200 tokens/day per user via OpenRouter
  • PIN-protected settings (anti-cheat against your future self)
  • Streak engine with no buy-back, 3 quarterly grace days
  • Accountability pods (3-5 users, opt-in, peer skip-visibility)
  • Public build log
  • Re-entry flow that reframes failure as fresh start
  • Guest/demo mode for instant try-without-signup
  • PWA, share certificates, OG images, onboarding shortcut
  • Removed features (leaderboard, camera proctoring) when they produced wrong incentives

09

What's next

I'd add a calendar-blocking feature: when you set 'I'll build between 7 AM and 9 AM tomorrow', the app automatically blocks distracting apps during that window. Pure check-in is reactive. Pre-commitment + blocking is proactive. Adding next iteration.

What I learned

The hardest software to build is software that's hard on you. Most apps optimise for retention; FORGE optimises for honesty. Ship the feature, watch how it actually changes behaviour, kill it if it produces the wrong incentive, even if you were proud of it. Removing software is harder than adding it.