Where to go from here
We built the whole thing across the day. We wrote a React frontend and a FastAPI backend generated from an OpenAPI spec. We used SQLite for the local phase, then switched the containerized app to Postgres. We packaged it in a Docker Compose stack, deployed to AWS with CloudFormation, and added a CI/CD pipeline.
To keep the workshop to one day, we made the simplest choice at several points and left the harder version for later. Here's what to tighten, roughly in the order it matters once real users show up.
Security and secrets
Three security shortcuts in the workshop build need attention before this faces public traffic:
- Lock down CORS. The backend's CORS allow-list is set for local development.
Restrict it in
main.pyto the single domain you deploy the app to, so other sites can't call your API. - Persist sessions so logins survive deploys. Bearer tokens live in memory, so every restart or redeploy logs everyone out, which means you should store them or switch to signed stateless tokens.
- Keep credentials in a secret store. The database password already lives in AWS
Secrets Manager, and any other credentials belong there too, out of
.envfiles on the box, so you can rotate them without redeploying. On AWS the app is already served over HTTPS through CloudFront. On another host, put it behind a load balancer with a certificate or a reverse proxy like Caddy.
Data and scale
Two data choices keep the app small but limit how far it scales:
- Use a managed database. Postgres runs as a container on the same box as the app, so it shares that box's fate. Amazon RDS gives you backups, failover, and upgrades you don't have to run yourself.
- Add migrations. The app creates tables on startup, which is fine until the schema changes and you need to alter live data. Add a tool like Alembic so schema changes get versioned instead of applied by hand.
A bigger deployment
When a single instance stops being enough, a managed container host is the next step:
- Try a managed container host, since a single EC2 instance is the simplest thing that works but leaves you patching the server. AWS App Runner or ECS on Fargate with RDS removes that server, at the cost of a more involved CloudFormation template. Render, Railway, and Fly.io are simpler managed options to compare.
A real multiplayer game
One piece of the game still polls instead of streaming, and live updates need a push channel:
- Make spectating live. On the spectate page, the browser fetches active games over plain HTTP requests, so you only see new moves after you reload the page. To let viewers watch each move arrive on its own, add a push channel like WebSockets on both the backend and the frontend.
Each of these is a good next prompt for the assistant. Use the same workflow from the workshop. Describe what you want, name the file, and read the result against what you know.