# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Umami is a simple, fast, privacy-focused alternative to Google Analytics. It's built with Next.js 15 (App Router), TypeScript, and supports multiple database backends (PostgreSQL, ClickHouse, Kafka). ## Development Commands ### Package Manager - Uses **pnpm** as the package manager (monorepo with `pnpm-workspace.yaml`) - Install dependencies: `pnpm install` ### Development - Start development server: `pnpm dev` (runs on port 3001 with Turbo) - Build application: `pnpm build` (runs multiple build steps including database setup) - Start production server: `pnpm start` - Build for Docker: `pnpm build-docker` ### Database Operations - Build Prisma client: `pnpm build-prisma-client` - Update database schema: `pnpm update-db` - Check database connection: `pnpm check-db` - Seed test data: `pnpm seed-data` - Change admin password: `pnpm change-password` ### Code Quality - Lint: `pnpm lint` (uses Biome) - Format: `pnpm format` (uses Biome) - Check (lint + format): `pnpm check` (uses Biome) - Test: `pnpm test` (uses Jest) - Cypress E2E tests: `pnpm cypress-run` or `pnpm cypress-open` ### Tracker Script - Build tracker script: `pnpm build-tracker` (rollup builds `/public/script.js`) - Update tracker: `pnpm update-tracker` ### Internationalization - Generate language files: `pnpm generate-lang` - Format language files: `pnpm format-lang` - Compile language files: `pnpm compile-lang` ## Architecture ### Tech Stack - **Frontend**: Next.js 15 (App Router), React 19, TypeScript, Tailwind CSS - **Backend**: Next.js API routes, Prisma ORM, multiple database support - **Database**: PostgreSQL (primary), ClickHouse (analytics), Kafka (event streaming) - **State Management**: Zustand, React Query (TanStack) - **Styling**: CSS Modules, Tailwind CSS, `@umami/react-zen` component library - **Code Quality**: Biome (linting/formatting), TypeScript, Jest, Cypress ### Key Directories - `src/app/` - Next.js App Router pages and API routes - `(collect)/` - Collection endpoints (pixels, links) - `(main)/` - Main application UI routes - `api/` - REST API endpoints - `src/components/` - React components - `common/` - Shared UI components - `charts/` - Data visualization components - `hooks/` - Custom React hooks - `src/lib/` - Utility libraries and shared logic - `src/tracker/` - Analytics tracker JavaScript (built to `/public/script.js`) - `src/styles/` - Global CSS and design tokens - `prisma/` - Database schema and migrations - `db/` - Database-specific schemas (PostgreSQL, ClickHouse) - `scripts/` - Build and utility scripts ### Database Architecture - **Primary Database**: PostgreSQL with Prisma ORM - **Analytics Database**: ClickHouse for high-volume analytics data - **Event Streaming**: Kafka for real-time event processing - **Cache**: Redis for session and data caching - Database type determined by `DATABASE_URL` environment variable - Queries use `runQuery()` helper that routes to appropriate database ### API Structure - RESTful API built with Next.js Route Handlers - Authentication via JWT tokens - Main collection endpoint: `/api/send` (handles analytics events) - Admin endpoints under `/api/admin/` - User/team management under `/api/me/`, `/api/users/`, `/api/teams/` - Website analytics under `/api/websites/[websiteId]/` ### Tracker System - JavaScript tracker at `/public/script.js` (built from `src/tracker/`) - Configurable via data attributes on script tag - Supports event tracking, page views, custom events - Can be hosted externally via `TRACKER_SCRIPT_URL` env var - Multiple script names supported via `TRACKER_SCRIPT_NAME` env var ### Environment Configuration Required environment variables: - `DATABASE_URL` - PostgreSQL connection string - `APP_SECRET` - JWT secret key Optional environment variables: - `CLICKHOUSE_URL` - ClickHouse connection for analytics - `KAFKA_URL` - Kafka connection for event streaming - `REDIS_URL` - Redis connection for caching - `CLOUD_MODE` - Enable cloud-specific features - `COLLECT_API_ENDPOINT` - Custom endpoint for tracker - `TRACKER_SCRIPT_NAME` - Alternative script names - `DISABLE_UI` - Disable web interface (API-only mode) ## Development Notes ### Database Setup 1. Set `DATABASE_URL` in `.env` file 2. Run `pnpm build` to create database tables and admin user (admin/umami) 3. For ClickHouse analytics, also set `CLICKHOUSE_URL` ### Testing - Unit tests: `pnpm test` (Jest with `src/lib/__tests__/`) - E2E tests: `pnpm cypress-run` (requires running application) - Test database: Uses separate test database configuration ### Code Style - Uses Biome for formatting and linting (configured in `biome.json`) - Line width: 100 characters - Single quotes for strings - Trailing commas in multiline objects/arrays - TypeScript strict mode enabled ### Build Process The `pnpm build` command runs multiple sequential steps: 1. `check-env` - Validate environment variables 2. `build-db` - Build Prisma client and database schema 3. `check-db` - Verify database connection 4. `build-tracker` - Build analytics tracker script 5. `build-geo` - Build GeoIP database 6. `build-app` - Build Next.js application ### Docker Deployment - Docker image includes standalone Next.js output - Uses multi-stage build for production optimization - Includes all necessary dependencies - Health check endpoint at `/api/heartbeat` ### Internationalization - Uses `react-intl` for translations - Messages extracted from `src/components/messages.ts` - Compiled to `public/intl/messages/` - Default locale: `en-US`, configurable via `DEFAULT_LOCALE` env var ## Common Tasks ### Adding a New API Endpoint 1. Create file in `src/app/api/[path]/route.ts` 2. Use `parseRequest()` helper for request validation 3. Use `runQuery()` for database operations 4. Return appropriate HTTP responses using helpers from `src/lib/response.ts` ### Adding a New Component 1. Create component in `src/components/` (organized by feature) 2. Use CSS Modules for styling (`*.module.css`) 3. Export TypeScript interfaces/types 4. Add to appropriate barrel file (`index.ts`) if needed ### Database Schema Changes 1. Update `prisma/schema.prisma` 2. Create migration: `prisma migrate dev --name description` 3. Update Prisma client: `pnpm build-prisma-client` 4. Update TypeScript types as needed ### Adding Tracker Features 1. Modify `src/tracker/index.js` 2. Rebuild tracker: `pnpm build-tracker` 3. Test with local development server ## Troubleshooting ### Database Connection Issues - Verify `DATABASE_URL` format: `postgresql://user:pass@host:port/db` - Check database is running and accessible - Run `pnpm check-db` to test connection ### Build Failures - Ensure all environment variables are set - Check Node.js version (requires 18.18+) - Clear `.next` cache if build issues persist ### Tracker Not Working - Verify script is loaded: check browser console - Check CORS headers if hosted on different domain - Test with `/api/send` endpoint directly