umami-software/umami
Umami is a modern, privacy-focused analytics platform. An open-source alternative to Google Analytics, Mixpanel and Amplitude.
Privacy-focused web analytics platform, open-source alternative to Google Analytics
Analytics data flows from client tracking scripts through API routes to database storage, then back through query functions to dashboard components
Under the hood, the system uses 2 feedback loops, 3 data pools, 3 control points to manage its runtime behavior.
Structural Verdict
A 10-component dashboard with 4 connections. 674 files analyzed. Loosely coupled — components are relatively independent.
How Data Flows Through the System
Analytics data flows from client tracking scripts through API routes to database storage, then back through query functions to dashboard components
- Track Event — Client-side tracker collects pageviews and custom events
- API Ingestion — API routes receive and validate tracking data
- Database Storage — Prisma stores events, sessions, and metrics in PostgreSQL/ClickHouse
- Query Processing — Query functions aggregate and filter analytics data
- Dashboard Rendering — React components display charts and tables with real-time data
System Behavior
How the system actually operates at runtime — where data accumulates, what loops, what waits, and what controls what.
Data Pools
Stores website events, sessions, users, and aggregated metrics
Client-side state for user preferences, theme, and authentication tokens
React Query cache for API responses and analytics data
Feedback Loops
- Real-time Analytics (polling, reinforcing) — Trigger: Dashboard page load. Action: Polls latest analytics data every few seconds. Exit: User navigates away.
- Authentication Refresh (retry, balancing) — Trigger: 401 API response. Action: Attempts to refresh auth token. Exit: Token refreshed or redirect to login.
Delays & Async Processing
- Analytics Aggregation (batch-window, ~varies by query) — Data may lag behind real-time events for complex aggregations
- Tracker Script Loading (async-processing, ~network dependent) — Page events may be missed if script loads after user interaction
Control Points
- DATABASE_URL (env-var) — Controls: Database connection and type (PostgreSQL vs ClickHouse)
- APP_SECRET (env-var) — Controls: JWT signing and application security
- basePath (env-var) — Controls: Application base path for reverse proxy deployments
Technology Stack
Full-stack React framework with App Router
Database ORM with PostgreSQL and ClickHouse support
Data fetching and caching for API calls
Lightweight state management
Analytics visualizations and charts
End-to-end testing framework
Bundler for tracking script
Containerization and deployment
Key Components
- useApi (hook) — Provides authenticated HTTP client methods for API calls with shared token support
src/components/hooks/useApi.ts - useNavigation (hook) — Manages URL navigation, query parameters, and route building for Next.js router
src/components/hooks/useNavigation.ts - useMessages (hook) — Handles internationalization with message formatting and error message translation
src/components/hooks/useMessages.ts - Chart (component) — Base chart component using Chart.js for analytics visualizations
src/components/charts/Chart.tsx - SideMenu (component) — Navigation sidebar component used in admin and settings areas
src/components/common/SideMenu.tsx - getWebsiteStats (function) — Core analytics query function for retrieving website statistics from database
src/queries/analytics/websites/getWebsiteStats.ts - tracker (module) — Client-side tracking script that collects pageviews and events without cookies
src/tracker/index.ts - seed (utility) — Database seeding utility that generates realistic analytics data for testing
scripts/seed/index.ts - useApp (hook) — Global application state management using Zustand for locale, theme, and tokens
src/store/app.ts - AdminNav (component) — Administrative navigation sidebar for managing users, websites, and teams
src/app/(main)/admin/AdminNav.tsx
Configuration
docker-compose.yml (yaml)
services.umami.image(string, unknown) — default: ghcr.io/umami-software/umami:latestservices.umami.ports(array, unknown) — default: 3000:3000services.umami.environment.DATABASE_URL(string, unknown) — default: postgresql://umami:umami@db:5432/umamiservices.umami.environment.APP_SECRET(string, unknown) — default: replace-me-with-a-random-stringservices.umami.depends_on.db.condition(string, unknown) — default: service_healthyservices.umami.init(boolean, unknown) — default: trueservices.umami.restart(string, unknown) — default: alwaysservices.umami.healthcheck.test(array, unknown) — default: CMD-SHELL,curl http://localhost:3000/api/heartbeat- +14 more parameters
pnpm-workspace.yaml (yaml)
packages(array, unknown) — default: **ignoredBuiltDependencies(array, unknown) — default: cypress,esbuild,sharponlyBuiltDependencies(array, unknown) — default: @prisma/client,@prisma/engines,prisma
app.json (json)
name(string, unknown) — default: Umamidescription(string, unknown) — default: Umami is a simple, fast, website analytics alternative to Google Analytics.keywords(array, unknown) — default: analytics,charts,statistics,web-analyticswebsite(string, unknown) — default: https://umami.isrepository(string, unknown) — default: https://github.com/umami-software/umamiaddons(array, unknown) — default: heroku-postgresqlenv.APP_SECRET.description(string, unknown) — default: Used to generate unique values for your installationenv.APP_SECRET.required(boolean, unknown) — default: true- +2 more parameters
biome.json (json)
$schema(string, unknown) — default: https://biomejs.dev/schemas/2.3.6/schema.jsonvcs.enabled(boolean, unknown) — default: truevcs.clientKind(string, unknown) — default: gitvcs.useIgnoreFile(boolean, unknown) — default: truefiles.includes(array, unknown) — default: **,!!**/distformatter.enabled(boolean, unknown) — default: trueformatter.lineWidth(number, unknown) — default: 100formatter.indentStyle(string, unknown) — default: space- +21 more parameters
Explore the interactive analysis
See the full architecture map, data flow, and code patterns visualization.
Analyze on CodeSeaRelated Dashboard Repositories
Frequently Asked Questions
What is umami used for?
Privacy-focused web analytics platform, open-source alternative to Google Analytics umami-software/umami is a 10-component dashboard written in TypeScript. Loosely coupled — components are relatively independent. The codebase contains 674 files.
How is umami architected?
umami is organized into 4 architecture layers: App Routes, Components, Database Layer, Tracker. Loosely coupled — components are relatively independent. This layered structure keeps concerns separated and modules independent.
How does data flow through umami?
Data moves through 5 stages: Track Event → API Ingestion → Database Storage → Query Processing → Dashboard Rendering. Analytics data flows from client tracking scripts through API routes to database storage, then back through query functions to dashboard components This pipeline design reflects a complex multi-stage processing system.
What technologies does umami use?
The core stack includes Next.js (Full-stack React framework with App Router), Prisma (Database ORM with PostgreSQL and ClickHouse support), React Query (Data fetching and caching for API calls), Zustand (Lightweight state management), Chart.js (Analytics visualizations and charts), Cypress (End-to-end testing framework), and 2 more. A focused set of dependencies that keeps the build manageable.
What system dynamics does umami have?
umami exhibits 3 data pools (Analytics Database, Application State), 2 feedback loops, 3 control points, 2 delays. The feedback loops handle polling and retry. These runtime behaviors shape how the system responds to load, failures, and configuration changes.
What design patterns does umami use?
5 design patterns detected: Custom Hooks Pattern, Query Functions, Component Re-exports, API Route Handlers, Permission Abstractions.
Analyzed on March 31, 2026 by CodeSea. Written by Karolina Sarna.