Module 3

Greenfield Lab — SPECTRA from Scratch

Install SPECTRA, then take a small to-do app through Spec Kit’s full path — constitution to converge — stopping at every human gate. Feel the whole workflow in your hands before you point it at a real codebase.

Time 2 hours
Format Hands-on lab
Prerequisites Modules 1, 2; an AI agent; Node 18.18+; uv & Git

Learning objectives

By the end of this module, you will be able to:

  1. Install SPECTRA into a new project and confirm your AI agent can see the Spec Kit and SPECTRA commands.
  2. Run Spec Kit’s full path end to end on a small greenfield app: /speckit-constitution → /speckit-specify → /speckit-clarify → /speckit-plan → /speckit-checklist → /speckit-tasks → /speckit-analyze → /speckit-implement → /speckit-converge.
  3. Name the artifact each step produces and review it critically before moving on.
  4. Act at each human gate: answer clarify’s questions, tick the checklist yourself, and fix each analyze finding where it belongs.
  5. Recognize when the agent is making assumptions you should have specified explicitly.

What you'll build

A simple single-page to-do web app. Users can add tasks, see them listed, mark them done (and undo), and delete them. Tasks persist in the browser via localStorage — no database, no backend.

Tech stack, as create-next-app 15 scaffolds it:

This is small enough to finish in two hours, but real enough to require thinking about edge cases. It's also a mirror for Module 4, whose starter is a to-do app of the same shape on the same framework (it pins React 18 and Tailwind CSS 3; nothing in either lab depends on the difference).

The route

This lab runs Spec Kit’s full path: the core loop plus three optional quality gates — clarify, checklist, and analyze — which SPECTRA’s roster lists as add-ons. A feature this small could take the short path (specify → plan → tasks → implement → converge); you take the long way once so you know what each gate buys you.

Agents draft, people decide. Every step stops at a human gate, and in this lab every role at the gate is you. Feature artifacts land in specs/001-<name>/.

StepYou runIt producesHuman gate
2/speckit-constitution.specify/memory/constitution.mdFoundation — leads approve every standard
3/speckit-specifyspec.md, checklists/requirements.mdPlan — the product owner approves intent and scope
4/speckit-clarifyYour answers, written into spec.mdPlan — the product owner answers
5/speckit-planplan.md and supporting design filesDesign — architects approve the design
6/speckit-checklistchecklists/<name>.mdPlan, revisited — the reviewer ticks each item
7/speckit-taskstasks.mdImplement — engineers review the breakdown
8/speckit-analyzeA report; no file changesImplement — you decide what each finding means
9/speckit-implementCode; tasks ticked [X]Implement — engineers review every change
10/speckit-convergeNothing, or new tasks in tasks.mdImplement — you decide when it’s done
—/speckit-spectra-create-pr (offered)Nothing: you decline itDeploy — a maintainer merges
Two different “plans”.SPECTRA’s Plan phase turns a business ask into requirements and testable stories. The speckit.plan command belongs to the Design phase: it writes the technical plan.
A note on Git.Spec Kit doesn’t need Git: it tracks the active feature in .specify/feature.json, not by the branch you have checked out. create-next-app normally runs git init and makes one commit for you (--disable-git skips that); after that, this lab never asks you to commit. In real work, committing at each human gate is a cheap habit (Module 8). For numbered feature branches such as 001-todo-app, specify extension add git adds them — the active feature still comes from .specify/feature.json.

1.Setup (15 min)

1.1 Pick your AI agent

SPECTRA works with any coding agent Spec Kit supports — Claude Code, GitHub Copilot, Cursor, Gemini CLI, and many more. The course’s command examples use the Claude Code and Copilot trigger form; if your agent spells commands differently, see Module 1’s “Command spelling” note. If your team has mixed adoption, pair up: one person drives, one observes.

1.2 Scaffold the Next.js project

From a directory of your choice:

npx create-next-app@15 todo-app --typescript --tailwind --app --no-src-dir --no-eslint --turbopack --import-alias "@/*"
cd todo-app

