A full feature, followed minute by minute: a publishing streak system on a
content SaaS. You'll see where plan mode, /goal, /code-review and /usage
fit in a real session.
The context
You're building a SaaS that helps freelancers publish on LinkedIn. What you noticed after 3 weeks of beta: 68% of your users create 1 or 2 posts and then drop off. You want to motivate them to publish regularly with a streak system (a run of consecutive periods), without making it punishing.
Minute 0-5, brainstorm
What you type:
"Brainstorm a publishing streak system. Freelancers publish 1-2 times and then drop off. I want to motivate them to publish regularly without being punishing. Context: Next.js 16 + Supabase, auth and dashboard already in place."
What Claude suggests:
Option 1, daily streak (Duolingo style)
Simple but punishing. Miss one day and you lose everything. A bad fit for freelancers who don't publish every day.
Option 2, weekly streak (recommended)
More flexible. "Publish at least 1 post per week" → the streak goes up. 14 days without publishing → the streak resets to zero. You can skip days, you just need to publish every week.
Option 3, points and levels
Full gamification, but it risks pulling attention away from the main goal (creating good content).
What you reply:
"Let's go with the weekly streak. Good call on the 14-day grace period."
Minute 5-15, planning
You switch to plan mode with Shift+Tab: Claude explores the code read-only and changes nothing until you've approved.
What you type:
"Write the implementation plan for the weekly streak. Supabase table, Server Action, dashboard component, tests."
What Claude produces:
A plan with 6 numbered tasks. For each one: the file to create or modify, what the task does, and the command that verifies it.
Task 1: SQL migration supabase/migrations/20260420_create_streaks.sql: streaks table (user_id, current_streak, best_streak, last_publication_date, updated_at) + RLS policy + index
Task 2: Regenerate the TypeScript types → src/types/database.types.ts
Task 3: Server Action src/lib/actions/streak.ts: getStreak() and updateStreakAfterPublish()
Task 4: UI component src/components/dashboard/publishing-streak.tsx: animated Framer Motion flame + counter
Task 5: Integration in src/app/(app)/dashboard/page.tsx
Task 6: Unit tests tests/unit/actions/streak.test.ts: 4 scenarios
What you check:
- Is the order logical? Yes: database, types, logic, UI, integration, tests
- Is anything missing? No, it's complete
- Is the scope reasonable? Yes, about 30-40 minutes of execution
What you do: you approve the plan and Claude leaves plan mode. Your session runs in auto mode (the default mode, see chapter 9): a classifier lets typecheck, lint and tests through without asking you, and by default blocks anything that touches production (deploys, production migrations) or destroys work, like a force push.
So Claude goes all the way without you nudging it at every step, you set an end condition:
/goal the 6 tasks in the plan are done and npm run typecheck, npm run lint and npm run test pass
The goal starts right away, no need to send another message. After each turn, a small fast model rereads the conversation and checks whether the condition is met. As long as it isn't, Claude goes for another turn. The ◎ /goal active indicator stays on screen the whole time. You can stop it at any point with /goal clear (details in chapter 18).
Pick a condition Claude can observe. The evaluator doesn't run anything
itself, it only reads what shows up in the conversation. "Tests pass" is
something it sees in the terminal. "The code is clean" can't be measured, and
it may go in circles. If the plan is wrong, /goal will still execute it to
the end: reviewing the plan is still your job.
Minute 15-25, execution (tasks 1-3)
Claude works on its own. Here's what happens in the chat:
Task 1, SQL migration
Claude creates supabase/migrations/20260420_create_streaks.sql:
streakstable with the 5 columns- RLS policy: each user only sees their own streak
- Index on
user_idfor performance
It runs npx supabase migration up --local on the local database → migration applied in 340ms.
A rule set directly in the PostgreSQL database (so in Supabase) that filters which rows a user is allowed to read or modify. Even if the app code forgets a filter, the database refuses to return someone else's streak. A Supabase table without an RLS policy is the first hole to look for in a review.
Task 2, TypeScript types
It regenerates the types from the database with npx supabase gen types typescript --local > src/types/database.types.ts. The TypeScript code now knows about the streaks table and its columns.
It runs npm run typecheck → no errors.
Task 3, Server Action
It creates src/lib/actions/streak.ts with the business logic:
getStreak(): fetches the current streakupdateStreakAfterPublish(): called after each publication- Logic: if the last publication is less than 14 days old, streak++; otherwise, streak = 1.
best_streakis updated when the current one beats it.
It runs npm run typecheck && npm run lint → everything passes.
Minute 25-40, execution (tasks 4-6)
Task 4, UI component
Claude creates src/components/dashboard/publishing-streak.tsx:
- Flame icon (
lucide-reactFlame) that grows with the streak - "3 weeks in a row" counter
- Personalized encouragement message
- Subtle entrance animation with Framer Motion
It runs npm run typecheck, all clear.
Task 5, dashboard integration
It modifies src/app/(app)/dashboard/page.tsx to place the streak component at the top of the grid, next to the "Posts published this month" widget.
Task 6, unit tests
It creates tests/unit/actions/streak.test.ts with:
- Normal calculation test (streak +1 when the last post is < 14 days old)
- Broken streak test (reset to 1 after 14 days)
- Best streak test (personal record preserved)
- First streak test (new user, no existing row)
It runs npm run test streak → 4/4 tests pass in 180ms.
Minute 40-50, visual check and iteration
You open localhost:3000/dashboard in your browser and look at the result.
What you notice:
- The streak counter shows up in the dashboard, OK
- The flame is a bit small, needs fixing
- The encouragement message is generic, needs work
What you type:
"The counter is too small. I'd like a bigger flame (48px instead of 24px), and a different encouragement message depending on the number of weeks: 1 week = 'Off you go!', 2-3 = 'Nice rhythm!', 4+ = 'Unstoppable!'"
Claude adjusts it in 2 minutes. You refresh the browser, it's right.
Minute 50-60, review and commit
What you type:
/code-review
The review runs as a background subagent (a separate Claude with its own context). You can set a level, from low to max: /code-review high digs deeper, at the cost of more tokens. It rereads all the modified code and reports:
- No bug found
- RLS configured correctly (security OK)
- Consistent types
- Suggestion: add a fallback when the table is empty (a new user who has never published)
Claude applies the suggestion by adding a ?? { current_streak: 0, best_streak: 0 } in getStreak(). Then:
/commit
Claude creates the commit: feat(dashboard): add weekly publishing streak with animated flame
/commit isn't a built-in command: it comes from the commit-commands plugin (see chapter 16). Without the plugin, just write "Commit with a conventional message" and you get the same result.
Minute 60, the wrap-up with /usage
One last habit before closing:
/usage
You see the estimated cost of the session, the breakdown by subagent, skill and MCP server, and the cache rate (the share of context reread for almost nothing instead of being reprocessed). Two things to look at:
- Is the review subagent heavy? Normal on a big diff. On a small fix,
/code-review lowis enough. - Did the cache rate drop? Often a model switch mid-session or a long break. Chapter 19 explains how to avoid it.
Then /clear before the next feature: it's free and Claude starts again from a clean context.
Timing summary
| Phase | Duration | Who |
|---|---|---|
| Brainstorm | 5 min | Claude suggests 3 options, you pick one |
| Planning | 10 min | Claude writes the plan, you approve |
| Execution | 25 min | /goal + auto mode, Claude codes 6 tasks |
| Testing + iteration | 10 min | You test and ask for adjustments |
| Review + commit | 10 min | /code-review, fix, commit, /usage |
| Total | 60 min | Complete feature: database + logic + UI + tests |
Question
Which /goal condition is most likely to succeed?
Pick an answer to see the explanation.
Key takeaways
- One hour for the database, the logic, the UI and the tests. You didn't type any code: you chose the approach, approved the plan and fixed the rendering.
/goalworks if its condition can be checked in the terminal (tests, typecheck)./code-reviewthen/usagebefore closing, and/clearbefore the next feature.