Lesson 7: Building a Full-Stack Quiz Platform — FastAPI, React, and One Docker Compose Stack
Most “full-stack tutorials” end with seven repos and seven ports. That is not integration—it is inventory. This project is a single AI quiz platform: a React + TypeScript SPA, a FastAPI backend, a composition core/ package, PostgreSQL and Redis behind one Docker Compose stack, and a nginx gateway that exposes one host port for APIs and another for the UI.
You will walk away with a repeatable pattern: curriculum topics (API client discipline, auth, CRUD, live sessions, analytics, error UX, E2E) operationalized as product workflows and learning sandboxes, without copying lesson folders into the runtime tree.
Runtime stack
System overview
The Lesson 7 Project separates how engineers learn from how users work.
The browser loads the SPA on port 3001. Same-origin requests hit /api/v1 through nginx, which proxies to the gateway and then to FastAPI. Product routes implement the real app: register, manage quizzes, run sessions, view analytics.
The core/ layer owns auth (JWT + passlib), Redis-backed cache with memory fallback, Gemini question generation, quiz CRUD, session persistence, analytics aggregation, and structured error envelopes. backend/app/ is the HTTP shell: routers, dependencies, middleware. Lesson directories in the parent monorepo are read-only references; behavior is reimplemented here.
Core composition: the engine layer
core/ is the integration engine. Product and learning handlers stay thin; they call services and return Pydantic-shaped responses.
Routers mount in main.py with redirect_slashes=False (avoids host-mismatch redirects behind nginx) and a lifespan hook that connects cache and seeds demo data when empty.
The frontend engine is not a framework—it is a thin composition of concerns: one Axios instance (normalizeUrl strips trailing slashes before requests), one auth provider (token in localStorage, attached on every call), and page components that own local UI state while delegating domain rules to the API. That split is what keeps “minimal frontend” honest: React renders and validates; Python scores and persists.
Product quiz generation delegates to the engine in one line of intent:
The Axios side mirrors the same boundary—routes never construct URLs with ambiguous trailing slashes:
Data flow through the stack
Keep going with the full lesson
The rest of this lesson — plus its implementation guide, runnable scripts and source code — is included with the course or an All Access plan. Create a free account to start the free lessons in every course.
Already a member? Sign in