muningis.lt

I tried spec-kit so you don't have to

spec-kit
claude
ai

spec-kit is Github's implementation of Spec Driven Development toolkit.

What is Spec Driven Development?

Fancy way to describe it, would be to say that it's Natural Language Programming Language which gets transpiled to any (almost?) programming language. You define a Specification, describing how something should work, acceptance criteria.

Trying it out

I love having for-purpose animations in my presentations, more specifically, something what I've done in pretty much all of my presentations - code highlighting and transformation/morphing. This is relatively easy with Keynote, and they look really nice... until you've to change something which means I've to go through each slide containing that piece of code, and redo all the opacity (which I've to do colour by colour or rather AST token by token). I'm not much of a writer but I thought that one specific format might work nice for this - I describe a story, few comments, share relevant commands and output from Claude Code, and comment on that with links to commits.

Initialising a project

So, to try it out, I've decided I would try building custom Slides/Presentation tool using Claude Code + spec-kit. I followed setup guide and initialised project using specify init slides which I followed by entering Claude Code and running my first command - /speckit.constitution where Claude asked me some questions to clarify about the project.

 ● What is the official name of this project?
   → Slides
 ● What type of project is this and what are its core guiding principles? (Select all that apply)
   → Test-First Development, Type Safety, Simplicity First
 ● What technology stack constraints should be enforced?
   → typescript, bun for server-side routing and serving static files, react for client side, use these libraries: framer-motion, codehike, valibot
 ● How many core principles should the constitution define?
   → 7 principles
 ● Beyond Test-First, Type Safety, and Simplicity, which additional principles should be included to reach 7?
   → Performance First, Component Reusability, Code Review Required
 ● What is the development workflow for this project?
   → Trunk-based
 ● What quality gates should be enforced?
   → CI/CD Pipeline

And I let it commit it - # 962f7bb. And at that point I realised that I forgot to tell it to use tailwind for styling, so I ran /speckit.constitution use tailwind for styling and let Claude commit it - 4028236.

Stories & Specifications

To define a story (set of tasks) or rather specification you start with speckit.specify slash-command, e.g./speckit.specify Bootstrap a project. From there, you run speckit.clarify to allow your agent look if there's anything it needs to clarify, if not you can proceed with speckit.plan and speckit.tasks slash-commands.

Additionally, if you've gh (github-cli) installed, you can use speckit.taskstoissues slash-command to convert tasks into issues so you can keep track of them inside GitHub's repo.

Bootstrap a Project

First story, was to bootstrap a project, of course.

> /speckit.specify Bootstrap a project

⏺ Now I understand the context. This is a "Slides" project - a presentation software. The user wants to "Bootstrap a project" which means setting up the initial project structure and foundation. Let me write the specification.

/speckit.clarify

⏺ I've re-analyzed the spec. The planning phase has already been completed for this feature (plan.md, research.md, data-model.md, quickstart.md all exist). Running clarification post-pla n is valid but the spec is already well-defined.

/speckit.tasks

⏺ Tasks Generated

  Path: specs/001-project-bootstrap/tasks.md

  Summary

  | Metric             | Value   |
  |--------------------|---------|
  | Total Tasks        | 35      |
  | Setup Phase        | 5 tasks |
  | Foundational Phase | 9 tasks |
  | User Story 1 (P1)  | 6 tasks |
  | User Story 2 (P2)  | 5 tasks |
  | User Story 3 (P3)  | 4 tasks |
  | Polish Phase       | 6 tasks |

  Task Count by User Story

  | User Story | Priority | Tasks | Description                     |
  |------------|----------|-------|---------------------------------|
  | US1        | P1       | 6     | Developer Starts New Project    |
  | US2        | P2       | 5     | Developer Runs Quality Checks   |
  | US3        | P3       | 4     | Developer Builds for Production |

  Parallel Opportunities

  - Phase 1: T003, T004, T005 (config files)
  - Phase 2: T008-T010 (dependency groups), T011-T014 (config files)
  - Phase 3: T015-T017 (separate files)

  Independent Test Criteria

  | Story | Test                                                        |
  |-------|-------------------------------------------------------------|
  | US1   | bun install && bun dev → see welcome page at localhost:3000 |
  | US2   | bun run check → zero errors                                 |
  | US3   | bun run build → dist/ created, bun run preview → serves app |

  MVP Scope

  User Story 1 (6 tasks) delivers a working development environment where developers can:
  - Install dependencies with bun install
  - Start dev server with bun dev
  - See the application in the browser

  Format Validation

  All 35 tasks follow the required checklist format:
  - Checkbox prefix (- [ ])
  - Sequential Task IDs (T001-T035)
  - [P] markers for parallelizable tasks
  - [US1]/[US2]/[US3] labels for user story tasks
  - Specific file paths in descriptions

