AI-Assisted Development

Practical Workshop

Part 12: Hands-on — build a feature the right way

12 / 12 — Practical Workshop
AI-Assisted Development

We learn best by doing.

Let’s build something.

12 / 12 — Practical Workshop
AI-Assisted Development

What We’ll Build

Mini feature: Toggle “completed” on a Todo

New endpoint: POST /todos/:id/complete

  • If todo exists -> set completed = true, return 200
  • If todo doesn’t exist -> return 404
  • If already completed -> return current state (idempotent)

Why this feature?
Small enough to finish in one session. Rich enough to exercise the full workflow.

Stack: Express + TypeScript

Tiny in-memory Todo API at examples/express-todo-ts

src/
  models/todo.ts          # Type definition
  routes/todos.ts         # Route handlers (GET, POST)
  services/todoService.ts # In-memory store
tests/
  todos.test.ts           # Jest + supertest

Existing endpoints: GET /todos and POST /todos.
We’ll add the completion endpoint together.

12 / 12 — Practical Workshop
AI-Assisted Development

Setup

What you need:

  • Node 18+ installed
  • Cursor installed and logged in
  • Git + a local clone of the workshop repo
cd examples/express-todo-ts
pnpm install

Open the project in Cursor and notice:

  • Project structure: src/models, src/routes, src/services, tests/
  • No .cursorrules or AGENTS.md – AI has zero project-specific context

“There are no rules files. The AI doesn’t know our conventions. Keep that in mind as you review what it generates.”

12 / 12 — Practical Workshop
AI-Assisted Development

Step 1 — Explore (Ask Mode)

Open Cursor chat in Ask mode:

We're in the Express + TypeScript project at @examples/express-todo-ts.
Where is the Todo API implemented?
Please:
- List the main files (models, routes, services, tests).
- Summarize in 3-5 bullet points how it currently works.
Do not change any code yet.

What to notice:

  • Use @src and @tests to give context
  • Verify what AI says by reading the files it mentions
  • AI can summarize incorrectly — always check
12 / 12 — Practical Workshop
AI-Assisted Development

Step 2 — Design & Tests First (Plan Mode)

We want to add a feature to the Express + TypeScript Todo API:

- Endpoint: POST /todos/:id/complete
- Behavior:
  - If exists -> set completed = true, return 200
  - If not found -> return 404
  - If already completed -> return current state (idempotent)

Tasks:
1. Propose 3-5 Jest test cases for this behavior.
2. Write the test functions in the test file, matching existing style.
3. Stop after the tests — do not implement the endpoint yet.

Run pnpm test — they should fail. That’s the point.

12 / 12 — Practical Workshop
AI-Assisted Development

Step 3 — Generate Implementation (Agent Mode)

Once tests are failing:

Now implement the feature so that the new tests pass.

Constraints:
- Keep existing behavior of the Todo API unchanged.
- If you need to touch multiple files, list them first.
- Prefer small, focused changes.

Use either:

  • Inline edit (Cmd/Ctrl+K) inside route/service files
  • Composer / Agent mode for a multi-file change

Review the proposed changes before accepting:

  • Does it match the tests?
  • Are there edge cases missing?
  • Any security or performance issues?
12 / 12 — Practical Workshop
AI-Assisted Development

Step 4 — Review & Commit

Apply the edits and run the full test suite.

Review checklist:

  • All tests pass (old + new)
  • Implementation matches the spec
  • No unrelated changes crept in
  • No security issues (auth, validation, logging)
  • Could I explain this in a code review?

Commit small and descriptive:

git commit -m "test: add tests for POST /todos/:id/complete"
git commit -m "feat: implement todo completion endpoint"
12 / 12 — Practical Workshop
AI-Assisted Development

Refactoring Exercise

After implementing, review the AI-generated code. The AI likely put the logic directly in the route handler:

// Business logic in the route — works, but doesn't scale
todosRouter.post("/:id/complete", (req, res) => {
  const todo = listTodos().find((t) => t.id === id);
  todo.completed = true;
  return res.status(200).json(todo);
});

Prompt for refactoring:

Move the completion logic from the route handler into a
completeTodo(id) function in src/services/todoService.ts.
Keep route handlers thin. Keep tests passing.

Think about: Is the new structure easier to test? Easier for a new developer to understand?

12 / 12 — Practical Workshop
AI-Assisted Development

Reflection

What felt fast?
Boilerplate, test scaffolding, repetitive patterns.

Where did human judgment matter most?
Deciding the endpoint behavior. Reviewing the implementation and edge cases.

Which golden rules did we actually use?
Context-first, iterative, plan mode, tests first, mandatory review.

12 / 12 — Practical Workshop
AI-Assisted Development

Where would AI have gone wrong

if nobody reviewed the code?

12 / 12 — Practical Workshop
AI-Assisted Development

Optional Extensions

If you have more time:

Error handling & logging
Add structured logs to the new endpoint. Ask AI to propagate consistent logging across related routes.

Security checks
Require authentication for the /complete endpoint. Ask AI for potential security pitfalls in the new code.

Database migration
Replace the in-memory store with SQLite. See how the service-layer abstraction makes this easier.

Each extension reinforces the same core habits: think first, prompt with context, keep steps small, review everything.

12 / 12 — Practical Workshop
AI-Assisted Development

What We Practiced Today

The workflow
Ask -> Plan -> Agent -> Review

The habits

  • Context before code
  • Tests as the spec
  • Small, reviewable steps
  • Human judgment on every output

The mindset
AI accelerates the work — you own the decisions.

From writing code to owning the design.