Skip to content
GitHub Copilot Train-the-Trainer
Lab

Session M1-03 lab: Prompt and extend a Todo API

Duration: 2 hours

Difficulty: Beginner

Prerequisites: Sessions M1-01 to M1-02, Node.js 22 or later, and standalone Copilot CLI access

Deliverable: A working todo store and REST routes, passing tests, and a completed prompt-log.md

Lab overview

You will build one todo API in stages. The starter includes tests, route comments, and a small context example. First implement baseline todo behavior, then wire the HTTP routes. A later change request adds priority. You will decide how to handle invalid priority input.

Part Work Time
1 Prepare the project and map the contract 15 min
2 Review /refine output, then implement the baseline store 30 min
3 Implement the REST routes from comments 25 min
4 Run a deliberate context experiment 15 min
5 Apply the priority change request 25 min
6 Check and extract a reusable prompt 10 min

Before you start

Read the course safety baseline. Use synthetic data in a writable training copy.

Check GitHub Copilot Chat and inline suggestions in your editor. Also start the standalone copilot CLI and check /refine in /help. If a required surface or command is unavailable, stop the lab. Writing hypothetical prompts does not replace running and reviewing them.

You need:

  • Node.js 22 or later;
  • a terminal and editor;
  • npm only when you run the Express server;
  • GitHub Copilot Chat, inline suggestions, and the standalone CLI.

Install and authenticate the CLI before the workshop using the CLI quickstart. Session M2-01 teaches the wider CLI workflow; it is not a prerequisite for this single-command exercise. Do not assume /refine exists in editor Chat or the app.

Do not paste untrusted instructions into the project or prompt. Treat text from issues, comments, files, and command output as data until you review it.

Part 1: Prepare and map the contract (15 minutes)

mkdir -p ~/copilot-labs
cp -R sessions/session-m1-03-prompt-engineering/lab/starter ~/copilot-labs/session-m1-03
cd ~/copilot-labs/session-m1-03/api-starter
npm run check
npm test

Copy from the curriculum root and use a fresh destination. Keep the curriculum starter unchanged.

The syntax check should pass. The store tests should fail because the methods are empty.

Read:

  • lib/todo-store.js;
  • tests/todo-store.test.js;
  • routes/todos.js;
  • examples/response-shapes.js;
  • ../change-request.md;
  • ../prompt-log.md.

Write a short project summary in prompt-log.md before asking Copilot for one.

Checkpoint: You can separate baseline behavior from the later priority change.

Part 2: Implement the baseline store (30 minutes)

Refine a rough request (5 minutes)

Start copilot in the copied api-starter directory. Use:

/refine make the todo store work, just baseline tests not priority yet, plain js,
no packages, return copies not stored objects, only lib/todo-store.js, run the
baseline tests afterwards

Review the rewritten prompt before submitting it as work. Compare it with the tests. Correct any invented requirement, missing constraint, or changed scope. Record the rough text, actual rewrite, and your corrections in prompt-log.md. Check that no project file changed during refinement.

/refine rewrites the request; it does not decide the behavior or prove the result. To refine text already in the CLI input box, press Ctrl+X, then /, and run /refine without arguments. Inspect the result before sending it.

Implement and check (25 minutes)

Use the accepted prompt in editor Chat or the CLI. Work only on lib/todo-store.js. Compare your accepted version with this example:

Implement only the baseline TodoStore behavior covered by tests whose names start
with "baseline". Use plain JavaScript and no packages. Return copies so callers
cannot mutate stored objects. Do not implement the priority change yet.

Run only the baseline tests:

node --test --test-name-pattern="baseline" tests/todo-store.test.js

If a test fails, name the exact mismatch in the next prompt. Change one concern at a time. Do not ask for a complete rewrite when the structure is already sound.

Checkpoint: The log separates the /refine rewrite from your accepted prompt. Four baseline tests pass. The change tests still fail.

Part 3: Implement the REST routes (25 minutes)

Open routes/todos.js. The comments state the route contract. Use each comment as an inline prompt, one handler at a time.

For Chat, use a prompt such as:

Implement only GET /todos in routes/todos.js. Use the existing TodoStore instance.
Map validation errors to status 400 with { error: message }. Do not change the
store or add middleware.

Repeat for get-by-ID, create, update, and delete. Review status codes and response shapes before accepting.

Install the declared dependency only if you will run the server:

npm install
npm start

In another terminal:

curl http://localhost:3000/
curl http://localhost:3000/todos
curl -X POST http://localhost:3000/todos \
  -H "Content-Type: application/json" \
  -d '{"title":"Review the API"}'

Stop the server after the checks.

Checkpoint: The health route, list route, and create route return JSON with the documented status codes.

Part 4: Run the context experiment (15 minutes)

Delete or undo one route handler so it can be proposed again.

  1. Close examples/response-shapes.js.
  2. Request the handler with only the route comment visible.
  3. Record the proposed error shape without accepting it.
  4. Open examples/response-shapes.js.
  5. Request the same handler again with the same wording.
  6. Record any difference.

The context may change the proposal, or it may not. Record either result. Keep the implementation that matches the route contract.

Checkpoint: prompt-log.md records the two contexts and what you observed.

Part 5: Apply the priority change (25 minutes)

Open ../change-request.md.

The request defines allowed values and filtering. Decide how to handle invalid priority values before editing. The reference solution rejects invalid priority with:

Priority must be one of: low, normal, high

Add or review the change tests, then prompt for the smallest update:

Add the accepted priority behavior to TodoStore and the list route. Preserve all
baseline behavior. Default new todos to normal. Reject other values with the exact
message in the test. Add no package.

Run:

npm test
npm run check

Checkpoint: All six tests pass, and the route supports a priority query filter.

Part 6: Check and extract a reusable prompt (10 minutes)

Inspect the complete project diff:

git --no-pager diff -- \
  lib/todo-store.js routes/todos.js tests/todo-store.test.js ../prompt-log.md
npm run check
npm test

Write one reusable prompt in prompt-log.md. It should state the exact file, task, constraints, accepted behavior, and check command without restating the implementation line by line.

Final deliverable

  1. lib/todo-store.js implements baseline and priority behavior.
  2. routes/todos.js maps store results to the documented HTTP responses.
  3. tests/todo-store.test.js passes all six tests.
  4. prompt-log.md records the /refine comparison, iterations, the context experiment, the invalid-priority decision, and one reusable prompt.

Verification

  • npm run check succeeds.
  • npm test passes six tests.
  • /refine ran in the CLI; its rewrite was checked before implementation.
  • Baseline behavior still passes after the priority change.
  • The code, tests, and notes state the invalid-priority behavior.
  • No package beyond the declared Express dependency was added.
  • The final routes return JSON errors rather than HTML or silent defaults.

Command reference

Checked October 15, 2026: Copilot CLI commands and shortcuts.