Lesson 7: Building a Full-Stack Quiz Platform — FastAPI, React, and One Docker Compose Stack

Hands On AI Engineering Course – AI Powered Quiz Implementation ~6 min read 60 min hands-on

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:

python

The Axios side mirrors the same boundary—routes never construct URLs with ambiguous trailing slashes:

typescript

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