# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Niteshift Sandbox Status **This repository is running in a Niteshift sandbox with the following already configured:** ✅ **Dev server is ALREADY RUNNING** on http://localhost:3001 with hot reload enabled ✅ Database is set up and migrated (PostgreSQL) ✅ All dependencies are installed (pnpm) ✅ Environment variables are configured (.env file exists) ✅ Tracker script and geo database are built **Default credentials:** - Username: `admin` - Password: `umami` **You can start making changes immediately** - all changes will hot reload automatically! ### TL;DR - Start Prototyping Now ```typescript // 1. Access the running app // http://localhost:3001 (login: admin/umami) // 2. Make a quick UI change - edit any file in src/ import { Button } from '@umami/react-zen'; // Use component library import { useApi } from '@/components/hooks'; // Fetch data with React Query // 3. Save file - see changes instantly in browser! ``` **Most common tasks:** - **New page**: Create `src/app/(main)/[feature]/page.tsx` - **New component**: Add to `src/components/common/` - **Fetch data**: Use `useApi()` hook or pre-built query hooks from `src/components/hooks/queries/` - **Styles**: Use `@umami/react-zen` components (minimal custom CSS needed) ## Overview Umami is a privacy-focused web analytics platform built with Next.js 15, TypeScript, and PostgreSQL. It serves as an alternative to Google Analytics with a focus on simplicity and privacy. ## Tech Stack - **Framework**: Next.js 15 with App Router - **Language**: TypeScript (ES2022 target) - **Database**: PostgreSQL with Prisma ORM (supports optional ClickHouse for analytics) - **Package Manager**: pnpm - **UI Components**: React 19 with `@umami/react-zen` component library - **Data Fetching**: `@tanstack/react-query` (React Query) - **State Management**: Zustand stores - **Styling**: Minimal custom CSS (CSS Modules with PostCSS), primarily using component library - **Internationalization**: `react-intl` with custom `useMessages` hook - **Charts**: Chart.js with react-spring animations - **Build Tools**: Rollup (for tracker), Next.js with Turbo - **Testing**: Jest with ts-jest ## Useful Commands (Niteshift Sandbox) **Note:** The dev server is already running - you don't need to start it! ### Testing ```bash pnpm test # Run Jest tests ``` ### Code Quality ```bash pnpm lint # Run ESLint (optional - runs automatically on commit) ``` ### Database (if schema changes needed) ```bash pnpm build-db-client # Regenerate Prisma client after schema changes pnpm update-db # Apply new migrations ``` ### If You Need to Rebuild Assets ```bash pnpm build-tracker # Rebuild tracking script (rarely needed) pnpm build-geo # Rebuild geo database (rarely needed) ``` ## Rapid UI Prototyping Guide ### Quick Start for UI Changes **The dev server is already running on http://localhost:3001 with hot reload!** 1. **Make your changes** - Edit any file in `src/` 2. **View instantly** - Changes appear in browser automatically (no manual refresh needed) 3. **Component library**: Use `@umami/react-zen` for all UI primitives: ```typescript import { Button, Form, TextField, Modal, Row, Column } from '@umami/react-zen'; ``` 4. **Import path alias**: Always use `@/` for imports: ```typescript import { useApi } from '@/components/hooks'; import { formatDate } from '@/lib/date'; ``` ### UI Component Architecture #### Component Library (`@umami/react-zen`) The codebase uses a custom component library for UI primitives. Common components include: - **Layout**: `Row`, `Column`, `Container`, `Grid` - **Forms**: `Form`, `TextField`, `TextArea`, `Select`, `Checkbox`, `Toggle`, `SearchField` - **Buttons**: `Button`, `ActionButton`, `IconButton` - **Display**: `Modal`, `Dropdown`, `Menu`, `Tabs`, `Banner`, `Tooltip` - **Data**: `Table`, `List`, `Empty` **Example component usage**: ```typescript import { Button, Form, TextField } from '@umami/react-zen'; export function MyForm() { return (
); } ``` #### Custom Components (`@/components/common/`) Pages typically use a **mix** of `@umami/react-zen` components and custom components from `@/components/common/`. Common custom components include: - **Layout**: `PageBody`, `PageHeader`, `Panel`, `SectionHeader` - **Data Display**: `DataGrid`, `Empty`, `EmptyPlaceholder`, `LoadingPanel` - **Forms**: `ActionForm`, `ConfirmationForm`, `TypeConfirmationForm` - **UI Elements**: `Avatar`, `Favicon`, `FilterLink`, `LinkButton`, `Pager` - **Utilities**: `DateDisplay`, `DateDistance`, `ErrorMessage`, `ExternalLink` **Example**: Most pages combine both: ```typescript import { Column } from '@umami/react-zen'; import { PageBody, PageHeader, Panel } from '@/components/common'; export function MyPage() { return ( {/* Content */} ); } ``` #### Other Component Locations - **`src/components/input/`**: Input/button components (DateFilter, DownloadButton, WebsiteSelect, etc.) - **`src/components/charts/`**: Chart components (BarChart, LineChart, etc.) - **`src/components/metrics/`**: Analytics displays (MetricCard, StatsTable, etc.) - **`src/components/boards/`**: Dashboard board components ### Data Fetching Patterns #### Pre-built Query Hooks (Recommended) **Most common pattern**: Use existing query hooks from `src/components/hooks/queries/`. See `src/components/hooks/index.ts` for the full list of available hooks. ```typescript import { useWebsitesQuery } from '@/components/hooks/queries/useWebsitesQuery'; import { useReportsQuery } from '@/components/hooks/queries/useReportsQuery'; import { useUsersQuery } from '@/components/hooks/queries/useUsersQuery'; // In component: const { data: websites, isLoading } = useWebsitesQuery(); ``` Available query hooks include: `useWebsitesQuery`, `useUsersQuery`, `useReportsQuery`, `useTeamsQuery`, `useLinksQuery`, `usePixelsQuery`, `useRealtimeQuery`, `useWebsiteMetricsQuery`, `useWebsiteEventsQuery`, `useSessionDataQuery`, and many more. Check `src/components/hooks/queries/` for the complete list. #### Using the `useApi` Hook Directly For custom API calls or when a pre-built hook doesn't exist, use `useApi()`: ```typescript import { useApi } from '@/components/hooks'; import { useQuery, useMutation } from '@tanstack/react-query'; export function MyComponent() { const { get, post } = useApi(); // Option 1: Use with React Query hooks directly const { data, isLoading, error } = useQuery({ queryKey: ['custom-data'], queryFn: () => get('/custom-endpoint'), }); // Option 2: Direct API call (for mutations, form submissions, etc.) const handleSubmit = async (values) => { await post('/api/resource', values); }; return
{data?.name}
; } ``` **Note**: Most query hooks internally use `useApi()` with `usePagedQuery()` for pagination support. Prefer pre-built hooks when available. ### State Management #### Zustand Stores Global state is managed with Zustand stores in `src/store/`: ```typescript import { useApp } from '@/store/app'; import { setLocale, setTimezone, setUser } from '@/store/app'; // In component - read state const user = useApp(state => state.user); const locale = useApp(state => state.locale); // Update state setUser(userData); setLocale('en-US'); ``` Available stores: - **`app.ts`**: Global app state (user, locale, theme, timezone, dateRange) - **`dashboard.ts`**: Dashboard state - **`websites.ts`**: Websites state - **`cache.ts`**: Cache management - **`version.ts`**: Version checking ### Custom Hooks Essential hooks in `src/components/hooks/`: #### Data Hooks - **`useApi()`**: API wrapper with React Query integration - **`useConfig()`**: Get app configuration - **`useDateRange()`**: Date range management - **`useFilters()`**: Filter state management - **`usePagedQuery()`**: Pagination helper #### UI Hooks - **`useMessages()`**: Internationalization (i18n) messages and formatting - **`useLocale()`**: Current locale - **`useFormat()`**: Number, date, and value formatting - **`useMobile()`**: Mobile device detection - **`useNavigation()`**: Next.js navigation helpers - **`useEscapeKey()`**: ESC key handler - **`useDocumentClick()`**: Click outside handler #### Context Hooks These hooks provide access to React Context values for specific entities: - **`useUser()`**: Access current user context (from `UserProvider`) - **`useWebsite()`**: Access current website context (from `WebsiteProvider`) - **`useTeam()`**: Access current team context (from `TeamProvider`) - **`useLink()`**: Access current link context (from `LinkProvider`) - **`usePixel()`**: Access current pixel context (from `PixelProvider`) **Usage**: These hooks are typically used within components that are wrapped by their respective providers. For example: ```typescript import { useWebsite } from '@/components/hooks'; export function MyComponent() { const website = useWebsite(); // Returns website data from WebsiteProvider return
{website?.name}
; } ``` #### Example Usage: ```typescript import { useMessages, useFormat, useMobile } from '@/components/hooks'; export function MyComponent() { const { formatMessage, labels } = useMessages(); const { formatValue } = useFormat(); const isMobile = useMobile(); return (
{formatMessage(labels.welcome)} {formatValue(1000, 'number')}
); } ``` ### Internationalization (i18n) All user-facing text should use `useMessages`: ```typescript import { useMessages } from '@/components/hooks'; export function MyComponent() { const { formatMessage, labels } = useMessages(); return (

{formatMessage(labels.dashboard)}

{formatMessage(labels.description)}

); } ``` Messages are defined in `src/components/messages.ts` and compiled to JSON files in `public/intl/messages/`. ### Styling #### Approach - **Minimal custom CSS**: The codebase relies heavily on `@umami/react-zen` components for styling - **CSS Modules**: Use when custom styles are needed (`.module.css` files) - **Global styles**: `src/styles/global.css` and `src/styles/variables.css` - **CSS Variables**: Primary color customization via `--primary-color` #### Adding Custom Styles Only create CSS modules when absolutely necessary: ```typescript // MyComponent.module.css import styles from './MyComponent.module.css'; export function MyComponent() { return
Content
; } ``` ### Common UI Patterns #### DataGrid Pattern For lists with search, pagination, and actions: ```typescript import { DataGrid } from '@/components/common/DataGrid'; import { useWebsitesQuery } from '@/components/hooks/queries/useWebsitesQuery'; export function WebsiteList() { const query = useWebsitesQuery(); return ( } > {(row) =>
{row.name}
}
); } ``` #### Form Pattern Standard form with validation: ```typescript import { Form, TextField, Button } from '@umami/react-zen'; import { useApi } from '@/components/hooks'; export function MyForm() { const { post } = useApi(); const handleSubmit = async (values) => { await post('/api/resource', values); }; return (
); } ``` #### Modal Pattern ```typescript import { Modal, Button } from '@umami/react-zen'; import { useState } from 'react'; export function MyComponent() { const [showModal, setShowModal] = useState(false); return ( <> {showModal && ( setShowModal(false)}>
Modal content
)} ); } ``` ### Page Structure Pages in `src/app/(main)/` follow this pattern: ```typescript 'use client'; // Required for interactive components import { useMessages } from '@/components/hooks'; import { Button } from '@umami/react-zen'; export default function MyPage() { const { formatMessage, labels } = useMessages(); return (

