Kiro IDE: Creating a First Project — Part 2
From steering documents to a reviewed feature specification: requirements, technical design, and implementation tasks.
From project context to feature behavior
Part 1 established the project context through product.md, tech.md, and structure.md. This second tutorial follows the next stage: asking Kiro to specify the manufacturers screen, reviewing its output, and turning the agreed behavior into a technical design and task plan.
The application remains deliberately small: a responsive table showing manufacturer name, country, and vehicle types from the NHTSA vPIC API, with Previous and Next navigation. The intended deployment is a static website on shared hosting, with PHP available if a proxy proves necessary.
The deliverables for this stage are three documents. Application implementation and deployment are outside this tutorial’s scope.
| Artifact | Main responsibility | Review question |
|---|---|---|
requirements.md | User stories and acceptance criteria | Is the expected behavior clear and consistent? |
design.md | Architecture, state, request handling, and verification strategy | Can this design satisfy the requirements? |
tasks.md | Sequenced implementation and verification work | Can the work be executed and checked in manageable steps? |
1. Start a Requirements-First feature spec
In Kiro, start a new Spec, choose Feature, and select Requirements-First when prompted. This workflow progresses from requirements to design and then tasks. The exact presentation can vary by IDE version. Kiro Feature Specs documentation
Use a feature name that describes the capability, such as manufacturers-browser. The resulting documents for this session were placed under:
.kiro/
├── steering/
│ ├── product.md
│ ├── tech.md
│ └── structure.md
└── specs/
└── manufacturers-browser/
├── requirements.md
├── design.md
└── tasks.mdBegin with a bounded prompt. Request requirements first and reserve design and implementation for later review points:
Create a feature spec named manufacturers-browser for the single-screen
vehicle manufacturers application.
Read the existing steering documents in .kiro/steering/ and use them
as project context.
The screen should display manufacturer common name, country, and
vehicle types in a responsive table, fetching one page at a time
from the NHTSA API.
Begin with requirements and acceptance criteria in EARS notation.
Cover initial loading, Previous and Next navigation, missing names,
empty vehicle types, loading and error states, retry behavior,
accessibility, responsive presentation, and pagination boundaries.
Identify unresolved assumptions, including browser CORS access and
the previously recorded last-page value of 232. Propose how to
resolve them rather than treating them as verified facts.
Ask for clarification where needed. Stop after requirements.md
so it can be reviewed before proceeding to design.
Do not implement application code.The original session used this approach. Kiro reported reading the steering context, delegating requirements work, and refining the individual requirements before presenting the file. Those internal steps explain how the session proceeded; they do not establish that the resulting behavior is correct.
2. Review behavior across requirements
Kiro initially produced ten requirements covering the main screen behaviors. It used EARS notation, which expresses conditions and expected system behavior in structured criteria. Kiro documents this format as part of its feature-spec workflow. Requirements and EARS
An illustrative criterion for this application is:
WHEN a navigation request fails, THE App SHALL preserve the last successfully displayed results and offer a Retry action for the failed page.
Each criterion may appear sensible on its own. The important review is whether the criteria remain compatible when combined into a sequence of events.
The first reviews exposed several conflicts:
| Finding | Consequence | Resolution direction |
|---|---|---|
| Navigation allowed 30 seconds, but loading timed out after 10 seconds | One request had conflicting timeout rules | Define one REQUEST_TIMEOUT_MS value |
| Current Page changed before the request succeeded | The label could describe data not yet displayed | Separate displayed page from requested page |
| Loading cleared the table, but errors had to preserve it | Failed navigation could lose the visible results | Keep the last successful results while loading |
| Requested Page reset after failure | Retry could request the already displayed page | Store the failed target separately |
| Different sections controlled Next independently | Button state depended on which rule was applied last | Define one authoritative button evaluator |
For example, suppose page 2 is displayed and the request for page 3 fails. The correct result is still page 2’s table and label, plus a Retry action that requests page 3. A short event trace makes an incorrect state model easier to identify than another paragraph of general requirements.
Kiro’s format-validation messages were useful structural checks. They did not detect every behavioral contradiction found during review.
3. Consult the API contract before adding state
A major simplification came from checking the official NHTSA vPIC API documentation.
The Get All Manufacturers section documents 100-item pages and a page parameter, starting at page 1. It also offers an optional manufacturer-type filter, which remains outside this version’s scope. The documentation does not establish 232 as a permanent final page.
https://vpic.nhtsa.dot.gov/api/vehicles/GetAllManufacturers?format=json&page=1Earlier steering had recorded 232 as a known last-page value. Attempts to accommodate growth and shrinkage around that estimate introduced additional rules for totals, labels, and boundary confirmation.
The revised approach removed the fixed total from navigation. The label became simply Page N. Instead of presenting a total, the application would inspect each response and decide whether another request should be permitted.
| Observed response | Proposed application behavior |
|---|---|
| 100 records | Render the page and permit a request for the next page |
| 1–99 records | Render the page and record it as the last page under the boundary assumption |
| Empty next-page probe | Keep the displayed results and record the boundary |
| Failed request | Keep the displayed results and offer Retry |
A full page permits probing; it does not prove that a subsequent page contains data. The final page can contain exactly 100 records.
The session reported observing an empty response for page 233. That is an observation from the session, not a durable last-page guarantee. Treating partial or empty results as termination signals remains an application assumption to document and verify. The requirements explicitly retain a risk concerning unexpected empty pages within the dataset.
NHTSA also documents automated traffic controls. Fetching pages on demand avoids unnecessary bulk requests. NHTSA API reference and usage notice
4. Generate and inspect the technical design
After refining the requirements, request Generate Tech Design. Keep implementation deferred so the architecture can be reviewed as a separate artifact.
For this project, Kiro proposed a small static application:
index.html Page structure and controls
css/style.css Responsive presentation
js/app.js Requests, state, rendering, and interactions
proxy.php Conditional: required only if direct API access fails CORS checksThe JavaScript uses an IIFE to contain its variables. This is a simplicity choice for a single-file script; it should not be justified by an unverified claim that shared hosting cannot serve JavaScript modules.
The design introduces separate concepts for the displayed, requested, and failed pages:
| State | Meaning |
|---|---|
currentPage | Successfully displayed page; initially 0 before data loads |
requestedPage | Target of the active request |
failedPage | Target retained for Retry |
fetchInFlight | Whether a request is active |
lastPageKnown | Whether a boundary has been recorded |
lastConfirmedPage | Page associated with that boundary |
An implementation also needs the current response classification, or equivalent state, to evaluate whether probing is allowed. Requirements should describe these behaviors without implying that a particular variable count guarantees correctness.
Previous and Next must be evaluated independently. Shared overrides disable both while loading or before usable data exists. Otherwise Previous depends on whether the displayed page is greater than 1; Next depends on the recorded boundary and response classification.
Review backward navigation after boundary discovery. A full response from an earlier page must not erase a boundary discovered on a later page. The revised design limits invalidation to full responses at or beyond the previously recorded boundary.
5. Review the request lifecycle and data handling
The design review also changed the fetch pipeline. A timer originally ended when response headers arrived, leaving body consumption outside the intended timeout window.
The revised plan uses one outer try/catch/finally, keeping cancellation active through response-body reading and guaranteeing cleanup. AbortController can cancel both a fetch and consumption of its response body. AbortController documentation
Start request → mark loading → disable navigation
try:
Fetch the selected page
Check HTTP status
Read JSON while timeout remains active
Validate response structure
Apply the appropriate success or boundary transition
catch:
Retain the failed target
Preserve previously displayed results
Show error and Retry
finally:
Clear timeout
Release request-in-flight state
Recalculate navigation controlsParsing JSON successfully is not sufficient validation. The planned checks require a Results array, an integer Count between 0 and 100, and agreement between Count and the array length.
API field values must be inserted as text, using textContent, rather than interpreted as HTML.
One remaining policy was identified at the handoff: the generated design proposed silently skipping records with an invalid manufacturer name. That conflicts with displaying the returned records consistently. The recommended implementation policy is to treat invalid record structure as a recoverable response error and preserve the last successful results. This policy should be aligned in the spec before the relevant task is implemented; it was not verified through running code in this stage.
6. Generate an implementation plan with checks
With the requirements and design reviewed, request Generate Task List. The generated tasks.md organizes work into setup, HTML, CSS, JavaScript behavior, optional proxy work, integration checks, accessibility verification, and a final checkpoint.
The plan includes requirement references to connect tasks back to expected behavior. Those links make review easier, but should be checked after criteria are renumbered during revisions.
Several scenarios deserve explicit verification:
| Scenario | Expected observation |
|---|---|
| Initial request fails | Empty table, navigation disabled, Retry available |
| Next request fails | Displayed table and page label remain unchanged |
| Retry fails repeatedly | Each retry requests the same failed target |
| Full final page followed by an empty probe | Existing results remain visible; Next becomes disabled |
| Previous after boundary discovery | Earlier results load without discarding the later boundary |
| Response body stalls | Timeout exits loading and offers recovery |
| Malformed response structure | Recoverable error before replacing displayed data |
The empty-probe precondition matters: Next must be enabled on an unconfirmed full page. A test cannot start by clicking a disabled Next button on an already confirmed last page.
Use controlled fixtures or request mocks for rare responses. The live API alone cannot reliably produce every failure, timeout, and empty-dataset condition on demand.
7. Keep deployment assumptions as completion gates
Direct browser access to NHTSA remains an unresolved integration question until tested from the deployed origin. An agent’s successful server-side request does not establish browser CORS access.
The design uses a simple USE_PROXY switch. If direct access succeeds, the application calls NHTSA. If CORS prevents access, a same-origin PHP proxy must accept and forward the requested page number.
Proxy work is therefore conditionally required, rather than something that can always be skipped for a faster delivery. The task plan now prevents feature completion until the data-source decision is resolved and the selected path is verified end to end.
The existing PHP endpoint must not be assumed to support page forwarding merely because it returns manufacturer data. That behavior needs verification or implementation.
A practical review prompt
For a similar project, use this prompt after generating the spec documents:
Review requirements.md, design.md, and tasks.md together.
Trace initial load, navigation, failure, repeated retry, partial results,
and empty probes. Check that labels match displayed data, button rules
are independent, and failures preserve the last successful results.
Check that the timeout covers response-body reading, response validation
happens before UI state changes, and API values are rendered as text.
Separate documented API guarantees from observed behavior and assumptions.
Make conditional integration work mandatory when its condition applies.
Correct concrete inconsistencies, summarize the changes, and stop before
application implementation. Do not expand the feature scope.Review should lead to a usable implementation baseline. Repeated rewriting without concrete failing scenarios can add complexity of its own. After resolving the material issues, execute tasks incrementally and use the verification steps to test the proposed behavior.
Where Part 2 ends
The project now has a requirements document, a technical design, and an implementation plan. The most consequential change was removing a hardcoded page total after consulting the API reference. Other reviews clarified state transitions, retry behavior, timeout cleanup, and deployment gates.
These artifacts are a reviewed plan, not evidence that the application works. No application code was implemented or deployed during this stage, and browser CORS verification remains pending.
Part 3 can begin with project setup, semantic HTML, and responsive CSS, followed by JavaScript implementation in reviewed task groups. The specification provides the baseline; implementation and verification will determine whether it delivers the intended behavior.