The flags pre-answer the prompts (TypeScript, Tailwind, App Router, no src/, no linter, Turbopack, default import alias). If your version still asks something, accept the default. Then run npm run dev, open http://localhost:3000, confirm you see the Next.js welcome page, and stop the server with Ctrl+C.

1.3 Install SPECTRA

SPECTRA ships as a uv tool. Install it once, from anywhere:

uv tool install spectra-cli --from git+https://github.com/telus-digital/spectra

Run spectra on its own to verify: the banner’s cli vX.Y.Z line is your installed version. Bare spectra is informational only and never touches the current folder. (No uv or Git yet? The SPECTRA install guide has per-OS steps.)

spectra is a setup and lifecycle command, not a replacement for Spec Kit. The workflow you’re about to run is Spec Kit’s; SPECTRA puts it in place, keeps it current, and adds its own speckit.spectra.* agents on top.

1.4 Install SPECTRA into the project

From todo-app/:

spectra install

That one command:

  1. Installs Spec Kit’s specify CLI if it’s missing.
  2. Offers to initialize this folder as a Spec Kit project. Say yes: it runs exactly specify init --here --force — “here” is this folder, and --force lets it proceed in a folder that already has files. It may overwrite Spec Kit’s own managed files but doesn’t delete your app. When it asks for your coding agent, pick the one from 1.1.
  3. Registers the public SPECTRA catalog.
  4. Installs the SPECTRA extension.

Your project now has, alongside the scaffold (shown for Claude Code):

.specify/
  memory/constitution.md    # the constitution - a template until step 2
  templates/                # spec, plan, tasks, checklist, constitution templates
  extensions/spectra/       # the SPECTRA extension
.claude/skills/             # speckit-* and speckit-spectra-* skills

specify init infers nothing from your code; everything under .specify/ starts as a template.

Restart your AI agent.Commands are written to disk at install time, so an agent that was already running won't see them.

Then check the stack and see what’s on offer:

spectra version
spectra agent-list

spectra version reports every part of the stack. This course needs Spec Kit 1.0.9 or later; if yours is older, spectra update brings it current. spectra agent-list prints SPECTRA’s roster by SDLC phase, marking each agent core or add-on and saying whether Spec Kit or SPECTRA provides it. Today you use Spec Kit’s agents; the speckit.spectra.* ones are beyond this lab.

No SPECTRA?From step 2 on, everything except the pull-request offer in step 9 is plain Spec Kit. Install it with uv tool install specify-cli, then run specify init --here --force --integration claude in todo-app/ (specify integration list shows the other agents’ keys). Add --non-interactive for CI or agent harnesses, and --script sh|ps|py to pick the helper-script flavour.

1.5 Sanity-check the agent

Open your agent in todo-app/ and type /speckit. The command list should show speckit-constitution through speckit-converge, plus SPECTRA’s speckit-spectra-* agents. If not, restart the agent and check it’s running in todo-app/. (Don’t test with a bare /speckit-specify: without a description it just stops with an error.)

2.Write the constitution (10 min)

Human gate — Foundation.Architects and engineering leads approve every standard before the first feature. Here, that’s you.

The constitution holds project-wide standards that don't belong in any single spec. SPECTRA calls the agent that writes it Guardrails. It lives at .specify/memory/constitution.md and starts as a template. Give your standards to the command:

/speckit-constitution Record these standards for a single-page to-do app.

Stack
- Next.js 15 (App Router) with TypeScript; React 19 as scaffolded
- Tailwind CSS v4 for styling
- localStorage for persistence — no backend, no database, no API routes

Code organisation
- The page lives in app/page.tsx
- Components live in app/components/
- Storage helpers and shared types live in lib/storage.ts
- Components that use browser APIs or React state declare "use client"

Styling
- Tailwind utility classes only; no separate CSS files for layout
- app/globals.css keeps what the scaffold put there; add no new rules

Data
- A todo is { id: string, text: string, completed: boolean, createdAt: string }
- createdAt is an ISO 8601 string
- IDs come from crypto.randomUUID() (collision-safe, in all modern browsers)
- The localStorage key is one named constant in lib/storage.ts, never a
  repeated magic string

