PopChoice

Under the Hood

Every choice here was made to learn the parts that course projects skip: self-hosted vector search, background job pipelines, monorepo tooling, and containerized multi-service deployments. The decisions below explain the reasoning, not just the result.

Frontend

Next.js 16

Full-stack framework

Next.js 16 and the App Router provide the backbone of the application. Server components allow for streaming renders and layout-level data fetching, while full-stack TypeScript eliminates API contract drift.

The results page uses server components to fetch and stream movie data without client-side waterfalls — the UI renders progressively as recommendations arrive.

React 19

UI Library

React 19 concurrent features keep the quiz UI responsive during heavy async operations. The use of Actions simplifies form handling and state transitions throughout the application.

XState

State Management

The 5-question quiz is modeled as a formal state machine. This prevents illegal state transitions and provides a clear, predictable flow for the complex branching logic.

Using @xstate/react allows the UI to react to machine state changes, handling loading states and transitions with zero "if (loading)" spaghetti code.

Tailwind CSS 4

Styling layer

Utility-first styling with CSS custom property design tokens as the source of truth. Tailwind 4 generates classes dynamically, while tokens carry the semantic meaning for themes.

All theme-adaptive colors (light/dark mode) live in CSS custom properties. This means a single className can respond to the theme without JavaScript.

Motion

Animations

Formerly Framer Motion, this library handles all spring-based transitions and entrance animations, ensuring the UI feels "alive" and responsive to user input.

Lucide React

Icon Set

A clean, consistent icon library that is fully tree-shakeable and optimized for modern React environments.

AI + Data

OpenAI text-embedding-3-large

Taste encoding

Quiz answers are assembled into structured prompts and encoded into 3072-dimension vectors. This captures deep semantic meaning: "family dynamics" and "moral complexity" land near each other in embedding space.

The embedding request is the only AI call that blocks the user. Everything else runs asynchronously in background workers.

gpt-5.4-mini

Explanation generation

Generates personalized explanations for each recommendation. gpt-5.4-mini provides an exceptional balance of speed and reasoning quality for real-time applications.

At 6 explanations per quiz submission, using the full gpt-5.4 model would increase latency. The "mini" variant provides near-instant results.

PostgreSQL

Primary Movie Database

Serves as the central repository for 400+ curated films, metadata, and vectors. Storing everything in a single relational database simplifies data integrity and cross-referencing.

pgvector

Vector Search

A PostgreSQL extension that enables vector similarity search directly in our database. This avoids the overhead of managing a separate vector database like Pinecone or Weaviate.

Cosine similarity search finds the nearest neighbors to the user's taste vector with sub-100ms performance at scale.

Infrastructure

Redis

Data Store

Acts as the job store for our background tasks and the coordination layer for global rate limiting across our AI pipeline.

Redis ensures that even with multiple worker instances, we never exceed our OpenAI API token-per-minute or request-per-minute quotas.

BullMQ

Job Queue

Handles the heavy lifting of background job scheduling, retries, and failure recovery for the movie data backfill and discovery pipeline.

Coolify

Deployment Platform

Runs the production environment for our multi-service architecture on a VPS, orchestrating the Next.js app, worker services, PostgreSQL, and Redis through Docker Compose.

The repository is connected through Coolify, which deploys the monorepo to the VPS whenever production changes are shipped.

Turborepo

Build System

Manages monorepo builds with high-performance caching. It ensures that shared packages are built correctly before the apps that consume them.

Docker

Containerization

Ensures consistent environments from local development to production. Multi-stage Dockerfiles keep the final production images lean and secure.

Quality

Vitest

Testing Framework

A Vite-native testing framework that provides near-instant feedback during development. It handles unit and integration tests across the entire monorepo.

Playwright

E2E Testing

Ensures the critical path from quiz submission to movie recommendations works flawlessly across all modern browser engines.

Storybook

Component Lab

Allows for isolated development and testing of UI components, ensuring visual consistency and accessibility before they are integrated into the app.

MSW

API Mocking

Mock Service Worker intercepts network requests at the browser level, allowing the UI to be developed against realistic API responses without a live backend.