Then I also ran /speckit.taskstoissues which eventually told me to manually run ./specs/001-project-bootstrap/create-issues.sh - but total of 35 Issues were created so I guess I'm happy? At time of writing this, I'm unsure if I will continue using this functionality, but it was nice to explore. It was time to commit specification 4323fea and start the implementation. In total it took maybe around 15 minutes to bootstrap the project a1bab0f there was one missing functionality which I expected to exist - bun's server handling routing and static files, but as SWE who has complained enough about tickets and pushed them back due to lack of details, I will take the L here. I should have known better!

CI/CD

What kind of project does not have CI/CD which would prevent from faulty code getting merged into default branch? I don't have answer to that. This is quite straightforward task, so perhaps being extra explicit won't be needed?

> /speckit.specify setup github workflows to verify code quality and if it actually works.

⏺ Specification complete.

  | Item      | Value                                             |
  |-----------|---------------------------------------------------|
  | Branch    | 002-ci-workflows                                  |
  | Spec File | specs/002-ci-workflows/spec.md                    |
  | Checklist | specs/002-ci-workflows/checklists/requirements.md |
  | Status    | Ready for /speckit.clarify or /speckit.plan       |

  Summary:
  - US1 (P1): PR quality checks - typecheck, lint, tests run on every PR
  - US2 (P2): Build verification - production build runs on pushes to main
  - 8 functional requirements covering automated checks, status reporting, caching, and error messages
  - 4 success criteria focused on speed (<5 min), visibility, actionable errors, and caching benefits

> /speckit.clarify

⏺ No critical ambiguities detected worth formal clarification.

  The specification is well-defined for this CI workflows feature:

  | Category                            | Status |
  |-------------------------------------|--------|
  | Functional Scope & Behavior         | Clear  |
  | Domain & Data Model                 | Clear  |
  | Interaction & UX Flow               | Clear  |
  | Non-Functional Quality Attributes   | Clear  |
  | Integration & External Dependencies | Clear  |
  | Edge Cases & Failure Handling       | Clear  |
  | Constraints & Tradeoffs             | Clear  |
  | Terminology & Consistency           | Clear  |
  | Completion Signals                  | Clear  |
  | Misc / Placeholders                 | Clear  |

  Rationale: This is a straightforward CI/CD feature with:
  - Clear trigger events (PR open, push to main)
  - Well-defined checks (typecheck, lint, test, build)
  - Measurable success criteria (5 min completion, visible status, caching improvement)
  - Documented assumptions about existing commands (bun run check, bun run build)
  - Edge cases already addressed

> /speckit.plan

⏺ Planning complete.

  | Item       | Path                                 |
  |------------|--------------------------------------|
  | Branch     | 002-ci-workflows                     |
  | Plan       | specs/002-ci-workflows/plan.md       |
  | Research   | specs/002-ci-workflows/research.md   |
  | Quickstart | specs/002-ci-workflows/quickstart.md |

  Generated Artifacts:
  - plan.md - Technical context, constitution check (all PASS), project structure
  - research.md - Decisions on Bun setup, caching, triggers, job structure, error reporting
  - quickstart.md - Developer guide for using the CI workflows
  - CLAUDE.md - Updated with GitHub Actions context

  Constitution Check: All gates PASS. This feature implements the quality gates defined in the constitution (Type Check, Lint, Tests, Build).