UI
- Single page, no routing
- An empty state when there are no tasks
- Newest task at the top of the list
- Completed tasks show a strikethrough; the row is not removed

Workflow
- Specs are spec-first: written before the code, not maintained afterwards
- No automated test suite in this lab; each user story is verified by hand
  against its acceptance scenarios

The agent maps your list onto the constitution template — named principles in MUST/SHOULD language, a version number, a governance section, and a Sync Impact Report comment at the top — and writes .specify/memory/constitution.md. (You can edit that file by hand instead; the command adds the structure and keeps dependent templates in step.)

2.1 Review it

This is short on purpose. The constitution should hold durable conventions, not the world. If something here turns out to be wrong later, you'll change it once and every future spec inherits the change.

Why are some specifics here?crypto.randomUUID() and a single named storage-key constant are decisions worth pinning at the project level so the agent doesn't reinvent them in every spec. The Module 4 starter follows neither, and you'll see there why that matters. The Workflow lines settle two things the agent would otherwise guess: how long the spec matters (spec-first, from Module 1) and whether to set up a test framework.

3./speckit-specify — the what and why (10 min)

Human gate — Plan.The product owner approves intent, scope, and business alignment. You’re the product owner.
/speckit-specify Build a single-page to-do app for one person keeping a short
personal list in their own browser. They can add a task, see all their
tasks in one list with the newest at the top, mark a task as done (and
undo that), and delete a task. Their tasks are still there after they
reload the page or come back later in the same browser. There are no
accounts, and nothing leaves the browser.

Notice what’s missing: Next.js, React, Tailwind, localStorage. specify is for the what and the why. The stack is already in the constitution, and the design belongs to /speckit-plan.

The agent creates a feature directory (for example specs/001-todo-app/), writes spec.md, and records the directory in .specify/feature.json as the active feature. It also creates checklists/requirements.md, a built-in spec-quality checklist whose items specify and clarify tick and untick themselves as the spec changes — read those ticks as the agent’s own claim, not a sign-off. If it hit a decision it couldn’t make, it may ask you up to three questions straight away. Answer them; the dialogue is part of the practice.

3.1 Review checklist

Don't accept the draft as-is. It has prioritised user stories with Given/When/Then acceptance scenarios, edge cases, numbered requirements (FR-001…), success criteria, and assumptions. Check it against the six-element framework from Module 2:

If any are weak, edit the spec directly or ask the agent: “The out-of-scope list is missing — please add at least four items based on what the constitution and the request imply.” If the draft names components or storage APIs, the how is leaking into the what; trim it.

Don’t re-run specify to fix the spec.Each /speckit-specify run starts a new feature directory (002-…) and makes it the active one. Refine this spec by editing it, by asking in chat, or with clarify next.

4./speckit-clarify — settle the open questions (10 min)

Human gate — Plan.Still the product owner’s call. The agent asks and recommends; you decide.
/speckit-clarify

Clarify scans the spec for gaps that would change what gets built and asks about the ones that matter most — at most five questions per pass, one at a time, each with a recommended answer and its reasoning. Reply with an option letter, “yes” to take the recommendation, or a short answer of your own. After each answer it writes the decision into spec.md: a Q → A line under a ## Clarifications heading, plus the change itself in the section it affects.

4.1 Decide before it asks

A thin to-do spec leaves these open. Have an answer ready for each; clarify will probably ask about some, and you should raise the rest.

If something is still open after one pass, run it again with a focus:

/speckit-clarify Focus on what the user sees when saving fails, and on very long task text.
  • Empty or whitespace-only input: nothing is added and no error is shown; text is trimmed before saving.
  • Completed tasks: stay where they are, struck through.
  • Editing: out of scope.
  • Length: 200 characters at most; the input accepts no more.
  • Delete: immediate, no confirmation.
  • Saving fails: the app keeps working for the rest of the visit and shows a short, non-blocking message that changes won’t be kept.

Yours can differ. What matters is that each is now a decision in the spec, not a guess in the code.

4.2 Check the answers landed

You stop iterating on the spec when a new engineer could implement the app from your spec without asking you anything. Not before.

5./speckit-plan — the how (15 min)

