DEV Community

文生 张
文生 张

Posted on

Spec-first from seed to jack-o'-lantern: building Pumpkin Focus Timer with Kiro

This post is written as part of the Kiroween 2026 hackathon (#KiroweenHackathon26) — the Halloween-themed event on Devpost built around Kiro, AWS's agentic AI IDE. It's a build log of our project Pumpkin Focus Timer and, more importantly, an honest review of what spec-driven development actually felt like on a small, deadline-boxed project.

The project

Pumpkin Focus Timer is a zero-dependency Pomodoro-style web app with one hook: as you accumulate focused seconds during the day, a pumpkin grows through five stages — seed 🌰 → sprout 🌱 → small pumpkin 🎃 → big pumpkin 🎃 → glowing jack-o'-lantern 🎃✨. Finish a session and you get a spooky Web Audio chime and a celebration overlay. Daily stats persist in localStorage and reset at midnight.

How we used Kiro: spec first, code second

We deliberately avoided vibe coding and ran Kiro's full spec-driven workflow before touching implementation:

  1. requirements.md — user stories plus EARS-format functional requirements (WHEN/IF/THE SYSTEM SHALL). EARS forced edge cases into writing early: tab throttling, storage failures, midnight rollover.
  2. design.md — the state machine (idle → running → paused → completed), the endAt-timestamp timer model, the growth-stage data model with thresholds, and the audio autoplay strategy.
  3. tasks.md — a resumable task list that the implementation followed step by step.

The full spec ships in the repo under .kiro/specs/pumpkin-focus-timer/. The biggest win was reviewing requirements before code existed. EARS phrasing made gaps embarrassingly obvious — for example, nothing in the first draft said what "reset" should do to persistence, so we had to decide and write it down instead of leaving it undefined.

The honest part: where the spec didn't save us

We'll publish the bug we shipped because it's instructive: the state machine in design.md was correct, but the primary button handler only implemented pause and resume. The idle → running transition was in the spec and the design doc, yet the implementation missed it — pressing Start did nothing. It slipped because our spec review covered the documents, not the mapping between documents and code. A property-based test over the state machine (or a Kiro hook that lints every documented transition against a handler) would have caught it in one run. We fixed it, and the fix is part of the repo history.

Lesson: specs catch design gaps, but you still need automated checks that tie the spec to the code.

QA smoke mode, on purpose

The growth stages are driven by real focused seconds (300s for the first transition, 3600s for the glowing pumpkin), which is great for motivation and terrible for screen recordings. So we added a documented QA affordance: ?smoke=1 runs 15-second sessions with compressed thresholds. It's in the README, it's honest, and it made both automated QA and the demo video possible. The demo video shows normal mode first, then smoke mode for the full growth cycle.

What we learned about Kiro specifically

  • Spec review beats prompt iteration. Reading a requirements doc is faster than regenerating code three times.
  • The task list is a context anchor. Picking a project back up meant reading tasks.md, not reverse-engineering half-written code.
  • Write the spec you'd want to inherit. The EARS style felt bureaucratic until it caught three edge cases in one pass.

Kiroween runs through December 4 — if you've been curious about agentic IDEs, it's a good excuse to try Kiro on something small and spooky.

Happy shipping, and happy Halloween. 🎃

Top comments (0)