{formatMessage(labels.title)}

{/* Page content */}
); } ``` **To view your new page:** Navigate to http://localhost:3001/your-route (server is already running!) ### Tips for Rapid Prototyping in Niteshift 1. **Zero setup needed**: The dev server is running, database is ready, just start coding! 2. **Instant feedback**: Hot reload is active - save a file and see changes in <1 second 3. **Leverage existing components**: Check `src/components/common/` and `src/components/input/` before creating new components 4. **Use query hooks**: Don't write custom API calls if a query hook exists in `src/components/hooks/queries/` 5. **Follow established patterns**: Look at similar pages/components for consistent patterns 6. **Internationalization**: Always use `useMessages()` for text, never hardcode strings 7. **TypeScript**: Leverage type inference - the codebase has strong typing 8. **Component library first**: Always check if `@umami/react-zen` has what you need before writing custom UI ## Project Architecture ### Directory Structure - **`src/app/`**: Next.js App Router pages and API routes - `src/app/(main)/`: Main application pages (authenticated area) - `src/app/(collect)/`: Analytics data collection endpoints - `src/app/api/`: REST API routes (admin, auth, teams, websites, reports, etc.) - `src/app/login/`, `src/app/logout/`, `src/app/sso/`: Authentication pages - `src/app/share/`: Public sharing pages - **`src/lib/`**: Core utility functions and shared logic - Database utilities (`db.ts`) - Authentication (`auth.ts`) - Request/response helpers (`request.ts`, `response.ts`) - Date utilities (`date.ts`) - Constants (`constants.ts`) - IP detection (`ip.ts`) - Device detection (`detect.ts`) - Formatting utilities (`format.ts`) - **`src/queries/`**: Database query layer - `src/queries/prisma/`: Prisma queries for PostgreSQL - `src/queries/sql/`: Raw SQL queries (organized by feature: events, pageviews, sessions, reports) - **`src/components/`**: React components - `src/components/common/`: Shared UI components - `src/components/input/`: Form input components - `src/components/charts/`: Chart components - `src/components/metrics/`: Analytics metric displays - `src/components/boards/`: Dashboard boards - `src/components/hooks/`: Custom React hooks - `src/components/svg/`: SVG icon components (generated by `pnpm build-icons`) - **`src/tracker/`**: Client-side tracking script source code - **`src/permissions/`**: Authorization and permission checks - **`src/store/`**: Zustand state management stores - **`src/generated/prisma/`**: Auto-generated Prisma client (DO NOT edit manually) - **`prisma/schema.prisma`**: Prisma schema definition - **`scripts/`**: Build and utility scripts - `check-db.js`: Database connection verification - `build-geo.js`: GeoIP database setup ### API Architecture API routes follow Next.js App Router conventions with `route.ts` files. Standard pattern: 1. Request parsing with `parseRequest()` from `@/lib/request` 2. Authentication via `checkAuth()` (can be skipped with `skipAuth: true`) 3. Schema validation using Zod 4. Database queries via Prisma or raw SQL 5. Response formatting via helpers from `@/lib/response` Example: ```typescript export async function GET(request: Request) { const { query, auth, error } = await parseRequest(request, schema); if (error) return error(); // ... business logic return json(data); } ``` ### Database Query Pattern The codebase supports multiple database backends through `runQuery()` in `src/lib/db.ts`: - **Prisma queries** (in `src/queries/prisma/`): Used with PostgreSQL - **Raw SQL queries** (in `src/queries/sql/`): Direct SQL for complex analytics - **ClickHouse queries**: Optional high-performance analytics backend Use `runQuery()` with object containing query implementations for each backend: ```typescript return runQuery({ [PRISMA]: () => prismaQuery(), [CLICKHOUSE]: () => clickhouseQuery(), }); ``` ### Environment Variables **In Niteshift:** The `.env` file is already configured with `DATABASE_URL` and any required variables. See `next.config.ts` for full list of available environment variables. ### Key Data Models Core entities in `prisma/schema.prisma`: - **User**: User accounts with authentication - **Team**: Organizations/teams - **Website**: Tracked websites - **Session**: User sessions with device/location data - **WebsiteEvent**: Individual events/pageviews - **Report**: Custom analytics reports - **Link**: Short links (link tracking feature) - **Pixel**: Tracking pixels ## Important Notes for Niteshift Development ### TypeScript Configuration - Module resolution: `bundler` - Path alias: `@/*` maps to `src/*` - Strict mode enabled (except `strictNullChecks`) - Target: ES2022 - Types are checked automatically - errors show in editor ### Testing - Unit tests in `src/lib/__tests__/` using Jest - Test pattern: `*.test.ts` or `*.spec.ts` - Run with `pnpm test` ### Code Style - Prettier and ESLint run automatically via pre-commit hooks - Manually run with `pnpm lint` if needed - Stylelint for CSS validation ### Database & Prisma - Prisma client is in `src/generated/prisma/` (not default location) - Never edit generated files manually - If you modify `prisma/schema.prisma`, regenerate with: `pnpm build-db-client` - Database is already migrated and ready to use ## Quick Reference for UI Development ### Most Common Imports ```typescript // UI Components (from component library) import { Button, Form, TextField, Modal, Row, Column, Grid } from '@umami/react-zen'; // Custom Components (from common) import { PageBody, PageHeader, Panel, DataGrid, Empty } from '@/components/common'; // Hooks import { useApi, useMessages, useFormat, useWebsite, useUser } from '@/components/hooks'; // State import { useApp } from '@/store/app'; import { setUser, setLocale, setTimezone } from '@/store/app'; ``` ### Most Common Patterns - **New page**: Create in `src/app/(main)/[feature]/page.tsx` - **New API route**: Create in `src/app/api/[feature]/route.ts` - **New component**: Add to `src/components/common/` or `src/components/input/` - **New hook**: Add to `src/components/hooks/` - **New query hook**: Add to `src/components/hooks/queries/` - **Global state**: Add to or use existing `src/store/*.ts` ### Development Workflow (Niteshift Sandbox) 1. **Access app** - http://localhost:3001 (already running!) 2. **Login** - Use admin/umami credentials 3. **Make changes** - Edit files in `src/` 4. **See results** - Hot reload happens automatically, changes appear instantly 5. **Check types** - TypeScript errors show in editor automatically 6. **Test** - `pnpm test` (optional) 7. **Lint** - `pnpm lint` (optional, runs automatically on commit)