Part 4: OpenAPI spec from the frontend
The service layer in frontend/src/services/ already lists the backend calls
the UI makes.
Before we create the backend, we use that code as the source for the first API spec. We write an OpenAPI file that the frontend and backend both agree on.
Writing the spec first makes the rest go smoother. It's easier to give the assistant a precise target than to make it infer the backend from the frontend code. We can iterate on the API while it's still cheap to change, before any code depends on it. And once it exists, every later disagreement between the two sides has one document to settle it.
Start the assistant
Start your coding assistant, which for me is Codex:
codex
I'm running inside a throwaway Codespace, so I start it in full-access mode with
the --yolo flag:
codex --yolo
This skips the per-action approval prompts and lets the assistant run commands on its own. It's convenient, but the assistant can then edit files and run anything without asking. Only use it in a disposable environment like a Codespace, never on a machine you care about.
It doesn't matter which assistant you use for this workshop, as long as it takes prompts in English and runs actions based on them. From here on, "the assistant" means whichever tool you started.
Generate the spec
Pointing the assistant means telling it which files to read and what to produce. We aim it at the services layer and ask for a spec at the repo root. We treat the frontend as canonical here: whatever it calls is what the backend must provide.
Use this prompt:
Read the frontend's API client in frontend/
Create openapi.yaml at the repo root that specifies the backend this frontend
expects: every endpoint, method, path, request body, response body, and which
endpoints need authentication
The assistant reads the client and writes openapi.yaml, covering the endpoints
the frontend already calls.
In my case, the endpoints look like this:
POST /auth/signup create an account, return a token (201)
POST /auth/login log in, return a token
GET /auth/me the current user (auth)
POST /auth/logout log out (auth)
GET /leaderboard top scores, filterable by mode + limit
POST /leaderboard submit a score (auth, 201)
GET /games/active active games to spectate
The two game modes show up as an enum, walls and pass-through, exactly as
the frontend uses them. Endpoints that change data on behalf of a user - submit
a score, read your own profile - are marked as needing a bearer token.
You can skip this step, but I find it worth the few minutes. Every interaction between the frontend and backend goes through this API, and it gets harder to change once both sides depend on it. The spec also saves tokens: when we want to change something, the assistant reads the agreed spec instead of reverse-engineering the frontend each time.
FastAPI later serves its own live version at /docs. We can diff that
against this file to confirm the backend matches, and from then on treat the
running FastAPI app as the ground truth.
Open the generated openapi.yaml to read every schema in full.
Commit the spec:
git add .
git commit -m "Add OpenAPI spec"
With the API spec written down, we build the backend that fulfils it in Part 5: FastAPI backend from the spec.