Human gate — Design.Architects approve the design and the decisions in it. You’re the architect.
/speckit-plan Build it on the stack the constitution sets out. Keep it small:
one page, three components, one storage module.

This is where implementation detail belongs. The agent writes plan.md — technical context, a Constitution Check against your standards, the project structure — plus supporting files beside it: research.md (decisions and why), data-model.md (the Todo entity), and quickstart.md (how to run and validate).

5.1 Review checklist for the plan

The plan should:

5.2 What the plan should not contain

If the plan is wrong, fix it before moving on. The cost of a wrong plan caught here is minutes. The cost of a wrong plan caught at /speckit-implement is potentially the whole afternoon.

5.3 SSR / hydration: the one gotcha to watch for

Next.js renders pages on the server first, then hydrates them in the browser. localStorage doesn't exist on the server. If the plan reads localStorage during the initial render, the client and server will produce different HTML and React will throw a hydration warning.

The right pattern: the page renders an empty initial state on first paint, then a useEffect hook reads localStorage after mount and updates state. The plan should call this out explicitly. If it doesn't, push back: “How does this avoid hydration mismatch when localStorage is read?”

This is the kind of stack-specific issue the constitution can't anticipate but the plan must.

6./speckit-checklist — unit tests for your requirements (10 min)

Human gate — Plan, revisited.You’re the reviewer signing off that the requirements are good enough to build from. The agent writes the questions; only you tick the boxes.
/speckit-checklist Focus on user-facing behaviour: empty states, input rules, and what happens when saving fails.

This checklist tests the spec, not the code: is each requirement complete, clear, consistent, measurable? The agent may ask up to three quick questions first, then writes checklists/<name>.md (ux.md, say) with every item unchecked. Something like:

- [ ] CHK001 Is the behaviour for whitespace-only input specified? [Edge Case, Spec §FR-003]
- [ ] CHK002 Is "newest at the top" defined for tasks added in the same second? [Clarity]
- [ ] CHK003 Is what the user sees when saving fails described? [Gap]

6.1 Review and tick — yourself

Work through the file with spec.md open beside it:

The agent never self-approves. You can ask it to help evaluate an item (“does the spec answer CHK003?”), but the tick is yours. Leave anything unticked and /speckit-implement will stop before it starts and ask whether to proceed anyway.

Two kinds of checklist.checklists/requirements.md is the built-in one: specify and clarify tick and untick its items themselves as the spec changes. Treat those ticks as the agent’s claim, not a sign-off, and challenge any you disagree with. The checklists /speckit-checklist generates are reviewer-owned: the command leaves every item unchecked, and only you tick them. Implement counts both.

7./speckit-tasks — break it down (5 min)

Human gate — Implement.Engineers review the breakdown before any code is written.
/speckit-tasks

The agent turns the plan into tasks.md: small, ordered tasks, each naming the file it touches, in phases — Setup (housekeeping, such as clearing the scaffold’s demo page), Foundational (what every story needs first: the Todo type, the storage key, load and save helpers), one phase per user story in priority order, and Polish (cross-cutting clean-up and final verification). Tests, when the spec asks for them, sit inside each story’s phase.

[P] marks a task that can run in parallel with its neighbours — different files, no dependency on unfinished work. [US1], [US2]… tag the story a task serves. During implement, finished tasks are ticked [X]. An excerpt might look like:

## Phase 3: User Story 1 - Add and see tasks (Priority: P1)
- [ ] T004 [P] [US1] Create the add-task form in app/components/TodoForm.tsx
- [ ] T005 [P] [US1] Create the list and row components in app/components/
- [ ] T006 [US1] Hold state in app/page.tsx; load after mount, save on change

7.1 Review checklist

7.2 Common defects

8./speckit-analyze — catch drift before you build (10 min)

Human gate — Implement.The report is advice. You decide what each finding means and where it gets fixed.
/speckit-analyze

Analyze reads the spec, plan, tasks, and constitution together and reports where they disagree: a requirement with no task, a task with no requirement, a plan choice that contradicts the spec, vague wording, one thing called two names. It is read-only — it never edits a file. You get findings graded CRITICAL, HIGH, MEDIUM, or LOW, a table mapping each requirement to its tasks, and an offer to suggest fixes it won’t apply on its own. Any conflict with the constitution is automatically CRITICAL.

