Files
stats/.claude/CLAUDE.md
Carl-Gerhard Lindesvärd aa81bbfe77 feat: session replay
* wip

* wip

* wip

* wip

* final fixes

* comments

* fix
2026-02-26 14:09:53 +01:00

171 lines
6.8 KiB
Markdown

# CLAUDE.md
NEVER CALL FORMAT! WE'LL FORMAT IN THE FUTURE WHEN WE HAVE MERGED ALL BIG PRS!
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Openpanel is an open-source web/product analytics platform (Mixpanel alternative). It's a **pnpm monorepo** with apps, packages, tooling, and SDKs.
## Common Commands
```bash
# Development
pnpm dev # Run all services (api, worker, dashboard) in parallel
pnpm dev:public # Run public/docs site only
pnpm dock:up / dock:down # Start/stop Docker (PostgreSQL, Redis, ClickHouse)
# Code quality
pnpm check # Lint check (Biome via Ultracite)
pnpm fix # Auto-fix lint/format issues
pnpm typecheck # Typecheck all packages
# Testing
pnpm test # Run all tests (vitest)
pnpm vitest run <path> # Run a single test file
# Workspace: packages/* and apps/* (excluding apps/start)
# Database
pnpm codegen # Generate Prisma types + geo data
pnpm migrate # Run Prisma migrations (dev)
pnpm migrate:deploy # Deploy migrations (production - never run this)
# Docker utilities
pnpm dock:ch # ClickHouse CLI
pnpm dock:redis # Redis CLI
```
## Architecture
### Apps
| App | Stack | Port | Purpose |
|-----|-------|------|---------|
| `apps/api` | Fastify + tRPC | 3333 | REST/RPC API server |
| `apps/start` | TanStack Start (Vite + React 19) | 3000 | Dashboard SPA |
| `apps/public` | Next.js 16 + Fumadocs | - | Marketing/docs site |
| `apps/worker` | Express + BullMQ | 9999 | Background job processor |
### Key Packages
| Package | Purpose |
|---------|---------|
| `packages/db` | Prisma ORM (PostgreSQL) + ClickHouse client |
| `packages/trpc` | tRPC router definitions, context, middleware |
| `packages/auth` | Authentication (Arctic OAuth, Oslo sessions, argon2) |
| `packages/queue` | BullMQ + GroupMQ job queue definitions |
| `packages/redis` | Redis client + LRU caching |
| `packages/validation` | Zod schemas shared across apps |
| `packages/common` | Shared utilities (date-fns, ua-parser, nanoid) |
| `packages/email` | React Email templates via Resend |
| `packages/sdks/*` | Client SDKs (web, react, next, express, react-native, etc.) |
### Data Flow
1. **Event ingestion**: Client SDKs → `apps/api` (track routes) → Redis queue
2. **Processing**: `apps/worker` picks up jobs from BullMQ, batches events into ClickHouse
3. **Dashboard queries**: `apps/start` → tRPC → `apps/api` → ClickHouse (analytics) / PostgreSQL (config)
4. **Real-time**: WebSocket via Fastify, pub/sub via Redis
### Three-Database Strategy
- **PostgreSQL**: Relational data (users, orgs, projects, dashboards). Managed by Prisma.
- **ClickHouse**: Analytics event storage (OLAP). High-volume reads/writes.
- **Redis**: Caching, job queues (BullMQ), rate limiting, pub/sub.
### Dashboard (apps/start)
Uses TanStack Router with file-based routing (`src/routes/`). State management via Redux Toolkit. UI built on Radix primitives + Tailwind v4. Charts via Recharts. Modals in `src/modals/`.
### API (apps/api)
Fastify server with tRPC integration. Route files in `src/routes/`. Hooks for IP extraction, request logging, timestamps. Built with `tsdown`.
---
## Core Principles
Write code that is **accessible, performant, type-safe, and maintainable**. Focus on clarity and explicit intent over brevity.
### Type Safety & Explicitness
- Use explicit types for function parameters and return values when they enhance clarity
- Prefer `unknown` over `any` when the type is genuinely unknown
- Use const assertions (`as const`) for immutable values and literal types
- Leverage TypeScript's type narrowing instead of type assertions
- Use meaningful variable names instead of magic numbers - extract constants with descriptive names
### Modern JavaScript/TypeScript
- Use arrow functions for callbacks and short functions
- Prefer `for...of` loops over `.forEach()` and indexed `for` loops
- Use optional chaining (`?.`) and nullish coalescing (`??`) for safer property access
- Prefer template literals over string concatenation
- Use destructuring for object and array assignments
- Use `const` by default, `let` only when reassignment is needed, never `var`
### Async & Promises
- Always `await` promises in async functions - don't forget to use the return value
- Use `async/await` syntax instead of promise chains for better readability
- Handle errors appropriately in async code with try-catch blocks
- Don't use async functions as Promise executors
### React & JSX
- Use function components over class components
- Call hooks at the top level only, never conditionally
- Specify all dependencies in hook dependency arrays correctly
- Use the `key` prop for elements in iterables (prefer unique IDs over array indices)
- Nest children between opening and closing tags instead of passing as props
- Don't define components inside other components
- Use semantic HTML and ARIA attributes for accessibility:
- Provide meaningful alt text for images
- Use proper heading hierarchy
- Add labels for form inputs
- Include keyboard event handlers alongside mouse events
- Use semantic elements (`<button>`, `<nav>`, etc.) instead of divs with roles
### Error Handling & Debugging
- Remove `console.log`, `debugger`, and `alert` statements from production code
- Throw `Error` objects with descriptive messages, not strings or other values
- Use `try-catch` blocks meaningfully - don't catch errors just to rethrow them
- Prefer early returns over nested conditionals for error cases
### Code Organization
- Keep functions focused and under reasonable cognitive complexity limits
- Extract complex conditions into well-named boolean variables
- Use early returns to reduce nesting
- Prefer simple conditionals over nested ternary operators
- Group related code together and separate concerns
### Security
- Add `rel="noopener"` when using `target="_blank"` on links
- Avoid `dangerouslySetInnerHTML` unless absolutely necessary
- Don't use `eval()` or assign directly to `document.cookie`
- Validate and sanitize user input
### Performance
- Avoid spread syntax in accumulators within loops
- Use top-level regex literals instead of creating them in loops
- Prefer specific imports over namespace imports
- Avoid barrel files (index files that re-export everything)
- Use proper image components (e.g., Next.js `<Image>`) over `<img>` tags
### Framework-Specific Guidance
**Next.js:**
- Use Next.js `<Image>` component for images
- Use `next/head` or App Router metadata API for head elements
- Use Server Components for async data fetching instead of async Client Components
**React 19+:**
- Use ref as a prop instead of `React.forwardRef`
**Solid/Svelte/Vue/Qwik:**
- Use `class` and `for` attributes (not `className` or `htmlFor`)