Victor PereiraTechnical WritingsTutorial · Part 01

Kiro IDE: Creating a First Project — Part 1

Kiro IDE: Creating a First Project — product.md, tech.md, and structure.md.
Establish project context before implementation.

Establishing project context with product.md, tech.md, and structure.md before writing application code.

What are Kiro and spec-driven development?

Kiro is an AI-powered development environment that combines a familiar editor with an agent that can inspect a repository, investigate technical questions, propose decisions, and create project artifacts. My interest in trying it was to understand how those capabilities fit into a deliberate engineering workflow.

Spec-driven development (SDD) organizes development around explicit requirements, technical design, and implementation tasks. Instead of relying on a prompt alone to carry intent into code, the team creates reviewable artifacts that make expected behavior and decisions visible. Kiro supports this approach through its specification workflows. Kiro specs documentation

For my first experiment, I chose a small web application: one screen displaying vehicle manufacturers with pagination. A modest application would let me concentrate on the interaction with the agent rather than on application complexity.

This first article stops at the creation of three steering documents. I have not yet created the feature specification, implemented the screen, or deployed the application.

Steering establishes the project context

Before asking Kiro to implement a feature, I wanted to establish the context that should guide its decisions. Steering stores persistent project guidance in Markdown files under .kiro/steering/, reducing the need to repeat conventions and constraints in each conversation. Kiro steering documentation

The three documents in this experiment answer different questions:

DocumentQuestion it answers
product.mdWhat are we building, for whom, and within what scope?
tech.mdWhich technologies, integrations, and deployment constraints apply?
structure.mdHow should the project’s files and code be organized?

These are project guidance documents. The feature-specific requirements.md, design.md, and tasks.md belong to the next stage of the exercise.

Starting with a cloned repository

I installed Kiro, signed in, and opened my cloned repository, kiro_traffic.

Kiro’s initial inspection found only the .git directory. There was no application code, existing stack, or configuration to preserve. That is an important distinction from demonstrations where an agent generates steering by analyzing an established codebase: in this case, the context needed to emerge from investigation and conversation.

My original data source was an existing PHP endpoint on my website:

https://pereiravictor.com/traffic/getAllManufacturers.php

The endpoint uses data from the NHTSA vPIC API. The application would eventually run on my existing MochaHost account, so deployment capabilities also needed to influence the stack.

Giving Kiro a bounded first task

I asked Kiro to inspect the repository, investigate the endpoint, clarify hosting capabilities, and propose an approach before writing the steering documents.

The central instruction was:

Our first step is to establish project context and steering documents. Do not implement the application yet.

The prompt also asked Kiro to distinguish verified facts from assumptions, prefer a minimal stack, preserve existing work, and wait until decisions were agreed before creating the documents. It explicitly deferred application code and feature specification files.

This gave the agent a concrete assignment with a clear stopping point. I wanted it to investigate and propose solutions while keeping the decisions available for review.

The first response exposed a data question

Kiro inspected the repository and fetched my PHP endpoint. It identified a JSON response containing Count, Message, SearchCriteria, and a Results array.

The manufacturer records included these fields:

FieldRelevance to the planned screen
Mfr_CommonNameDisplay name; sometimes null
Mfr_NameFull name, usable as a fallback
CountryCountry value supplied by the API
VehicleTypesArray of vehicle-type objects; sometimes empty
Mfr_IDNumeric manufacturer identifier

The response contained 100 records. Kiro initially proposed fetching them once and dividing them into pages in JavaScript, with ten records per displayed page.

However, it also identified an unverified assumption: those 100 records might represent the complete dataset, or they might be only one page of a larger dataset. Seeing a successful response did not settle that question.

This became the most useful exchange in the session. The initial proposal was plausible for the observed payload, but it did not yet match my intended coverage.

Supplying the missing constraints

I clarified the hosting environment and the intended API usage:

  • My hosting account supports PHP and publicly accessible static files.
  • I do not have .htaccess access on my plan.
  • The interface should use a responsive table.
  • The displayed fields should be common name, country, and vehicle types.
  • Pagination should use 100 records per API page.
  • The application should call the NHTSA endpoint directly, using its page parameter.

I supplied this example:

https://vpic.nhtsa.dot.gov/api/vehicles/GetAllManufacturers?format=json&page=232

At the time of the session, I supplied 232 as the last page. Kiro subsequently reported observing 100 records on page 1 and 61 on page 232.

These observations supported changing the proposed approach to requesting one API page at a time. They should not be treated as a permanent guarantee that the registry will always contain 232 pages. Nor do observations of the first and last pages alone establish an independently verified total record count.

Kiro revised the approach

After the clarification, Kiro changed its proposal from locally slicing a single response to API-side pagination controlled by the browser.

Under the revised plan, clicking Next or Previous will trigger a new JavaScript fetch() request with the selected page number. NHTSA supplies the requested page of results; the browser renders it. This does not require a Node.js application server on my hosting account.