> /speckit.tasks

⏺ Tasks generated.

  | Item        | Value                           |
  |-------------|---------------------------------|
  | Path        | specs/002-ci-workflows/tasks.md |
  | Total Tasks | 16                              |

  Task Breakdown by User Story:

  | Story    | Tasks | Description                    |
  |----------|-------|--------------------------------|
  | Setup    | 1     | Directory structure            |
  | US1 (P1) | 7     | PR quality checks (ci.yml)     |
  | US2 (P2) | 5     | Main branch builds (build.yml) |
  | Polish   | 3     | Verification                   |

  Parallel Opportunities:
  - T009 can run in parallel with US1 tasks (different workflow files)
  - Both user stories can be worked on in parallel after Setup completes

  Independent Test Criteria:
  - US1: Open a PR → verify typecheck, lint, test run and show status
  - US2: Push to main → verify build runs and shows status

  MVP Scope: User Story 1 only (PR quality checks) - delivers core value of enforcing code quality before merge

  Format Validation: All 16 tasks follow the checklist format with checkbox, ID, story labels (where applicable), and file paths.

Did not convert tasks into issues this time - even though It might be nice on bigger projects with bigger issues, where more human input is required but for now it's quite redundant. Pull Request #37 - only 64 really relevant LOC changes.

Defining architecture

Project is initialised, workflows on Pull Requests works, and it would seem that next logical step would be to finally start working on slides. But boy oh boy, there's still so many to do before. There's file structure, import boundaries to be defined... I learn my lesson from Boostraping project, so this time I went little bit more verbose with with specification description. Furthermore, I'm expecting clarify to ask me questions. This time, I also checked requirements.md just after specify - and boy, oh boy, there's No [NEEDS CLARIFICATION] markers remain statement - which means, that clarify is only needed if spec.md contains [NEEDS CLARIFICATION].

> /speckit.specify Define architecture for files and import boundaries. Consider, that there will be client code (responsible for slides engine) and server code (responsible for serving static files, rendering routes and serving .json of slides configuration). There should be generic agent rule file, which would then be used by Claude Code all the time when working with code. Avoid index.ts (barrel) files at any costs and anything else what would, might and will cause problems - think about those very carefully.

⏺ Specification complete.

  | Item      | Value                                                        |
  |-----------|--------------------------------------------------------------|
  | Branch    | 003-architecture-boundaries                                  |
  | Spec File | specs/003-architecture-boundaries/spec.md                    |
  | Checklist | specs/003-architecture-boundaries/checklists/requirements.md |
  | Status    | Ready for /speckit.clarify or /speckit.plan                  |

  Summary:
  - US1 (P1): Developer adds new code - clear placement rules, import violations caught by tooling
  - US2 (P2): AI agent works on codebase - reads rules file, follows conventions
  - US3 (P3): Developer reviews import graph - unidirectional dependencies, no cycles

  Key Constraints Documented:
  - No barrel files (index.ts) - prevents circular deps, improves tree-shaking
  - Explicit import paths (no directory imports)
  - Three boundaries: client, server, shared
  - Agent rules file for AI assistant guidance

> /speckit.plan

