Chapter 5: Feature Planning

Features are new user-facing capabilities where design choices matter. They're the heart of most software projects, and they're where the Jetty Method provides the most structure. Feature planning happens before any code is written. By the end of planning, you'll have a clear UX approach, a specification the AI will build to, and a breakdown of implementation work. This upfront investment prevents the drift and mystery box problems from Chapter 1. You know what you're building and why before implementation begins.

What Feature Planning Produces

Feature planning produces four things:

A chosen UX approach. There's more than one way to build most features. You'll consider options and pick one deliberately rather than letting the AI choose implicitly.

An integration contract. How do users reach this feature? What existing code needs to invoke it? Features can't be islands. The integration contract ensures your feature connects to the rest of the application.

BDD scenarios. The specification of what the feature should do, written in plain English. These become both the contract the AI builds to and the tests that verify it was built correctly.

Implementation chores. The feature broken into buildable pieces. Each chore addresses specific scenarios. This is the work that will flow through speed mode.

UX Exploration

Most features can be built multiple ways, and the user experience differs depending on which approach you choose.

Consider a login feature. You could build a simple inline form with email and password fields. You could build a multi-step flow where users enter email first, then password. You could build a unified form that handles both login and signup, switching based on whether the email exists. Each approach has tradeoffs. Each creates a different experience.

The Jetty Method has you explore options before committing. When planning a feature, propose two or three approaches.

For each one, consider:
  • ~What's the user experience like?
  • ~What are the advantages?
  • ~What are the drawbacks?
  • ~How complex is the implementation?

Then build quick prototypes. Code is cheap now. Use that. A working prototype tells you things a paragraph description never will. You'll feel the difference between approaches in a way that bullet points can't capture.

Prototyping also teaches your AI assistant. When the AI builds a rough version of each approach, it develops context about your codebase, your patterns, and your preferences. That learning carries forward. The final implementation becomes simpler because the AI has already explored the terrain.

Think of prototypes as horizontal learning before vertical building. You're not wasting effort. You're investing in clarity. The prototype you throw away still taught you something, and it taught the AI something too.

EXAMPLE PROMPT
I need to add user notifications to my app. Before we commit to an approach, let's explore options. Propose three different ways this could work from the user's perspective. For each one, tell me what the experience feels like, the advantages, the drawbacks, and roughly how complex it would be to build. After I see the options, I'll pick one or two to prototype.

The Integration Contract

Here's a failure mode that catches many builders: you build a feature, it works perfectly in isolation, but users can't reach it. The feature is an island, disconnected from the rest of the application.

The integration contract prevents this. Before writing scenarios, you define three things:

Entry point. How do users reach this feature? A URL they navigate to? A button they click? A menu item? A command they type? Be specific. "/login" or "the Sign In button in the header" or "the auth login command."

Caller code. What existing code needs to invoke or link to this feature? If there's a Sign In button, what file contains it? If there's a route, where is routing configured? This identifies what existing code needs to change.

Integration scenario. A BDD scenario that proves the feature is reachable. "Given I'm on the home page, when I click Sign In, then I see the login form." This scenario must pass before the feature is considered complete.

The integration contract forces you to think about how the feature fits into the whole. It also creates a clear verification point: if users can't reach the feature through the defined entry point, something is wrong.

EXAMPLE PROMPT
Before we write scenarios for this feature, let's define the integration contract. How will users reach this feature? What existing code needs to change to make it accessible? And what's a simple scenario that proves users can actually get to it?

Writing BDD Scenarios

With your approach chosen and integration defined, you write the specification.

BDD scenarios describe behavior in plain English using a structured format:

Scenario: User successfully logs in with valid credentials

Given I am on the login page

When I enter valid email and password

And I click the login button

Then I am redirected to the dashboard

And I see a welcome message with my name

Each scenario has three parts. Given establishes the starting state. When describes the user's action. Then specifies the expected outcome.

When writing scenarios for a feature, start with the integration scenario. This proves users can reach the feature. Then write scenarios for the core functionality, the things the feature must do. Then write scenarios for optional functionality, things the feature should do but that aren't strictly required.

Here's what you include during feature planning:

The integration scenario (how users reach the feature)

Success scenarios for required functionality

Success scenarios for optional functionality

Here's what you don't include yet:

Error handling (what happens when things fail)

Edge cases (unusual inputs, boundary conditions)

Security and performance concerns

Those come later, in stable and production modes. Feature planning focuses on getting you through speed mode. The scenarios describe what success looks like when everything goes right.

This might feel incomplete. You know there are error cases. You know edge cases exist. But handling everything at once is overwhelming, and it leads to the fragile implementations from Chapter 1. By deferring error handling to stable mode, you can focus on getting the core behavior right first.

The worst thing to find out after you've covered every edge case is that you made a dealbreaking high-level assumption about the UX or technical approach.

EXAMPLE PROMPT
Now let's write the BDD scenarios for this feature. Start with the integration scenario that proves users can reach it. Then write scenarios for the core functionality, followed by any optional features. Just the success paths for now. We'll add error handling and edge cases in stable mode.

Proposing Implementation Chores

With scenarios written, you break the feature into implementation chores. Each chore is a piece of work that addresses specific scenarios.

At minimum, one chore must be an integration chore. This is the work that wires the feature into the existing application, making the integration scenario pass. It modifies the caller code you identified in the integration contract.

Other chores address the functionality scenarios. A login feature might have:

Integration chore: Add Sign In button to header, create login route

Core chore: Implement login form with email/password fields

Session chore: Create and manage user sessions after successful login

Each chore should be small enough to complete in one work session. If a chore feels too big, break it down further. The goal is incremental progress with frequent verification.

The chores you create here flow into speed mode. Each one will be implemented, tested against its scenarios, and verified before moving to the next. By the end of speed mode, all your success scenarios pass. Then stable mode adds error handling, and the feature becomes robust.

EXAMPLE PROMPT
Based on the scenarios we just wrote, propose implementation chores for this feature. Make sure one of them is the integration chore that wires this into the app. Each chore should be small enough to finish in one session and should map to specific scenarios.

That's feature planning. You explore approaches, define how users reach the feature, write scenarios that specify behavior, and break the work into chores. The upfront investment pays off in clarity: everyone (you, the AI, the tests) agrees on what you're building before implementation begins.