The proposed stack remained small:

  • HTML5 for the page and semantic table.
  • CSS3 for styling and responsive layout.
  • Vanilla JavaScript for requests, rendering, and pagination state.
  • An optional PHP proxy if direct browser access proves unsuitable.

There is no front-end framework, npm dependency, or build step in this proposal. Deployment is planned as a file upload to a public directory such as public_html/traffic/, using relative paths and avoiding a dependency on rewrite rules.

The three documents Kiro created

After the clarification exchange and file-change approvals, Kiro created:

.kiro/
└── steering/
    ├── product.md
    ├── tech.md
    └── structure.md

product.md: purpose and scope

The product document describes a single-screen application for browsing the NHTSA manufacturer registry without authentication.

It records a responsive table with common name, country, and vehicle types. When Mfr_CommonName is null, it proposes falling back to Mfr_Name. It also records Previous and Next controls and a current-page indicator.

Search, filtering, sorting, manufacturer detail pages, accounts, and local caching are outside this version’s scope. Writing those exclusions down helps prevent a small demonstration from expanding unintentionally.

tech.md: technology and integration decisions

The technology document records the minimal stack, the direct NHTSA endpoint, on-demand page requests, and the conditional PHP proxy.

It also captures deployment constraints: public-directory file upload, relative asset paths, and no reliance on .htaccess.

Importantly, it leaves browser CORS verification for implementation. A successful request from an agent’s fetching tool does not prove that JavaScript running on the deployed website can read the same response.

structure.md: the proposed application layout

The structure document proposes the following future application files:

kiro_traffic/
├── index.html
├── css/
│   └── style.css
├── js/
│   └── app.js
└── proxy.php          # Conditional

These application files were proposed, not implemented in this session. Only the steering documents were created.

The document also describes semantic table markup, pagination controls, loading and error messages, descriptive CSS classes, and JavaScript functions for fetching and rendering results.

Reviewing the output remains part of the work

The documents provide a useful baseline, but my first experience also highlighted details that deserve another review before implementation.

First, CORS remains unverified in the deployed browser environment. At one point the chat expressed more confidence about CORS than the final document supports. The implementation needs an actual browser test from the intended origin.

Second, 232 is recorded as a fixed last-page value. That captures the session’s working assumption, but the requirements should address how the application behaves when the upstream dataset changes.

Third, my original PHP endpoint was observed returning 100 records. The session did not establish that it can forward page requests. If a proxy becomes necessary, its pagination behavior must be verified or implemented rather than assumed.

Finally, some generated conventions are more restrictive than necessary: a proxy under 30 lines, no test files in version one, and wording that excludes subdirectories beyond css/ and js/ despite the existing .kiro/steering/ directory. These are review points, not qualities to preserve automatically. Likewise, the active PHP runtime should be confirmed if PHP becomes necessary; a compatibility number in a generated document does not establish the hosting configuration or its security suitability.

Follow along: establish your project context

This tutorial ends with three steering documents. You do not need a working application to complete this stage.

1. Prepare the workspace

Install Kiro, sign in, and clone or create your project repository. Choose File → Open Folder in Kiro and open the repository folder. Review its contents before starting.

2. Give Kiro the first task

Start a new chat. Describe the manufacturers screen, supply the endpoint, and explain the MochaHost deployment target. Ask Kiro to inspect the repository, investigate the API, and clarify hosting constraints before proposing a minimal stack. Request product.md, tech.md, and structure.md under .kiro/steering/ after agreement. Explicitly defer application code and feature specifications.

First establish the project context. Distinguish verified facts from assumptions, ask me to confirm the hosting capabilities you need, and propose the approach before creating the steering documents. Do not implement the application yet.

3. Clarify the decisions

Answer with your actual hosting capabilities and UI preferences. In my session, I confirmed static-file hosting, PHP availability, no access to .htaccess, a responsive table, and the direct NHTSA endpoint with its page parameter. I requested 100 records per page. Recheck the upstream pagination boundaries rather than assuming page 232 remains the last page.

4. Review the generated files

Review Kiro’s proposed changes before accepting them. Confirm the scope and stack, check assumptions about the endpoint, and keep browser CORS verification explicit. The proposed application layout describes future work; it does not mean those application files already exist.

5. Confirm the deliverable

  • All three steering files exist in .kiro/steering/.
  • The product scope matches the single manufacturers screen.
  • The technology choices fit your hosting account.
  • Unresolved integration questions remain visible.
  • No application code or feature specifications have been generated.

Review the files in Git and commit the agreed baseline when ready. The next stage is the feature specification.

Where Part 1 ends

I began with a cloned repository, an endpoint, and the idea of a paginated manufacturers screen. The session ended with three persistent guidance documents covering purpose, technology, deployment constraints, and proposed organization.

The experience included an initial assumption, my correction, additional investigation, and a revised plan. That interaction is central to how I want to use an engineering agent: give it room to investigate, supply the context it lacks, and review what it records before moving forward.

The next stage will use this baseline to create the screen’s requirements, technical design, and implementation tasks. For Part 1, the deliverable is the reviewed project context that will guide that work.