⏺ Planning complete.

  | Item       | Path                                            |
  |------------|-------------------------------------------------|
  | Branch     | 003-architecture-boundaries                     |
  | Plan       | specs/003-architecture-boundaries/plan.md       |
  | Research   | specs/003-architecture-boundaries/research.md   |
  | Quickstart | specs/003-architecture-boundaries/quickstart.md |

  Generated Artifacts:
  - plan.md - Technical context, constitution check (all PASS), project structure with src/client/, src/server/, src/shared/
  - research.md - Decisions on ESLint boundary enforcement, barrel file prevention, explicit imports, agent rules expansion
  - quickstart.md - Developer guide for using the architecture, import rules, common patterns
  - CLAUDE.md - Updated with architecture context

  Key Decisions:
  - Use eslint-plugin-import with no-restricted-paths for boundary enforcement
  - Forbid barrel files via ESLint no-restricted-syntax rule
  - Require explicit file extensions via import/extensions rule
  - Expand CLAUDE.md as the single source of truth for AI agents
  - Migration: move existing code to src/client/

At this point, this is something what I believe requires human input - even if it's still mere markdown files, I still prefer to review them. Nothing of issue I could find so I proceeded with creating tasks - which I also reviewed. Whether it will be smart enough to create .gitkeep files for empty directories - is question for future in 10 minutes (SPOILERT ALERT: it did not)

> /speckit.tasks

⏺ Tasks generated.

  | Item        | Value                                      |
  |-------------|--------------------------------------------|
  | Path        | specs/003-architecture-boundaries/tasks.md |
  | Total Tasks | 37                                         |

  Task Breakdown by User Story:

  | Story        | Tasks | Description                                             |
  |--------------|-------|---------------------------------------------------------|
  | Setup        | 4     | Create directory structure                              |
  | Foundational | 13    | Migrate code, configure ESLint boundary rules           |
  | US1 (P1)     | 5     | Developer documentation (README files, ARCHITECTURE.md) |
  | US2 (P2)     | 6     | AI agent rules (CLAUDE.md expansion)                    |
  | US3 (P3)     | 5     | Verify import boundaries work                           |
  | Polish       | 4     | Final verification                                      |

  Parallel Opportunities:
  - T002-T004 (different directories)
  - T007-T008 (different files during migration)
  - T019-T020 (different README files)
  - T029-T030 (different test boundary files)

  Independent Test Criteria:
  - US1: Developer can find correct file location within 30 seconds
  - US2: AI agent reads CLAUDE.md and places code correctly
  - US3: ESLint catches boundary violations, no circular dependencies

  MVP Scope: Phase 1 (Setup) + Phase 2 (Foundational) + Phase 3 (US1) - gives enforced boundaries and developer documentation

  Format Validation: All 37 tasks follow the checklist format with checkbox, ID, story labels (where applicable), and file paths.

It was time to commit and create PR and move on to next task.

Basic Server Side Code

At this point, it will start writing actual code and as we proceed, it will be writing more of it. As of writing this, my plan is to do make use of GitHub for code adjustments - I expect Claude to be able to use gh to react to review changes. At this point, I'm reviewing output after every step - specify, clarify (if needed), plan, tasks and implement. Unfortunately, so far there has been no need to clarify anything.

> /speckit.specify Create basic server side handler, which:
- serves static files
- has / (index) route - empty for now
- has /slides/:slug route - empty for now, in future will use :slug to render specific html file with injected JSON with specific slides
config

⏺ Specification Complete!

  Branch: 004-server-handler
  Spec File: /specs/004-server-handler/spec.md

  Checklist Results: All 16/16 items pass ✓

  Summary: The specification defines a basic server handler with:
  - US1 (P1): Static file serving - foundation for the application
  - US2 (P2): Root route / - placeholder home page
  - US3 (P3): /slides/:slug route - placeholder for future presentation rendering

  8 Functional Requirements covering static file serving, routing, security (path traversal prevention), and logging.

> /speckit.plan

⏺ Phase 0 & Phase 1 Planning Complete!   

  Generated Artifacts:
  - specs/004-server-handler/plan.md - Implementation plan with technical context and constitution check
  - specs/004-server-handler/research.md - Technical decisions (Bun.serve, static files, routing, security, logging)
  - specs/004-server-handler/quickstart.md - Developer quickstart guide
  - CLAUDE.md - Updated with new technology context

  Constitution Check: All gates PASS

  Summary of Technical Decisions:
  | Decision     | Choice                        |
  |--------------|-------------------------------|
  | HTTP Server  | Bun.serve() (no dependencies) |
  | Static Files | Bun.file() from dist/         |
  | Routing      | Manual string matching        |
  | Security     | Path validation               |
  | Logging      | Structured JSON to stdout     |

