A web application for tracking movies and series with community ratings, built with TypeScript, Node.js, Koa, React, and PostgreSQL.
- π¬ Browse and discover movies and series
- β Rate content (1-10 stars) and view community ratings
- π·οΈ Filter by genre tags and streaming platforms
- π OAuth2/OIDC authentication with PKCE (RFC 7636) and Google Sign-In
- π‘οΈ PKCE security - prevents authorization code interception attacks
- π Secure code verifier storage with automatic expiration and cleanup
- π₯ User approval workflow - new users require admin approval
- π§ Email notifications for new user requests
- π¨βπΌ Admin management: platforms, tags, and user approvals
- π Pagination (10 items per page)
- π "New to me" filter for recent additions
- π Secure session management with in-memory token caching
- Backend: TypeScript 5.7.2, Node.js 22.x LTS, Koa 2.16.1, PostgreSQL 16
- Frontend: React 18.2.0, TypeScript 5.7.2, TanStack Query 5.17.0, Vite
- Authentication: Keycloak (dev/staging), WorkOS (production)
- Testing: Jest 29.7.0 (backend), Vitest (frontend)
- Architecture: Domain-Driven Design (DDD) with CQRS pattern
- Node.js 22.x LTS or higher
- npm 10.x or higher
- Docker and Docker Compose (for local development)
- SMTP server credentials (for email notifications)
- Google OAuth credentials (for Google Sign-In)
# Install backend dependencies
cd backend
npm install
# Install frontend dependencies
cd ../frontend
npm installStart PostgreSQL and Keycloak:
# From repository root
docker-compose up -d
# Verify services are running
docker-compose ps
# Check logs (Keycloak takes ~30-60 seconds to start)
docker-compose logs -f keycloak# Backend environment
cd backend
cp .env.example .env
# Edit .env and configure:
# - KEYCLOAK_CLIENT_SECRET (see step 4)
# - SMTP settings for email notifications (see docs/EMAIL_SETUP.md)
# - ADMIN_EMAIL for receiving new user notifications
# Frontend environment
cd ../frontend
cp .env.example .env
# Default values should work for local developmentThe application uses OAuth2/OIDC authentication. Choose your environment:
For Local Development:
- Follow KEYCLOAK_SETUP.md for complete Keycloak configuration
- Includes Keycloak realm setup, client configuration, and Google Sign-In integration
For Production:
- Follow WORKOS_SETUP.md for WorkOS configuration
- Includes WorkOS organization setup, Google SSO connection, and deployment guide
Quick Start (Development):
# 1. Start Keycloak
docker-compose up -d
# 2. Follow docs/KEYCLOAK_SETUP.md to configure realm and client
# 3. Copy client secret to backend/.env
KEYCLOAK_CLIENT_SECRET=<your-client-secret-here>Note: Both guides link to the Google OAuth Setup for configuring Google Sign-In credentials.
cd backend
# Run migrations to create schema
npm run migrate
# (Optional) Seed sample data for testing
node scripts/seed-sample-data.ts# Terminal 1: Start backend (from backend/)
cd backend
npm run dev
# Backend will run on http://localhost:3000
# Terminal 2: Start frontend (from frontend/)
cd frontend
npm run dev
# Frontend will run on http://localhost:5173- Open the app: http://localhost:5173
- Click "Log In": You'll be redirected to Keycloak
- Log in with test user:
- Email:
[email protected]/ Password:admin123(admin user) - Email:
[email protected]/ Password:user123(regular user)
- Email:
- Verify authentication: You should see your name and "DEV" badge in the header
- Browse entries: Navigate to entries, add ratings, test filters
- Admin features ([email protected] only): Create/delete platforms and tags via
/adminpage - Click "Log Out": Session will be terminated
Once running, the backend API is available at:
- Health Check: http://localhost:3000/api/health
- Entries: http://localhost:3000/api/entries
- Authentication: http://localhost:3000/api/auth/*
- Admin endpoints: Require admin privileges (see AUTHENTICATION.md)
# Run tests
npm test
# Run tests in watch mode
npm test:watch
# Generate coverage report
npm test:coverage
# Build for production
npm run build
# Start production server
npm start
# Lint code
npm run lint
# Format code
npm run format# Run tests
npm test
# Run tests with UI
npm test:ui
# Generate coverage report
npm test:coverage
# Build for production
npm run build
# Preview production build
npm run preview
# Lint code
npm run lint
# Format code
npm run formatβββ backend/
β βββ src/
β β βββ domain/ # Domain entities and business logic
β β βββ application/ # Application services (Commands/Queries)
β β βββ infrastructure/ # External concerns (Database, WorkOS)
β β βββ ui/ # HTTP API (Koa)
β βββ tests/ # Unit, integration, and contract tests
βββ frontend/
β βββ src/
β β βββ components/ # React components
β β βββ pages/ # Application pages
β β βββ hooks/ # Custom React hooks
β β βββ services/ # API client
β βββ tests/ # Component and integration tests
βββ docker-compose.yml # Local development services
The project follows Test-Driven Development (TDD) with comprehensive test coverage:
- Unit Tests: Domain logic and business rules
- Integration Tests: Command/Query handlers and repositories
- Contract Tests: API endpoints with real database interactions
- Component Tests: React components (frontend)
# Backend tests
cd backend && npm test
# Frontend tests
cd frontend && npm test
# Backend tests with coverage
cd backend && npm test:coverageThe backend tests use a separate test database to avoid interfering with development data.
-
Create test environment file:
cd backend cp .env.test.example .env.test -
Initialize test database (one-time setup):
npm run test:db:setup
This will:
- Create the test database schema
- Seed pre-configured test users (regular user and admin user)
-
Run tests:
npm test
Test Database Configuration:
- Database:
movietrack_db_test(automatically created by docker-compose) - Pre-configured test users (UUIDs defined in
.env.test):- Regular user:
550e8400-e29b-41d4-a716-446655440000 - Admin user:
550e8400-e29b-41d4-a716-446655440001
- Regular user:
- Tests automatically setup and cleanup database state
Note: The test database is automatically created when you run docker-compose up. If you need to reset it:
npm run test:db:resetPostgreSQL database with the following schema:
- users: User accounts with OAuth2 identity and approval status
- entries: Movies and series with metadata
- ratings: User ratings (1-10 stars)
- genre_tags: Available genre categories
- streaming_platforms: Available streaming services
- entry_tags: Many-to-many relationship between entries and tags
The users table includes fields for the approval workflow:
approval_status: ENUM ('pending', 'approved', 'rejected')approval_requested_at: Timestamp when approval was requestedapproved_by: UUID of admin who approved/rejectedapproved_at: Timestamp of approval/rejection
The application uses OAuth2/OpenID Connect (OIDC) authentication with provider abstraction.
For detailed authentication architecture, see docs/AUTHENTICATION.md
Key Features:
- Provider-agnostic design (Keycloak, WorkOS, or Mock)
- PKCE (RFC 7636) - Prevents authorization code interception attacks
- Secure storage - SessionStorage with 5-minute expiration and automatic cleanup
- Google Sign-In integration
- User approval workflow with email notifications
- Secure session management with token caching
- Role-based access control (Admin/User)
PKCE Implementation (v1.6.0):
- β Cryptographically secure code verifier generation (256-bit entropy)
- β SHA256 code challenge derivation
- β One-time use with automatic cleanup
- β 5-minute expiration on stored verifiers
- β User-friendly error messages for storage issues
- β Full backward compatibility (PKCE is optional)
What PKCE Protects Against:
- Authorization code interception attacks
- Man-in-the-middle attacks during OAuth flow
- Malicious apps intercepting authorization codes
See docs/AUTHENTICATION.md for complete PKCE documentation.
| Environment | Guide | Description |
|---|---|---|
| Development | KEYCLOAK_SETUP.md | Local Keycloak configuration with Docker |
| Production | WORKOS_SETUP.md | WorkOS managed authentication setup |
| Google OAuth | docs/GOOGLE_OAUTH_SETUP.md | Google Sign-In credential setup (shared) |
| docs/EMAIL_SETUP.md | SMTP configuration for notifications |
| Role | Permissions |
|---|---|
| Pending | New users awaiting admin approval (limited access) |
| User | Browse entries, add ratings, create entries |
| Admin | All user permissions + approve users + manage tags/platforms |
- Follow TypeScript Constitution guidelines
- Write tests first (TDD)
- Use single quotes for strings
- Use
crypto.randomUUID()for UUIDs - Validate inputs with Zod at system boundaries
MIT