Areas we serve
Chapter 9

Capstone: Name the Stack

Read a generated booking app, then cut it down to an MVP.

Capstone objectives

  • Name every layer from a repository listing
  • Write the hosting requirements without guessing a brand of server
  • Separate “start here” from “upgrade when you know more”
  • Cut the generated app down to a single-page MVP on SQLite

The brief

Workshop Co. booking app — generated over a weekend

package.json
next, react, next-auth, @prisma/client. Scripts: dev, build, start.
prisma/schema.prisma
provider = "postgresql". Models: User, Class, Booking. Booking has a unique pair of user and class.
.env.example
DATABASE_URL, NEXTAUTH_SECRET, NEXTAUTH_URL. Values are empty.
.gitignore
Lists .env and .next.
Dockerfile
Present. The owner has never run Docker. There is no docker-compose.yml.
What works
npm run dev on the owner’s laptop, against Postgres installed by the tool. One test user. No domain.
Goal
The public can book a class at a real domain, over HTTPS, and the owner can sign in. The studio has a few dozen students, not ten thousand.

Part 1 — name the stack

Write one line for each layer: frontend, backend, database, and what the host has to keep running. Say what the Dockerfile changes and what it does not.

Model answer
  • Frontend: React pages served by Next.js.
  • Backend: Next.js on Node — the same process serves pages and the booking and login routes. next-auth is the login library. It needs NEXTAUTH_SECRET and NEXTAUTH_URL.
  • Database: PostgreSQL. Prisma is the library that talks to it. The unique booking constraint is what stops a double booking, if the app actually uses it.
  • Host: a machine that can run Node, run the production build, keep next start (or the Docker image) alive across reboots, and reach a Postgres server.
  • Dockerfile: it is a recipe for packaging the Node app. It does not provide Postgres, a domain, HTTPS, or the environment variables. Without a compose file, Docker is optional. Installing Node on a VPS is a valid way to run this same app.

Part 2 — what has to exist before the domain works

List the production pieces that are absent from the laptop demo. Keep them in the order you would actually do them.

Model answer
  1. A VPS (or equivalent) with Node.js, enough memory for the Next.js build, and a firewall that exposes 80 and 443 only.
  2. PostgreSQL, either on that server or as a separate database, with a user that is not a superuser, and a backup that has been restored once as a test.
  3. Environment variables set on the server: a real DATABASE_URL, a long random NEXTAUTH_SECRET, and NEXTAUTH_URL set to the public https:// origin.
  4. Prisma migrations applied to that database. Then a production build and a process manager so the app restarts on boot.
  5. A domain and DNS records (Book 1), then a TLS certificate (Book 2), with the proxy forwarding HTTPS to the app port.
  6. One real booking and one admin login tested from a phone that is not on the studio Wi-Fi.

Part 3 — what to ask, and what to skip

Write four questions you would send a host before ordering. Then write one upgrade you would not buy yet, and the signal that would change your mind.

Model answer

Ask: Can this plan run a long-lived Node process, or only PHP? Can Postgres run on it or beside it? Who applies security updates and restarts the process? Are backups of the database included, and have you restored one? Where does the server sit — a Canadian data centre is the right default for a studio collecting student names.

Do not buy yet: a large dedicated server, a second app instance, or a cache such as Redis. The studio has a few dozen students. A small VPS that fits Node and Postgres is the starting point. Upgrade when memory or CPU stays high during real class bookings, when the database disk grows, or when a restart causes missed reservations. Learn what the app uses first. The same server can be resized. You do not throw the first one away to find out.

Part 4 — the MVP cut

The studio has a few dozen students. Rewrite the stack as the first version you would actually launch. Name the frontend shape, the database, what you delete from the generated repo, and the signal that means SQLite is finished.

Model answer
  • Frontend: a single-page app. One shell for the class list, the reserve button, and the owner view. Deep links fall back to index.html.
  • Backend: one Node process with the booking and login routes. No second service.
  • Database: SQLite, studio.db on persistent disk, same tables Prisma already described. A nightly copy of the file is the backup. Postgres waits.
  • Delete for now: the unused Dockerfile, any Redis or payment code the model added, and the requirement to run a separate database server.
  • SQLite is finished when you need two app processes writing at once, or signups fail with “database is locked.” Then move the same tables to Postgres on the same server and resize. You learned the volume first.
Where to go next

If the words in part 2 felt thin, read Book 1 for DNS, Book 2 for HTTPS, and Book 8 before you add payments or a chat webhook. Book 9 is the one to read before you let a model answer students on the public site. This book was the map. Those are the streets.