> /speckit.tasks

⏺ Tasks Generated!

  Output: /specs/004-server-handler/tasks.md

  Summary:
  | Metric                       | Value   |
  |------------------------------|---------|
  | Total Tasks                  | 32      |
  | Phase 1 (Setup)              | 5 tasks |
  | Phase 2 (Foundational)       | 4 tasks |
  | Phase 3 (US1 - Static Files) | 8 tasks |
  | Phase 4 (US2 - Home Route)   | 4 tasks |
  | Phase 5 (US3 - Slides Route) | 7 tasks |
  | Phase 6 (Polish)             | 4 tasks |

  Task Count per User Story:
  - US1 (Static Files): 8 tasks (3 tests + 5 implementation)
  - US2 (Home Route): 4 tasks (1 test + 3 implementation)
  - US3 (Slides Route): 7 tasks (2 tests + 5 implementation)

  Parallel Opportunities:
  - Phase 1: T002-T005 (directories)
  - Phase 3: T010-T012 (test files)
  - Phase 5: T022-T023 (test cases)

  Independent Test Criteria:
  - US1: Request /main.js, receive file with correct MIME type
  - US2: Navigate to /, receive 200 response
  - US3: Navigate to /slides/my-presentation, receive response with slug captured

  Suggested MVP Scope: Phase 1 + Phase 2 + Phase 3 (Setup + Foundational + Static File Serving)

  Format Validation: ✓ All 32 tasks follow checklist format (checkbox, ID, labels, file paths)

Pull request #39 was first one where I added comments. And this is where it gets interesting - up until now, quite often, if you wanted different/adjusted output, it used to be much more effective to revert the changes and adjust prompt with more explicit information - but now, it's enough to comment on specific line changes, and it will do the job!

> There are comments on PR. Please take a look and adjust.

⏺ Pushed commit 309ec29 addressing all PR comments:

  1. Builder pattern with path params - Routes now use .get("/slides/:slideSlug", handler) syntax
  2. .notFound() builder - 404 handling via .notFound(() => new Response(...))
  3. Automatic logging - logRequest is handled inside router.build(), removed from individual routes

  New main.ts routing:
  const router = createRouter()
    .get("/", handleIndex)
    .get("/slides/:slideSlug", handleSlides)
    .static("/")
    .notFound(() => new Response("Not Found", { status: 404 }));

  Bun.serve({ port, fetch: router.build() });

Slides

Last part I'm sharing here, but it will continue on. Here, we finally start actual implementation of Slides Engine, I expected it to finally have some clarification questions, but there was none. However, finally, during planing step it started using Search tool!

> /speckit.specify Let's start working on the slides.
  - it should have forward/backwards navigation
  - some slides might be multi-step, hence in configuration, it should define whether it goes step-by-step or not
    - for forward, default is step-by-step
    - for backward, default is whole slide back
  - slides should be headless for now, no styling
  - slide types:
    - Title
    - Title + subtitle
    - Title (optional) + text
    - Title (optional) + bullet points --> step by step
    - Title (optional) + code block --> it might have multiple code blocks, which are shown one after another. It should morph code
  from one into another, step by step. use codehike for codeblocks
     - Vertical timeline --> step by step
  - slide configuration should be in .json file, verified by valibot
  - animations should use framer-motion
  - we need state management - but for that we can use common Programming Design Patterns. Use those wherever we can!

