# Project pack: Umami @ e92fdab

Facts about **Umami** for an AI following the [BespokeAI handover guide](https://handoff.bespokeai.software/guide/v1.md). This pack is pinned to one version and never changes after publication.

> Umami tells you how your website is doing: how many people visited, which pages they read, where they came from and which country and device they used. It is a simple, privacy-friendly alternative to Google Analytics that uses no cookies, so you usually don't need a cookie banner. You add one line of code to your site, and Umami shows clear charts. It runs on your own server, so your visitors' data stays with you.

## Version and source
- Repository: https://github.com/umami-software/umami
- Pinned commit: `e92fdab99508a8ed05249f6c5f07e140deab79e1`. Use exactly this version.
- Get it: `git clone https://github.com/umami-software/umami umami && cd umami && git checkout e92fdab99508a8ed05249f6c5f07e140deab79e1`
- Or download a zip: https://github.com/umami-software/umami/archive/e92fdab99508a8ed05249f6c5f07e140deab79e1.zip
- Official docs: https://umami.is/docs
- Live demo: https://cloud.umami.is/share/LGazGOecbDtaIwDr/umami.is. Official read-only demo linked from the README, showing statistics for umami.is.
- Licence: **MIT**. Free to use, change and share for any purpose, including commercial use. Keep the copyright and licence notice if you share the code. No obligation to publish your changes.

## Running it
- Easiest:

  ```sh
  Download docker-compose.yml from the repo, change APP_SECRET to a random string (and the database password), then run `docker compose up -d` and open http://localhost:3000. Log in as admin / umami and change the password straight away. Add your website in Settings → Websites and paste the tracking code into your site.
  ```

- Needs: Docker with Docker Compose, or Node.js 18.18+ with pnpm and PostgreSQL 12.14+
- Develop: `pnpm install && pnpm dev   # needs DATABASE_URL in .env; app on :3000`
- Test: `pnpm test`
- Check/lint: `pnpm lint`
- Build: `pnpm build`
- Stack: typescript (Next.js 16, React 19, Prisma, TanStack Query, Zustand, react-zen). Difficulty for a non-developer with an AI: **moderate**. A single Next.js app in TypeScript, so one language end to end. Most needs are covered by settings, the tracker's options, custom events, the API and share links. Code changes touch src/app/ (pages and API routes), src/queries/ (database queries with both PostgreSQL and ClickHouse versions) and src/tracker/ (the script on your site). Builds take a while.

## The project's own AI instructions
Read these in the repository before changing code: `CONTRIBUTING.md`.

## Customisation points (settings → extend → code)
- **websites-teams-sharing** [settings]: Add websites, give a team access, or make a public share link for a client or your board. → `Settings → Websites / Teams (src/app/(main)/settings/websites, teams); share links under each website's settings`
- **preferences-and-language** [settings]: Time zone, date range, language and theme. → `Settings → Preferences (src/app/(main)/settings/preferences); translations in public/intl/messages/`
- **env-switches** [settings]: Ignore your own IP, rename the tracking script, turn off telemetry or all outside calls, enable two-factor login. → `Environment variables (docs page umami.is/docs/environment-variables)`
- **tracker-options-and-events** [extend]: Count button clicks, form sends and downloads, skip certain pages, or only track your real domain. → `data-* attributes on the tracking script and umami.track() (src/tracker/index.ts; docs umami.is/docs/track-events)`
- **api-and-mcp** [extend]: Pull numbers into a weekly email or spreadsheet, or ask an AI assistant about your traffic. → `REST API with API keys (Settings → API keys, src/app/api/); MCP at /mcp (src/app/mcp/, packages/mcp/)`
- **reports-and-boards** [settings]: Track sign-ups or sales as goals and build a dashboard of the numbers you care about. → `Each website's reports (src/app/(main)/websites/[websiteId]/(reports)/ goals, funnels, journeys, utm, revenue…); Boards (src/app/(main)/boards)`
- **ui-pages** [code]: New views or a simpler screen for a non-technical colleague. → `src/app/(main)/** and src/components/**`
- **queries** [code]: New statistics or data. Database changes need a Prisma migration. → `src/queries/** (PostgreSQL and ClickHouse), prisma/schema.prisma + prisma/migrations/`

## Must keep working
- The tracking script URL and the /api/send endpoint. Every website you track depends on them.
- Existing visit data. Back up the database before upgrades or code changes.
- Team and website permissions. One client must not see another's statistics.
- Database changes need a Prisma migration, and queries must keep working on both PostgreSQL and ClickHouse.

## Staying updatable
Settings, tracker options, custom events, share links, the API and MCP cover most needs without a fork. Upstream accepts pull requests against the dev branch (not master) and asks that they build and lint cleanly. There is no AGENTS.md.

## Data, costs and safety
- Personal data: **yes**. Stored in: PostgreSQL (the umami-db-data volume), or ClickHouse for large sites. Visit data is anonymised (no cookies; visitor IDs use a rotating salt), but it still includes pages, referrers, rough location and device. Session replays and heatmaps, if you turn them on, record much more. Back up the database volume regularly; you can also export data from the app.
- Service: PostgreSQL (required, free (included in the compose file)): Stores your websites, users and visit data.
- Service: ClickHouse and Redis (optional, free if self-hosted): Only for very busy sites with lots of traffic.
- Service: Website icons from duckduckgo.com and update checks (optional, free): Shows site icons and tells you about new versions. Turn off with PRIVATE_MODE=1.
- Setting `DATABASE_URL` (**secret**: the person enters it themselves, never in chat): PostgreSQL connection string, including the password.
- Setting `APP_SECRET` (**secret**: the person enters it themselves, never in chat): A long random string used to sign logins. Never paste it into an AI chat.
- Setting `TWO_FACTOR_ENCRYPTION_KEY` (**secret**: the person enters it themselves, never in chat): 64-character hex key (openssl rand -hex 32) that turns on two-factor login.
- Setting `TRACKER_SCRIPT_NAME`: Rename the tracking script (default script.js) so fewer ad blockers stop it.
- Setting `DISABLE_TELEMETRY`: Set to 1 to stop sending anonymous usage data to the Umami team.
- Setting `PRIVATE_MODE`: Set to 1 to block all outside network calls (also hides website icons).
- Setting `IGNORE_IP`: IP addresses to leave out of the statistics, such as your own.
- Setting `MCP_ENABLED`: Set to 1 to switch on the /mcp endpoint so an AI assistant can read your statistics with an API key.
- Change the default admin / umami login and the example APP_SECRET and database password before going live.
- Umami must be reachable from the internet for the tracking script to work. Serve it over HTTPS and keep it updated.
- Session replays and heatmaps record what visitors do on your pages. Only turn them on if your privacy notice covers it; form inputs are masked by default and a strict mode hides all text.
- Anonymous telemetry is sent to the Umami team unless you set DISABLE_TELEMETRY=1; PRIVATE_MODE=1 blocks all outside calls.
- Share links are public to anyone who has them. API keys give access to all your statistics, so keep them out of AI chats.

---

# Customising Umami

Umami is one Next.js app written in TypeScript. **Almost everything a small business wants is settings, tracker options or the API.** Code changes are rarely needed.

## Level 1: Settings (no code)
- **Websites:** Settings → Websites. Add each site, copy its tracking code into your site's `<head>` (most website builders have a "custom code" box).
- **People:** Settings → Teams to share websites with colleagues; Settings → Profile and Security for passwords and two-factor login (needs `TWO_FACTOR_ENCRYPTION_KEY`).
- **Share links:** in a website's settings, turn on a public read-only link for clients or a board.
- **Reports:** goals (count sign-ups or "Book now" clicks), funnels, journeys, retention, UTM campaigns, revenue, heatmaps, plus Boards for your own dashboard.
- **Environment switches:** `IGNORE_IP` (leave out your own visits), `TRACKER_SCRIPT_NAME` (fewer ad blockers), `DISABLE_TELEMETRY=1`, `PRIVATE_MODE=1` (no outside calls), `MCP_ENABLED=1`. Full list: https://umami.is/docs/environment-variables.

## Level 2: Extend (no fork)
- **Tracker options:** `data-domains` (only count your real domain), `data-exclude-search`, `data-auto-track="false"` and more on the script tag. See https://umami.is/docs/tracker-configuration.
- **Custom events:** add `data-umami-event="Book now"` to a button, or call `umami.track()` from your own code.
- **REST API** with an API key (Settings → API keys): weekly summaries, spreadsheets, client reports. Reference at https://umami.is/docs/api.
- **MCP:** set `MCP_ENABLED=1` and connect an AI assistant to `/mcp` with an API key to ask questions about your traffic. A stand-alone MCP package lives in `packages/mcp/`.
- **Translations:** `public/intl/messages/*.json`.

## Level 3: Code
There is no upstream AGENTS.md. Follow `CONTRIBUTING.md` and Biome's formatting.

| Change | Where |
|---|---|
| Pages and views | `src/app/(main)/**` (Next.js App Router), shared UI in `src/components/**` |
| Website reports | `src/app/(main)/websites/[websiteId]/**` |
| API routes | `src/app/api/**` |
| Statistics queries | `src/queries/**` (PostgreSQL and ClickHouse versions) |
| Data | `prisma/schema.prisma` + `prisma/migrations/` |
| Tracking script | `src/tracker/index.ts` |
| Permissions | `src/permissions/` |

## Running locally
- **Just use it:** download `docker-compose.yml`, change `APP_SECRET`, run `docker compose up -d`, open http://localhost:3000 and log in as admin / umami (change the password at once).
- **Develop:**
  1. Install Node 22 with pnpm and run PostgreSQL (Docker is fine).
  2. Create `.env` with `DATABASE_URL=postgresql://…`.
  3. Run `pnpm install`, then `pnpm build` once to create the tables.
  4. Run `pnpm dev` and open http://localhost:3000.
- **Check:** `pnpm lint`, `pnpm test`, `pnpm build`.

## Pitfalls
- Change the default admin password and `APP_SECRET` before putting Umami online.
- Don't rename or move the tracking script or `/api/send` without updating every site that uses them.
- Ad blockers hide some visitors. Renaming the script helps a little, so treat numbers as a guide.
- Query changes must work on both PostgreSQL and ClickHouse.
- Pull requests go to the `dev` branch, not `master`.

---
Machine-readable: [bespoke.yaml](https://handoff.bespokeai.software/p/umami/e92fdab/bespoke.yaml) · Agent skill: [SKILL.md](https://handoff.bespokeai.software/p/umami/e92fdab/SKILL.md)