8.1 Fix each finding in the step that owns it

The finding is about…Fix it in…
A requirement — missing, vague, or contradictoryThe spec: /speckit-clarify, or edit spec.md
The design — a plan choice that breaks the spec or the constitutionThe plan: /speckit-plan, or edit plan.md
The task list — a gap, an orphan task, a wrong orderThe tasks: re-run /speckit-tasks, or edit tasks.md

Patching tasks.md to cover a requirement problem just hides the disagreement. Fix the source and let the fix ripple (a changed requirement may mean re-running /speckit-plan or /speckit-tasks), then re-run /speckit-analyze. Repeat until it comes back clean: nothing CRITICAL, and any MEDIUM or LOW you leave is a call you made, not one you skipped.

  • The empty-state requirement has no task. Owner: the task list.
  • The plan generates IDs with Date.now(). A constitution conflict, so CRITICAL. Owner: the plan; regenerate the tasks after.
  • “Newest at the top” in the spec, “sorted by date” in the plan. Terminology drift. Owner: the plan.
  • The 200-character limit from clarify has no task. Owner: the task list.

Illustrative only. If your first run is clean, read the coverage table anyway.

9./speckit-implement — build it in stages (20 min)

Human gate — Implement.Engineers review every change. The agent writes the code; you read it and run it.

Before it writes a line, implement counts the boxes in every checklist under checklists/. If any are unticked, it shows a table and asks whether to proceed anyway. The honest answer is usually “no” — go back to step 6.

9.1 Scope each run

Don’t let it build everything in one go. Scoped runs are easier to review, and on large features they keep the agent inside its context window. Tell it where to stop:

/speckit-implement only execute the Setup and Foundational phases, then stop and report progress

Check the app still runs and the storage module follows the constitution. Then:

/speckit-implement only execute the User Story 1 phase, then stop and report progress

Continue one story at a time, then Polish. Task ranges work too (only execute tasks T001-T006). Finished tasks are ticked [X], so each run picks up where the last stopped. Verify each stage before you start the next.

9.2 Watch for these moments

9.3 The pull-request offer — decline it

After every implement run, SPECTRA’s after_implement hook offers /speckit-spectra-create-pr (“Open a pull request for this spec?”). Decline it here. Declining does nothing: nothing is checked, committed, or pushed. Accepting wouldn’t get far anyway — the command needs the gh CLI signed in and a GitHub remote, and this repository has none.

On a real project you’d accept once the feature is done — after converge reports Converged — with the repository on GitHub and the work on a feature branch. It still asks before every commit, push, and the pull request itself. That’s the Deploy gate: the agent opens the pull request; a maintainer decides whether it merges. You can always run /speckit-spectra-create-pr yourself later.

9.4 Run the app

Once the last phase is done, run npm run dev, open http://localhost:3000, and try:

  1. Add a task. Does it appear at the top of the list?
  2. Try to add an empty or whitespace-only task. Does the app do what you decided in step 4?
  3. Mark a task done, then undone. Does the strikethrough appear and disappear?
  4. Delete everything. Do you see the empty state?
  5. Add three tasks, refresh the page. Are all three still there?
  6. Open the browser devtools → Application → Local Storage. Is there a key matching the constant from your constitution? Does its value look like a JSON array of todo objects?

If any of these fail, you have a divergence between spec and code. Is the spec wrong (you didn’t specify what you actually wanted), or the code (the agent missed something the spec stated)? Whichever is wrong, fix that one. Then re-verify.

10./speckit-converge — close the gap (5 min)

Human gate — Implement.Converge proposes remaining work. You decide whether each item is real — and when the feature is done.
/speckit-converge

Run it once implement has worked through the current tasks.md. Converge compares the code with the spec, plan, tasks, and constitution, and summarises each gap as missing, partial, contradicts, or unrequested (code nobody asked for). Then it ends one of two ways:

