An app is not finished when it works on your machine
Throughout the track you have built the pieces separately: the frontend that consumes the API, the backend that serves it, the authentication, the tests, the CI, and the deployment. The capstone connects them into a single pipeline: the path your code travels from the moment you write the first line until a real user uses it.
IDEA
│
├─▶ BUILD frontend (React + fetch) + backend (REST API + data)
│
├─▶ TEST unit and integration tests (green before moving on)
│
├─▶ PACKAGE container (Docker): the app + its environment, identical everywhere
│
├─▶ AUTOMATE CI: on every push, install → test → build the image
│
├─▶ DEPLOY CD: if CI is green, publish the new version
│
├─▶ OBSERVE logs, metrics, health check, and alerts (is it still alive?)
│
└─▶ SECURE HTTPS, secrets out of the repo, input validation, auth
Each stage is a gate
What matters is not that the stages exist, but that each one is a gate: you do not move forward until the previous one is green. If the tests fail, CI stops and nothing gets deployed. If the container does not start, it never reaches production. That chain of gates is what turns "it works on my machine" into "it works in production, and I know it".
Build: a frontend and backend that respect a contract
The frontend requests data with fetch and renders it; the backend validates the input,
authenticates, and responds with the correct status code (201 on create,
400 if the input is invalid, 401 if authentication is missing). Both respect
the same contract: the same routes and the same shape of the data.
Package: the container
A container (Docker) packages your app together with its environment (Node version, dependencies, variables). That way the image that passes the tests in CI is exactly the one that runs in production: no more "it works on my machine".
Automate: CI as a safety net
CI runs, on every change, the same sequence: install dependencies →
run the tests → build the image. It is a pipeline of steps where, if one
fails, the following ones do not run. In the capstone you will model that pipeline with
a runPipeline(steps) function.
Observe: knowing it is still alive
Once in production, you need eyes: a health check (/health) that
responds "I'm alive", logs of what happens, metrics, and alerts that
warn you before the user notices the problem. Deploying without observing is
flying blind.