⏺ Specification Complete!

  Branch: 005-slide-renderer
  Spec File: specs/005-slide-renderer/spec.md

  Summary:
  - 7 User Stories (2 P1, 4 P2, 2 P3)
  - 18 Functional Requirements
  - 7 Success Criteria
  - 7 Edge Cases identified

  User Stories:
  | Priority | Story                             |
  |----------|-----------------------------------|
  | P1       | Navigate Through Presentation     |
  | P1       | Load and Validate Configuration   |
  | P2       | Display Title Slides              |
  | P2       | Display Text Content Slides       |
  | P2       | Display Bullet Point Slides       |
  | P3       | Display Code Slides with Morphing |
  | P3       | Display Vertical Timeline Slides  |

  Checklist: All items pass ✓

> /speckit.plan

⏺ Planning Complete!

  Branch: 005-slide-renderer

  Generated Artifacts:

  | File                                   | Purpose                                                                                                         |
  |----------------------------------------|-----------------------------------------------------------------------------------------------------------------|
  | specs/005-slide-renderer/plan.md       | Implementation plan with technical context, constitution check, project structure                               |
  | specs/005-slide-renderer/research.md   | Technology decisions: Framer Motion patterns, CodeHike integration, State Machine + Observer + Command patterns |
  | specs/005-slide-renderer/quickstart.md | Developer quickstart guide                                                                                      |
  | CLAUDE.md                              | Updated with feature technologies                                                                               |

  Key Design Decisions:

  1. State Management: Custom FSM + Observer + Command patterns in src/shared/lib/navigation/ (no external library)
  2. Animations: Framer Motion with GPU-accelerated variants and AnimatePresence
  3. Code Highlighting: CodeHike with server-side highlight() function
  4. Validation: Valibot discriminated union schemas for slide types

  Constitution Check: All 7 principles PASS ✅

> /speckit.tasks

⏺ Tasks Generated!

  Path: specs/005-slide-renderer/tasks.md

  Summary

  | Metric         | Value                |
  |----------------|----------------------|
  | Total Tasks    | 61                   |
  | Phases         | 10                   |
  | Parallel Tasks | 29 (marked with [P]) |

  Tasks by User Story

  | Story        | Description                       | Priority | Task Count |
  |--------------|-----------------------------------|----------|------------|
  | US7          | Load and Validate Configuration   | P1       | 6          |
  | US1          | Navigate Through Presentation     | P1       | 11         |
  | US2          | Display Title Slides              | P2       | 5          |
  | US3          | Display Text Content Slides       | P2       | 4          |
  | US4          | Display Bullet Slides             | P2       | 5          |
  | US5          | Display Code Slides with Morphing | P3       | 7          |
  | US6          | Display Vertical Timeline Slides  | P3       | 6          |
  | Setup        | Infrastructure                    | -        | 5          |
  | Foundational | Core types/schemas                | -        | 4          |
  | Polish       | Cross-cutting concerns            | -        | 8          |

  MVP Scope (US7 + US1)

  - 17 tasks to reach functional navigation
  - Validates JSON, navigates slides, keyboard controls

  Independent Test Criteria

  | Story | How to Test Independently                                    |
  |-------|--------------------------------------------------------------|
  | US7   | Provide valid/invalid JSON files, verify validation messages |
  | US1   | Load presentation, use arrow keys to navigate                |
  | US2   | Create title slides, verify render                           |
  | US3   | Create text slides with/without title                        |
  | US4   | Create bullet slide, navigate to reveal items                |
  | US5   | Create code slide with multiple blocks, verify morphing      |
  | US6   | Create timeline, navigate to reveal events                   |

  Format Validated: All 61 tasks follow checklist format ✅

Everything worked quite fine except for actually rendering the slides in App.tsx file - but that was resolved relatively quickly, and final changes can be found #40. All in all, I would say this is definitely worth exploring, however it requires skill to write PRD (Product Requirement Documents) and Spec (Specification Documentation) - former describes what and why while later describes how. Even though Spec Driven Development is how focused, there's still PRD required to describes what part we are describing with how - after all, we can't say "fold nicely" without specifying that we're talking about rice when we describe a recipe, can we?