This commit is contained in:
187
CLAUDE.md
Normal file
187
CLAUDE.md
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
# 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
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
ARG NODE_IMAGE_VERSION="22-alpine"
|
ARG NODE_IMAGE_VERSION="22-alpine"
|
||||||
|
|
||||||
# Install dependencies only when needed
|
# Install dependencies only when needed
|
||||||
FROM node:${NODE_IMAGE_VERSION} AS deps
|
FROM hub.diyla.com/node:${NODE_IMAGE_VERSION} AS deps
|
||||||
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||||
RUN apk add --no-cache libc6-compat
|
RUN apk add --no-cache libc6-compat
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
@@ -10,7 +10,7 @@ RUN npm install -g pnpm
|
|||||||
RUN pnpm install --frozen-lockfile
|
RUN pnpm install --frozen-lockfile
|
||||||
|
|
||||||
# Rebuild the source code only when needed
|
# Rebuild the source code only when needed
|
||||||
FROM node:${NODE_IMAGE_VERSION} AS builder
|
FROM hub.diyla.com/node:${NODE_IMAGE_VERSION} AS builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
COPY . .
|
COPY . .
|
||||||
@@ -25,7 +25,7 @@ ENV DATABASE_URL="postgresql://user:pass@localhost:5432/dummy"
|
|||||||
RUN npm run build-docker
|
RUN npm run build-docker
|
||||||
|
|
||||||
# Production image, copy all the files and run next
|
# Production image, copy all the files and run next
|
||||||
FROM node:${NODE_IMAGE_VERSION} AS runner
|
FROM hub.diyla.com/node:${NODE_IMAGE_VERSION} AS runner
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
ARG PRISMA_VERSION="6.19.0"
|
ARG PRISMA_VERSION="6.19.0"
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
---
|
---
|
||||||
services:
|
services:
|
||||||
umami:
|
umami:
|
||||||
image: ghcr.io/umami-software/umami:latest
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
environment:
|
environment:
|
||||||
@@ -18,7 +20,7 @@ services:
|
|||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
db:
|
db:
|
||||||
image: postgres:15-alpine
|
image: hub.diyla.com/postgres:15-alpine
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_DB: umami
|
POSTGRES_DB: umami
|
||||||
POSTGRES_USER: umami
|
POSTGRES_USER: umami
|
||||||
|
|||||||
Reference in New Issue
Block a user