Victor PereiraTechnical WritingsTutorial · Part 02

Kiro IDE: Creating a First Project — Part 2

From steering documents to a reviewed feature specification: requirements, technical design, and implementation tasks.

Kiro Part 2: requirements, design, and tasks linked in a specification workflow.
Three reviewable artifacts connect project intent to an implementation plan. Conceptual illustration.

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.

ArtifactMain responsibilityReview question
requirements.mdUser stories and acceptance criteriaIs the expected behavior clear and consistent?
design.mdArchitecture, state, request handling, and verification strategyCan this design satisfy the requirements?
tasks.mdSequenced implementation and verification workCan 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.md

Begin 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:

FindingConsequenceResolution direction
Navigation allowed 30 seconds, but loading timed out after 10 secondsOne request had conflicting timeout rulesDefine one REQUEST_TIMEOUT_MS value
Current Page changed before the request succeededThe label could describe data not yet displayedSeparate displayed page from requested page
Loading cleared the table, but errors had to preserve itFailed navigation could lose the visible resultsKeep the last successful results while loading
Requested Page reset after failureRetry could request the already displayed pageStore the failed target separately
Different sections controlled Next independentlyButton state depended on which rule was applied lastDefine 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=1

Earlier 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 responseProposed application behavior
100 recordsRender the page and permit a request for the next page
1–99 recordsRender the page and record it as the last page under the boundary assumption
Empty next-page probeKeep the displayed results and record the boundary
Failed requestKeep 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

Before: an unverified 232-page limit. After consulting API documentation: fetch one page, observe the response, and show Page N.
Consulting the API reference removed a hardcoded total and simplified pagination.

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 checks

The 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:

StateMeaning
currentPageSuccessfully displayed page; initially 0 before data loads
requestedPageTarget of the active request
failedPageTarget retained for Retry
fetchInFlightWhether a request is active
lastPageKnownWhether a boundary has been recorded
lastConfirmedPagePage 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 controls

Parsing 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:

ScenarioExpected observation
Initial request failsEmpty table, navigation disabled, Retry available
Next request failsDisplayed table and page label remain unchanged
Retry fails repeatedlyEach retry requests the same failed target
Full final page followed by an empty probeExisting results remain visible; Next becomes disabled
Previous after boundary discoveryEarlier results load without discarding the later boundary
Response body stallsTimeout exits loading and offers recovery
Malformed response structureRecoverable 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.