{"owner":"polarsource","repo":"polar","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md"],"skills":{"AGENTS.md":"# Polar\n\nOpen source payment infrastructure platform for developers. Monorepo with a Python/FastAPI\nbackend and a Next.js frontend.\n\nThis file is the entry point for AI agents working in this repo: start here, then read the\nper-area `AGENTS.md` linked from the Architecture and Conventions sections before writing code.\n\n## General Guidelines\n\n- Do not add comments unless necessary — the code should be self-explanatory.\n- Use meaningful variable and function names.\n- Follow established conventions and good practices (SOLID, maintainable code).\n- Do not modify code unrelated to the task or issue you are working on.\n\n## Architecture\n\n```\npolar/\n├── server/                 # Python/FastAPI backend — see server/AGENTS.md\n│   ├── polar/\n│   │   ├── {module}/\n│   │   │   ├── endpoints.py     # FastAPI routes\n│   │   │   ├── service.py       # Business logic (singleton)\n│   │   │   ├── repository.py    # Database queries (SQLAlchemy)\n│   │   │   ├── schemas.py       # Pydantic models\n│   │   │   └── tasks.py         # Dramatiq background jobs\n│   │   ├── models/             # SQLAlchemy models (global, not per-module)\n│   │   └── backoffice/         # Admin UI (HTMX + DaisyUI) — see server/polar/backoffice/AGENTS.md\n│   └── migrations/             # Alembic database migrations\n├── clients/                # Turborepo + pnpm frontend — see clients/AGENTS.md\n│   ├── apps/web/               # Next.js dashboard\n│   ├── apps/app/               # Expo / React Native (iOS + Android)\n│   ├── apps/orbit/             # Orbit design-system showcase\n│   ├── packages/orbit/         # Orbit design system (components + tokens)\n│   ├── packages/ui/            # Legacy shared components (Radix + Tailwind)\n│   ├── packages/client/        # Generated API client + data hooks\n│   └── packages/i18n/          # Translations\n├── dev/                    # Dev scripts and tooling\n├── docs/                   # User/developer docs (Mintlify)\n├── sdk/                    # SDKs and generators\n│   ├── generator/              # Internal SDK code generator\n│   ├── python/                 # Generated Python SDK\n│   └── overlays/               # OpenAPI Overlay tweaks for Speakeasy-generated SDKs\n└── .claude/                # Claude Code config (settings, hooks, commands)\n```\n\nThe TypeScript API client is generated from the backend's OpenAPI schema. After changing the\nAPI, run `pnpm run generate` in `clients/packages/client`.\n\n## Setup\n\n```bash\n./dev/setup-environment     # generate .env files\n# For GitHub integration:\n./dev/setup-environment --setup-github-app --backend-external-url https://yourdomain.ngrok.dev\n```\n\n**Backend** (http://127.0.0.1:8000) — from `server/`:\n```bash\ndocker compose up -d          # PostgreSQL, Redis, Minio\nuv sync                       # install deps\nuv run task api               # API server\nuv run task worker            # background worker (separate terminal)\n```\n\n**Frontend** (http://127.0.0.1:3000) — from `clients/`:\n```bash\npnpm install && pnpm dev\n```\n\n**Stripe** — add to `server/.env`:\n- `POLAR_STRIPE_SECRET_KEY`\n- `POLAR_STRIPE_PUBLISHABLE_KEY`\n- `POLAR_STRIPE_WEBHOOK_SECRET`\n- `POLAR_STRIPE_CONNECT_WEBHOOK_SECRET`\n\n**Fresh worktrees** (`.claude/worktrees/`) don't carry `.env` or built artifacts. Before running\ntests in a new worktree:\n```bash\ncd server\n./dev/setup-environment       # generates .env\nuv run task generate_dev_jwks # creates .jwks.json\nuv run task emails            # builds emails/bin/react-email-pkg\n```\nWithout these, pytest fails at config load with `JWKS` and `EMAIL_RENDERER_BINARY_PATH` errors.\n\n## Development Workflow\n\n**Always prefix Python commands with `uv run`** — it guarantees the correct Python (3.14),\nproject dependencies, environment variables, and virtualenv context.\n\n```bash\ncd server\nuv run task test                                          # backend tests (pnpm test for frontend)\nuv run task lint && uv run task lint_types                # lint + type-check\nuv run alembic revision --autogenerate -m \"description\"   # generate a migration from model changes\nuv run alembic upgrade head                               # apply migrations\n```\n\n**Visual regression testing** — use `dev snap` to capture before/after screenshots across branches:\n```bash\ndev snap --branch my-feature        # test a specific branch\ndev snap --detect                   # auto-detect URLs from git diff\n```\n\nThe customer portal authenticates with a session token rather than the dashboard login, so\n`dev snap` can't reach it on its own. Get its URLs from `dev portal-urls --snap` first.\n\nSee `server/AGENTS.md` for backend command and testing specifics.\n\n## Conventions\n\nDetailed, review-enforced patterns live next to the code — read the relevant file before writing:\n\n- **Backend** → `server/AGENTS.md`: modular structure, repository/service/endpoint patterns,\n  `lazy=\"raise\"` relationships, status-coded `PolarError`, endpoints return ORM models,\n  authentication (`AuthSubject` + scopes).\n- **Frontend** → `clients/AGENTS.md`: Orbit `<Box />` design system (raw Tailwind is **deprecated**\n  for layout/spacing/color/etc.), TanStack Query for data, Zustand for state, 250-line `max-lines` limit.\n- **Backoffice** → `server/polar/backoffice/AGENTS.md`: HTMX + DaisyUI patterns.\n\n**i18n:** add new translatable strings only to `clients/packages/i18n/src/locales/en.ts` — a CI\njob auto-translates the rest. Don't edit other locale files. (More in `clients/AGENTS.md`.)\n\n## Architecture Decisions (ADRs)\n\nSignificant, cross-cutting, or hard-to-reverse decisions are recorded as short ADRs in\n`handbook/engineering/decisions/` (see the [index](handbook/engineering/decisions/index.mdx)).\nTreat **Accepted** ADRs as binding:\n\n- Before changing a load-bearing pattern, check for a relevant ADR (grep that directory).\n- If code contradicts an Accepted ADR, flag it and cite the id (e.g. \"violates ADR-0002\").\n- If a change makes a significant decision no ADR covers, propose a new one from\n  `handbook/engineering/decisions/template.mdx` rather than losing the rationale in the diff.\n\n## Custom Commands\n\n- `/polar-code-review` — checks the diff against Polar-specific rules with 2 parallel agents (conventions, ADR compliance). Bugs, security, and simplification are covered by the built-in `/code-review`, `/security-review`, and `/simplify`.\n\n## Documentation\n\n- **Handbook**: https://handbook.polar.sh/engineering/\n- **Design docs**: https://handbook.polar.sh/engineering/design-documents/\n- **API guidelines**: https://handbook.polar.sh/engineering/rest-api-guidelines\n- **User/developer docs**: `docs/` (Mintlify) — `cd docs && pnpm dev` to serve locally.\n\n## Key Integrations\n\n- **Stripe**: payments and subscriptions. Needs API keys + webhook secret in `server/.env`.\n- **GitHub**: authentication and repository features. Needs a GitHub App configured for local dev.\n- **Slack**: workspace integration for notifications. Configured via OAuth at runtime (no `.env` setup).\n- **S3 / Minio**: file storage.\n- **Redis**: cache and job queue.\n- **PostgreSQL**: primary database.\n\n## Cursor Cloud specific instructions\n\nPrefer the Polar Development CLI (`dev/cli/`, alias `dev`) — the same path local developers use.\nSee `dev/cli/README.md` for the full command list. Do **not** use `dev docker` (the heavier\nimage-based stack from the `local-environment` skill) unless you specifically need it.\nStandard lint/test commands live in `server/AGENTS.md` and `clients/AGENTS.md`.\n\n**Day-to-day start sequence**\n\n```bash\n# Once per VM boot (Docker isn't managed by systemd here):\nsudo dockerd > /tmp/dockerd.log 2>&1 &\n\ndev up --skip-integrations   # deps, infra (incl. Tinybird), migrations, builds\ndev seed                     # sample orgs/products + admin@polar.sh (NOT part of `dev up`)\ndev start                    # api + worker + web (+ stripe) in tmux session `polar`\n# Stop with:  dev stop\n# Status:     dev status\n```\n\n`--skip-integrations` avoids interactive GitHub/Stripe prompts. **Do not pass `--skip-tinybird`**\nif you need the dashboard Overview/homepage metrics — without Tinybird those widgets show a\nnetwork error. `dev up` does **not** load sample data; run `dev seed` afterward. That creates\n`admin@polar.sh` with access to seeded orgs (notably `admin-org` with a `Pro` product, plus\n`acme-corp`, `polar`, etc.). Login OTP codes print in the API pane. If seed says \"Already\nseeded\" (exit 2), the DB already has `acme-corp` — use `dev seed --reset` only when you\nintentionally want a wipe.\n\n**Tinybird already-running gotcha.** Step `04_start_infrastructure` early-returns when\nPostgres/Redis/Minio are already up, and will **not** start a missing Tinybird container in\nthat case. If `dev status` shows Tinybird down after `dev up`, start it explicitly:\n\n```bash\ncd server && docker compose --profile tinybird up -d\n# then wait for http://localhost:7181/tokens, write the admin_token into\n# ~/.config/polar/secrets.env as POLAR_TINYBIRD_{API,READ,CLICKHOUSE}_TOKEN,\n# run ./dev/setup-environment, and restart api/worker so they pick up the tokens.\n```\n\n`dev start` ends by *attaching* to the `polar` tmux session; in a non-interactive agent shell,\ncreate/attach then immediately `tmux detach-client -s polar`, or run `dev api` / `dev worker` /\n`dev web` as individual detached processes. The stripe pane of `dev start` will prompt to\ninstall the Stripe CLI via Homebrew — decline on Linux (no Homebrew); checkout/payment testing\nneeds a real Stripe sandbox later (`dev stripe`, see the `local-environment` skill's\n`payment-testing` rule).\n\n**One-time shell wiring** (already done in this VM snapshot): `./dev/cli/install` adds the\n`dev` alias; Node 24 is installed via nvm (`clients/` requires it — `.nvmrc` is `24`); `uv` is\nat `~/.local/bin/uv`. Source `~/.bashrc` (or start a login shell) so `nvm use 24` and the\n`dev` alias are active.\n\n**Docker caveats.** `/etc/docker/daemon.json` is pinned to `fuse-overlayfs` with\n`features.containerd-snapshotter: false` — required for Docker 29 in this VM; don't remove it.\nThe `ubuntu` user is in the `docker` group.\n\n**Backend config artifacts.** Config import fails without the email renderer binary\n(`server/emails/bin/react-email-pkg`, built by `dev up` / `uv run task emails`) and\n`server/.jwks.json` + `server/.env` (from `./dev/setup-environment` / `dev up`). Missing →\npydantic `EMAIL_RENDERER_BINARY_PATH` / `JWKS` errors. `dev status` reports \"Worker unknown\n(check manually)\" by design — confirm with `pgrep -af dramatiq` or the `polar` tmux pane.\n\n**Tests need no manual DB setup** — the `polar_test` database is auto-created/dropped by a\n`sqlalchemy_utils` fixture. Run `uv run task test` or a subset with\n`POLAR_ENV=testing uv run python -m pytest <path>`.\n\n**Login.** Email OTP codes are printed in the API pane / log (`LOGIN CODE: …`). Grab with\n`tmux capture-pane -t polar:services.0 -p | grep -a \"LOGIN CODE\" | tail -1`. `admin@polar.sh`\nis the conventional test account.\n\n**Onboarding gotcha.** The org-creation wizard's \"Launch Dashboard\" button only submits once the\nProduct step's required fields are filled (description ≥30 chars, ≥1 selling category, ≥1 pricing\nmodel). The AUP AI check auto-APPROVEs when `PYDANTIC_AI_GATEWAY_API_KEY` is unset.\n"},"files":{"AGENTS.md":"# Polar\n\nOpen source payment infrastructure platform for developers. Monorepo with a Python/FastAPI\nbackend and a Next.js frontend.\n\nThis file is the entry point for AI agents working in this repo: start here, then read the\nper-area `AGENTS.md` linked from the Architecture and Conventions sections before writing code.\n\n## General Guidelines\n\n- Do not add comments unless necessary — the code should be self-explanatory.\n- Use meaningful variable and function names.\n- Follow established conventions and good practices (SOLID, maintainable code).\n- Do not modify code unrelated to the task or issue you are working on.\n\n## Architecture\n\n```\npolar/\n├── server/                 # Python/FastAPI backend — see server/AGENTS.md\n│   ├── polar/\n│   │   ├── {module}/\n│   │   │   ├── endpoints.py     # FastAPI routes\n│   │   │   ├── service.py       # Business logic (singleton)\n│   │   │   ├── repository.py    # Database queries (SQLAlchemy)\n│   │   │   ├── schemas.py       # Pydantic models\n│   │   │   └── tasks.py         # Dramatiq background jobs\n│   │   ├── models/             # SQLAlchemy models (global, not per-module)\n│   │   └── backoffice/         # Admin UI (HTMX + DaisyUI) — see server/polar/backoffice/AGENTS.md\n│   └── migrations/             # Alembic database migrations\n├── clients/                # Turborepo + pnpm frontend — see clients/AGENTS.md\n│   ├── apps/web/               # Next.js dashboard\n│   ├── apps/app/               # Expo / React Native (iOS + Android)\n│   ├── apps/orbit/             # Orbit design-system showcase\n│   ├── packages/orbit/         # Orbit design system (components + tokens)\n│   ├── packages/ui/            # Legacy shared components (Radix + Tailwind)\n│   ├── packages/client/        # Generated API client + data hooks\n│   └── packages/i18n/          # Translations\n├── dev/                    # Dev scripts and tooling\n├── docs/                   # User/developer docs (Mintlify)\n├── sdk/                    # SDKs and generators\n│   ├── generator/              # Internal SDK code generator\n│   ├── python/                 # Generated Python SDK\n│   └── overlays/               # OpenAPI Overlay tweaks for Speakeasy-generated SDKs\n└── .claude/                # Claude Code config (settings, hooks, commands)\n```\n\nThe TypeScript API client is generated from the backend's OpenAPI schema. After changing the\nAPI, run `pnpm run generate` in `clients/packages/client`.\n\n## Setup\n\n```bash\n./dev/setup-environment     # generate .env files\n# For GitHub integration:\n./dev/setup-environment --setup-github-app --backend-external-url https://yourdomain.ngrok.dev\n```\n\n**Backend** (http://127.0.0.1:8000) — from `server/`:\n```bash\ndocker compose up -d          # PostgreSQL, Redis, Minio\nuv sync                       # install deps\nuv run task api               # API server\nuv run task worker            # background worker (separate terminal)\n```\n\n**Frontend** (http://127.0.0.1:3000) — from `clients/`:\n```bash\npnpm install && pnpm dev\n```\n\n**Stripe** — add to `server/.env`:\n- `POLAR_STRIPE_SECRET_KEY`\n- `POLAR_STRIPE_PUBLISHABLE_KEY`\n- `POLAR_STRIPE_WEBHOOK_SECRET`\n- `POLAR_STRIPE_CONNECT_WEBHOOK_SECRET`\n\n**Fresh worktrees** (`.claude/worktrees/`) don't carry `.env` or built artifacts. Before running\ntests in a new worktree:\n```bash\ncd server\n./dev/setup-environment       # generates .env\nuv run task generate_dev_jwks # creates .jwks.json\nuv run task emails            # builds emails/bin/react-email-pkg\n```\nWithout these, pytest fails at config load with `JWKS` and `EMAIL_RENDERER_BINARY_PATH` errors.\n\n## Development Workflow\n\n**Always prefix Python commands with `uv run`** — it guarantees the correct Python (3.14),\nproject dependencies, environment variables, and virtualenv context.\n\n```bash\ncd server\nuv run task test                                          # backend tests (pnpm test for frontend)\nuv run task lint && uv run task lint_types                # lint + type-check\nuv run alembic revision --autogenerate -m \"description\"   # generate a migration from model changes\nuv run alembic upgrade head                               # apply migrations\n```\n\n**Visual regression testing** — use `dev snap` to capture before/after screenshots across branches:\n```bash\ndev snap --branch my-feature        # test a specific branch\ndev snap --detect                   # auto-detect URLs from git diff\n```\n\nThe customer portal authenticates with a session token rather than the dashboard login, so\n`dev snap` can't reach it on its own. Get its URLs from `dev portal-urls --snap` first.\n\nSee `server/AGENTS.md` for backend command and testing specifics.\n\n## Conventions\n\nDetailed, review-enforced patterns live next to the code — read the relevant file before writing:\n\n- **Backend** → `server/AGENTS.md`: modular structure, repository/service/endpoint patterns,\n  `lazy=\"raise\"` relationships, status-coded `PolarError`, endpoints return ORM models,\n  authentication (`AuthSubject` + scopes).\n- **Frontend** → `clients/AGENTS.md`: Orbit `<Box />` design system (raw Tailwind is **deprecated**\n  for layout/spacing/color/etc.), TanStack Query for data, Zustand for state, 250-line `max-lines` limit.\n- **Backoffice** → `server/polar/backoffice/AGENTS.md`: HTMX + DaisyUI patterns.\n\n**i18n:** add new translatable strings only to `clients/packages/i18n/src/locales/en.ts` — a CI\njob auto-translates the rest. Don't edit other locale files. (More in `clients/AGENTS.md`.)\n\n## Architecture Decisions (ADRs)\n\nSignificant, cross-cutting, or hard-to-reverse decisions are recorded as short ADRs in\n`handbook/engineering/decisions/` (see the [index](handbook/engineering/decisions/index.mdx)).\nTreat **Accepted** ADRs as binding:\n\n- Before changing a load-bearing pattern, check for a relevant ADR (grep that directory).\n- If code contradicts an Accepted ADR, flag it and cite the id (e.g. \"violates ADR-0002\").\n- If a change makes a significant decision no ADR covers, propose a new one from\n  `handbook/engineering/decisions/template.mdx` rather than losing the rationale in the diff.\n\n## Custom Commands\n\n- `/polar-code-review` — checks the diff against Polar-specific rules with 2 parallel agents (conventions, ADR compliance). Bugs, security, and simplification are covered by the built-in `/code-review`, `/security-review`, and `/simplify`.\n\n## Documentation\n\n- **Handbook**: https://handbook.polar.sh/engineering/\n- **Design docs**: https://handbook.polar.sh/engineering/design-documents/\n- **API guidelines**: https://handbook.polar.sh/engineering/rest-api-guidelines\n- **User/developer docs**: `docs/` (Mintlify) — `cd docs && pnpm dev` to serve locally.\n\n## Key Integrations\n\n- **Stripe**: payments and subscriptions. Needs API keys + webhook secret in `server/.env`.\n- **GitHub**: authentication and repository features. Needs a GitHub App configured for local dev.\n- **Slack**: workspace integration for notifications. Configured via OAuth at runtime (no `.env` setup).\n- **S3 / Minio**: file storage.\n- **Redis**: cache and job queue.\n- **PostgreSQL**: primary database.\n\n## Cursor Cloud specific instructions\n\nPrefer the Polar Development CLI (`dev/cli/`, alias `dev`) — the same path local developers use.\nSee `dev/cli/README.md` for the full command list. Do **not** use `dev docker` (the heavier\nimage-based stack from the `local-environment` skill) unless you specifically need it.\nStandard lint/test commands live in `server/AGENTS.md` and `clients/AGENTS.md`.\n\n**Day-to-day start sequence**\n\n```bash\n# Once per VM boot (Docker isn't managed by systemd here):\nsudo dockerd > /tmp/dockerd.log 2>&1 &\n\ndev up --skip-integrations   # deps, infra (incl. Tinybird), migrations, builds\ndev seed                     # sample orgs/products + admin@polar.sh (NOT part of `dev up`)\ndev start                    # api + worker + web (+ stripe) in tmux session `polar`\n# Stop with:  dev stop\n# Status:     dev status\n```\n\n`--skip-integrations` avoids interactive GitHub/Stripe prompts. **Do not pass `--skip-tinybird`**\nif you need the dashboard Overview/homepage metrics — without Tinybird those widgets show a\nnetwork error. `dev up` does **not** load sample data; run `dev seed` afterward. That creates\n`admin@polar.sh` with access to seeded orgs (notably `admin-org` with a `Pro` product, plus\n`acme-corp`, `polar`, etc.). Login OTP codes print in the API pane. If seed says \"Already\nseeded\" (exit 2), the DB already has `acme-corp` — use `dev seed --reset` only when you\nintentionally want a wipe.\n\n**Tinybird already-running gotcha.** Step `04_start_infrastructure` early-returns when\nPostgres/Redis/Minio are already up, and will **not** start a missing Tinybird container in\nthat case. If `dev status` shows Tinybird down after `dev up`, start it explicitly:\n\n```bash\ncd server && docker compose --profile tinybird up -d\n# then wait for http://localhost:7181/tokens, write the admin_token into\n# ~/.config/polar/secrets.env as POLAR_TINYBIRD_{API,READ,CLICKHOUSE}_TOKEN,\n# run ./dev/setup-environment, and restart api/worker so they pick up the tokens.\n```\n\n`dev start` ends by *attaching* to the `polar` tmux session; in a non-interactive agent shell,\ncreate/attach then immediately `tmux detach-client -s polar`, or run `dev api` / `dev worker` /\n`dev web` as individual detached processes. The stripe pane of `dev start` will prompt to\ninstall the Stripe CLI via Homebrew — decline on Linux (no Homebrew); checkout/payment testing\nneeds a real Stripe sandbox later (`dev stripe`, see the `local-environment` skill's\n`payment-testing` rule).\n\n**One-time shell wiring** (already done in this VM snapshot): `./dev/cli/install` adds the\n`dev` alias; Node 24 is installed via nvm (`clients/` requires it — `.nvmrc` is `24`); `uv` is\nat `~/.local/bin/uv`. Source `~/.bashrc` (or start a login shell) so `nvm use 24` and the\n`dev` alias are active.\n\n**Docker caveats.** `/etc/docker/daemon.json` is pinned to `fuse-overlayfs` with\n`features.containerd-snapshotter: false` — required for Docker 29 in this VM; don't remove it.\nThe `ubuntu` user is in the `docker` group.\n\n**Backend config artifacts.** Config import fails without the email renderer binary\n(`server/emails/bin/react-email-pkg`, built by `dev up` / `uv run task emails`) and\n`server/.jwks.json` + `server/.env` (from `./dev/setup-environment` / `dev up`). Missing →\npydantic `EMAIL_RENDERER_BINARY_PATH` / `JWKS` errors. `dev status` reports \"Worker unknown\n(check manually)\" by design — confirm with `pgrep -af dramatiq` or the `polar` tmux pane.\n\n**Tests need no manual DB setup** — the `polar_test` database is auto-created/dropped by a\n`sqlalchemy_utils` fixture. Run `uv run task test` or a subset with\n`POLAR_ENV=testing uv run python -m pytest <path>`.\n\n**Login.** Email OTP codes are printed in the API pane / log (`LOGIN CODE: …`). Grab with\n`tmux capture-pane -t polar:services.0 -p | grep -a \"LOGIN CODE\" | tail -1`. `admin@polar.sh`\nis the conventional test account.\n\n**Onboarding gotcha.** The org-creation wizard's \"Launch Dashboard\" button only submits once the\nProduct step's required fields are filled (description ≥30 chars, ≥1 selling category, ≥1 pricing\nmodel). The AUP AI check auto-APPROVEs when `PYDANTIC_AI_GATEWAY_API_KEY` is unset.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# Polar\n\nOpen source payment infrastructure platform for developers. Monorepo with a Python/FastAPI\nbackend and a Next.js frontend.\n\nThis file is the entry point for AI agents working in this repo: start here, then read the\nper-area `AGENTS.md` linked from the Architecture and Conventions sections before writing code.\n\n## General Guidelines\n\n- Do not add comments unless necessary — the code should be self-explanatory.\n- Use meaningful variable and function names.\n- Follow established conventions and good practices (SOLID, maintainable code).\n- Do not modify code unrelated to the task or issue you are working on.\n\n## Architecture\n\n```\npolar/\n├── server/                 # Python/FastAPI backend — see server/AGENTS.md\n│   ├── polar/\n│   │   ├── {module}/\n│   │   │   ├── endpoints.py     # FastAPI routes\n│   │   │   ├── service.py       # Business logic (singleton)\n│   │   │   ├── repository.py    # Database queries (SQLAlchemy)\n│   │   │   ├── schemas.py       # Pydantic models\n│   │   │   └── tasks.py         # Dramatiq background jobs\n│   │   ├── models/             # SQLAlchemy models (global, not per-module)\n│   │   └── backoffice/         # Admin UI (HTMX + DaisyUI) — see server/polar/backoffice/AGENTS.md\n│   └── migrations/             # Alembic database migrations\n├── clients/                # Turborepo + pnpm frontend — see clients/AGENTS.md\n│   ├── apps/web/               # Next.js dashboard\n│   ├── apps/app/               # Expo / React Native (iOS + Android)\n│   ├── apps/orbit/             # Orbit design-system showcase\n│   ├── packages/orbit/         # Orbit design system (components + tokens)\n│   ├── packages/ui/            # Legacy shared components (Radix + Tailwind)\n│   ├── packages/client/        # Generated API client + data hooks\n│   └── packages/i18n/          # Translations\n├── dev/                    # Dev scripts and tooling\n├── docs/                   # User/developer docs (Mintlify)\n├── sdk/                    # SDKs and generators\n│   ├── generator/              # Internal SDK code generator\n│   ├── python/                 # Generated Python SDK\n│   └── overlays/               # OpenAPI Overlay tweaks for Speakeasy-generated SDKs\n└── .claude/                # Claude Code config (settings, hooks, commands)\n```\n\nThe TypeScript API client is generated from the backend's OpenAPI schema. After changing the\nAPI, run `pnpm run generate` in `clients/packages/client`.\n\n## Setup\n\n```bash\n./dev/setup-environment     # generate .env files\n# For GitHub integration:\n./dev/setup-environment --setup-github-app --backend-external-url https://yourdomain.ngrok.dev\n```\n\n**Backend** (http://127.0.0.1:8000) — from `server/`:\n```bash\ndocker compose up -d          # PostgreSQL, Redis, Minio\nuv sync                       # install deps\nuv run task api               # API server\nuv run task worker            # background worker (separate terminal)\n```\n\n**Frontend** (http://127.0.0.1:3000) — from `clients/`:\n```bash\npnpm install && pnpm dev\n```\n\n**Stripe** — add to `server/.env`:\n- `POLAR_STRIPE_SECRET_KEY`\n- `POLAR_STRIPE_PUBLISHABLE_KEY`\n- `POLAR_STRIPE_WEBHOOK_SECRET`\n- `POLAR_STRIPE_CONNECT_WEBHOOK_SECRET`\n\n**Fresh worktrees** (`.claude/worktrees/`) don't carry `.env` or built artifacts. Before running\ntests in a new worktree:\n```bash\ncd server\n./dev/setup-environment       # generates .env\nuv run task generate_dev_jwks # creates .jwks.json\nuv run task emails            # builds emails/bin/react-email-pkg\n```\nWithout these, pytest fails at config load with `JWKS` and `EMAIL_RENDERER_BINARY_PATH` errors.\n\n## Development Workflow\n\n**Always prefix Python commands with `uv run`** — it guarantees the correct Python (3.14),\nproject dependencies, environment variables, and virtualenv context.\n\n```bash\ncd server\nuv run task test                                          # backend tests (pnpm test for frontend)\nuv run task lint && uv run task lint_types                # lint + type-check\nuv run alembic revision --autogenerate -m \"description\"   # generate a migration from model changes\nuv run alembic upgrade head                               # apply migrations\n```\n\n**Visual regression testing** — use `dev snap` to capture before/after screenshots across branches:\n```bash\ndev snap --branch my-feature        # test a specific branch\ndev snap --detect                   # auto-detect URLs from git diff\n```\n\nThe customer portal authenticates with a session token rather than the dashboard login, so\n`dev snap` can't reach it on its own. Get its URLs from `dev portal-urls --snap` first.\n\nSee `server/AGENTS.md` for backend command and testing specifics.\n\n## Conventions\n\nDetailed, review-enforced patterns live next to the code — read the relevant file before writing:\n\n- **Backend** → `server/AGENTS.md`: modular structure, repository/service/endpoint patterns,\n  `lazy=\"raise\"` relationships, status-coded `PolarError`, endpoints return ORM models,\n  authentication (`AuthSubject` + scopes).\n- **Frontend** → `clients/AGENTS.md`: Orbit `<Box />` design system (raw Tailwind is **deprecated**\n  for layout/spacing/color/etc.), TanStack Query for data, Zustand for state, 250-line `max-lines` limit.\n- **Backoffice** → `server/polar/backoffice/AGENTS.md`: HTMX + DaisyUI patterns.\n\n**i18n:** add new translatable strings only to `clients/packages/i18n/src/locales/en.ts` — a CI\njob auto-translates the rest. Don't edit other locale files. (More in `clients/AGENTS.md`.)\n\n## Architecture Decisions (ADRs)\n\nSignificant, cross-cutting, or hard-to-reverse decisions are recorded as short ADRs in\n`handbook/engineering/decisions/` (see the [index](handbook/engineering/decisions/index.mdx)).\nTreat **Accepted** ADRs as binding:\n\n- Before changing a load-bearing pattern, check for a relevant ADR (grep that directory).\n- If code contradicts an Accepted ADR, flag it and cite the id (e.g. \"violates ADR-0002\").\n- If a change makes a significant decision no ADR covers, propose a new one from\n  `handbook/engineering/decisions/template.mdx` rather than losing the rationale in the diff.\n\n## Custom Commands\n\n- `/polar-code-review` — checks the diff against Polar-specific rules with 2 parallel agents (conventions, ADR compliance). Bugs, security, and simplification are covered by the built-in `/code-review`, `/security-review`, and `/simplify`.\n\n## Documentation\n\n- **Handbook**: https://handbook.polar.sh/engineering/\n- **Design docs**: https://handbook.polar.sh/engineering/design-documents/\n- **API guidelines**: https://handbook.polar.sh/engineering/rest-api-guidelines\n- **User/developer docs**: `docs/` (Mintlify) — `cd docs && pnpm dev` to serve locally.\n\n## Key Integrations\n\n- **Stripe**: payments and subscriptions. Needs API keys + webhook secret in `server/.env`.\n- **GitHub**: authentication and repository features. Needs a GitHub App configured for local dev.\n- **Slack**: workspace integration for notifications. Configured via OAuth at runtime (no `.env` setup).\n- **S3 / Minio**: file storage.\n- **Redis**: cache and job queue.\n- **PostgreSQL**: primary database.\n\n## Cursor Cloud specific instructions\n\nPrefer the Polar Development CLI (`dev/cli/`, alias `dev`) — the same path local developers use.\nSee `dev/cli/README.md` for the full command list. Do **not** use `dev docker` (the heavier\nimage-based stack from the `local-environment` skill) unless you specifically need it.\nStandard lint/test commands live in `server/AGENTS.md` and `clients/AGENTS.md`.\n\n**Day-to-day start sequence**\n\n```bash\n# Once per VM boot (Docker isn't managed by systemd here):\nsudo dockerd > /tmp/dockerd.log 2>&1 &\n\ndev up --skip-integrations   # deps, infra (incl. Tinybird), migrations, builds\ndev seed                     # sample orgs/products + admin@polar.sh (NOT part of `dev up`)\ndev start                    # api + worker + web (+ stripe) in tmux session `polar`\n# Stop with:  dev stop\n# Status:     dev status\n```\n\n`--skip-integrations` avoids interactive GitHub/Stripe prompts. **Do not pass `--skip-tinybird`**\nif you need the dashboard Overview/homepage metrics — without Tinybird those widgets show a\nnetwork error. `dev up` does **not** load sample data; run `dev seed` afterward. That creates\n`admin@polar.sh` with access to seeded orgs (notably `admin-org` with a `Pro` product, plus\n`acme-corp`, `polar`, etc.). Login OTP codes print in the API pane. If seed says \"Already\nseeded\" (exit 2), the DB already has `acme-corp` — use `dev seed --reset` only when you\nintentionally want a wipe.\n\n**Tinybird already-running gotcha.** Step `04_start_infrastructure` early-returns when\nPostgres/Redis/Minio are already up, and will **not** start a missing Tinybird container in\nthat case. If `dev status` shows Tinybird down after `dev up`, start it explicitly:\n\n```bash\ncd server && docker compose --profile tinybird up -d\n# then wait for http://localhost:7181/tokens, write the admin_token into\n# ~/.config/polar/secrets.env as POLAR_TINYBIRD_{API,READ,CLICKHOUSE}_TOKEN,\n# run ./dev/setup-environment, and restart api/worker so they pick up the tokens.\n```\n\n`dev start` ends by *attaching* to the `polar` tmux session; in a non-interactive agent shell,\ncreate/attach then immediately `tmux detach-client -s polar`, or run `dev api` / `dev worker` /\n`dev web` as individual detached processes. The stripe pane of `dev start` will prompt to\ninstall the Stripe CLI via Homebrew — decline on Linux (no Homebrew); checkout/payment testing\nneeds a real Stripe sandbox later (`dev stripe`, see the `local-environment` skill's\n`payment-testing` rule).\n\n**One-time shell wiring** (already done in this VM snapshot): `./dev/cli/install` adds the\n`dev` alias; Node 24 is installed via nvm (`clients/` requires it — `.nvmrc` is `24`); `uv` is\nat `~/.local/bin/uv`. Source `~/.bashrc` (or start a login shell) so `nvm use 24` and the\n`dev` alias are active.\n\n**Docker caveats.** `/etc/docker/daemon.json` is pinned to `fuse-overlayfs` with\n`features.containerd-snapshotter: false` — required for Docker 29 in this VM; don't remove it.\nThe `ubuntu` user is in the `docker` group.\n\n**Backend config artifacts.** Config import fails without the email renderer binary\n(`server/emails/bin/react-email-pkg`, built by `dev up` / `uv run task emails`) and\n`server/.jwks.json` + `server/.env` (from `./dev/setup-environment` / `dev up`). Missing →\npydantic `EMAIL_RENDERER_BINARY_PATH` / `JWKS` errors. `dev status` reports \"Worker unknown\n(check manually)\" by design — confirm with `pgrep -af dramatiq` or the `polar` tmux pane.\n\n**Tests need no manual DB setup** — the `polar_test` database is auto-created/dropped by a\n`sqlalchemy_utils` fixture. Run `uv run task test` or a subset with\n`POLAR_ENV=testing uv run python -m pytest <path>`.\n\n**Login.** Email OTP codes are printed in the API pane / log (`LOGIN CODE: …`). Grab with\n`tmux capture-pane -t polar:services.0 -p | grep -a \"LOGIN CODE\" | tail -1`. `admin@polar.sh`\nis the conventional test account.\n\n**Onboarding gotcha.** The org-creation wizard's \"Launch Dashboard\" button only submits once the\nProduct step's required fields are filled (description ≥30 chars, ≥1 selling category, ≥1 pricing\nmodel). The AUP AI check auto-APPROVEs when `PYDANTIC_AI_GATEWAY_API_KEY` is unset.\n","category":"root","tokens":2799}]}