Converge is append-only: it leaves your code alone, never removing a line, and never touches the spec or plan. Even unrequested code gets a task to review it, not a deletion.

/speckit-implement --> /speckit-converge --> Converged? -- yes --> done ^ | | | no +-------------- tasks appended --------------+

Read appended tasks before you implement them. If one traces to a requirement you no longer want, that’s a change to the spec, not a task to quietly skip. Then implement (decline the pull-request offer again) and converge again. Each pass should find less. When it says Converged, run the checks in 9.4 one last time.

11.Reflection (10 min)

Spend 10 minutes writing answers to these in a REFLECTION.md file in your project root. You don't need to share these with anyone, but writing them down is the difference between learning the practice and just executing the steps.

  1. Where did clarify ask about something you'd have left implicit — and what would the agent have assumed?
  2. What got caught at /speckit-plan review that would have been more painful to fix at /speckit-implement? (The hydration handling is the obvious candidate — was there anything else?)
  3. Which checklist items couldn't you tick honestly on the first read? What did you change?
  4. What did analyze find, and which step owned each fix?
  5. Did converge append anything? Did the agent invent scope anywhere, and how did you notice?
  6. Of the conventions in your constitution, which did the agent honor without prompting, and which did you have to reinforce?
  7. Which quality gates would you keep for a feature this size, and which for a production one? Overall, how does this compare to “just write a prompt and let the agent code”?

There's no right answer to any of these. The honest one is the useful one.

12.Common issues and how to handle them

“The agent's spec is way too long”

Edit it down. Spec Kit's default templates can be verbose, and some agents pad them further. The test from Module 2 still applies: if a sentence wouldn't change the agent's behavior, it doesn't belong. Stack details that leaked in from the constitution can go too — the plan picks them up anyway.

“The agent ignored my constitution”

Analyze and converge both treat a constitution conflict as their most severe finding, so these usually surface. If the agent still uses Date.now() despite the constitution, reference the rule explicitly in the plan (“Per the constitution, IDs use crypto.randomUUID()”) or re-prompt mid-implement. If your agent consistently ignores the constitution, that's a tooling-level concern worth raising on your team.

“The steps blur into each other”

Some agents will helpfully (or annoyingly) run several steps in one pass when a request is specific enough. Run the commands one at a time and review the artifact between each. The whole point of the workflow is the human gates.

“Clarify asked nothing”

It found no gaps it judged high-impact. If you know of an open question, name the area: /speckit-clarify Focus on delete behaviour and text length. Or write the decision into spec.md yourself.

“Implement stopped to ask about unchecked items” / “The agent ticked my checklist”

The stop is working as designed: finish the review in step 6 rather than answering “yes” out of habit. Ticks in checklists/requirements.md are expected — specify and clarify maintain them — but they’re the agent’s claim, so check them. Ticks in a checklist from /speckit-checklist should only ever be yours; untick anything you haven’t reviewed.

“The commands are working on the wrong feature”

You probably ran /speckit-specify twice, and the newer directory is now active. Open .specify/feature.json; it should read like {"feature_directory": "specs/001-todo-app"}. Point it back, or set the SPECIFY_FEATURE_DIRECTORY environment variable. Checking out a Git branch does not change the active feature.

“Converge keeps appending tasks”

Each pass should find less. If the same gap keeps coming back, the spec and the code disagree about something another implement pass can’t settle. Decide which one is right, and fix that one.

“I want to skip the quality gates”

You can. Only /speckit-specify is strictly required before /speckit-plan; clarify, checklist, and analyze earn their keep wherever there’s real ambiguity. For this lab, run them all. After the lab, decide for your team.

“The hydration warning won't go away”

The classic causes:

The fix in all three cases is the same: render a stable initial state on the server, then update once mounted. The plan should have called this out — if it didn't, that's a useful note for your reflection.


What you should now know

What's next

In Module 4 you'll take the same workflow into a brownfield codebase — the starter to-do app shipped with this course — and add a due date to it. The loop is the same; what changes is where the context comes from. Instead of writing standards before any code exists, you draw guardrails from code that already does, and you keep the first spec to one bounded change. It's the centerpiece of the course, and where most teams find SDD hardest.