mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 20:05:06 +03:00
Splits agent guidance into a lean monorepo-wide root file and a studio-specific file that Claude Code lazy-loads when working under `apps/studio/`. This keeps every session's baseline context small while giving studio work much richer, enforceable guidance. **Changed:** - `.claude/CLAUDE.md` — now monorepo-wide only: corrected pnpm version (10 → 11), expanded workspace table (design-system, ui-library, lite-studio, ui-patterns, api-types, pg-meta, shared-data), commands (`format`, `generate:types`, `api:codegen`), CI gates + never-hand-edit generated files, monorepo-wide conventions (incl. the named-exports rule, which lives in the shared eslint preset and applies to all six apps), and monorepo-wide skill triggers. Studio detail is replaced by a pointer to the nested file. Also corrects a long-standing error inherited from the old file: the `_Shadcn_` convention was inverted — `Button_Shadcn_` is the only suffixed export left and is rarely the right choice; primitives are unsuffixed. - `.claude/skills/studio-ui-patterns/SKILL.md` — removed the same stale `_Shadcn_` claim from the forms section (this skill also feeds CodeRabbit reviews). - `apps/studio/components/README.md` — component template now uses a named export, matching the lint-enforced convention (was the one doc still showing `export default`). - `apps/studio/TANSTACK_MIGRATION.md` — cleanup checklist gains an item to remove the migration section from `apps/studio/CLAUDE.md` when the migration finishes. - `.gitignore` — removed the blanket `CLAUDE.md` ignore rule (added in #40231 for personal local files, no longer used that way). Nested `CLAUDE.md` files are now tracked by default, so shared guidance can't silently fail to land. For *personal* notes, use `CLAUDE.local.md` (Claude Code loads it automatically alongside `CLAUDE.md`, and it's now gitignored here) — or `.git/info/exclude` if you prefer a different filename. **Added:** - `apps/studio/CLAUDE.md` — studio guidance, loaded on demand: mandatory skill routing (always load `studio-best-practices`, plus a task → skill table), TanStack Start migration rules (pages/routes mirroring, when a manual mirror is needed, never delete `pages/**` files), data-layer/state orientation, a default-to-shipping-tests-with-changes policy, and a "defaults that differ here" list (ESLint warning ratchet + local `lint:ratchet` command, `copyToClipboard` await rule, `useParams` from `common`, dayjs/sonner, `ui` vs `ui-patterns` import split, `@tanstack/react-table` over `react-data-grid`, etc.). ## Accuracy Every factual claim in both files (62 total) was verified against the code by parallel review agents instructed to refute each one. Results: 54 correct as written, 2 wrong (the inherited `_Shadcn_` inversion, and a fabricated `useExecuteSqlQuery` hook name — the real export is `useExecuteSqlMutation`), 6 imprecise (e.g. dayjs plugins load in both runtime entries, the ratchet counts occurrences regardless of severity). All fixed in this PR. ## Context cost | File | Size | When it loads | % of a 200k window | |---|---|---|---| | `.claude/CLAUDE.md` | 70 lines, ~1.2k est. tokens | every session | ~0.6% | | `apps/studio/CLAUDE.md` | 53 lines, ~1.6k est. tokens | only when touching studio files | ~0.8% | The always-loaded footprint grew only ~0.2k est. tokens vs the old 45-line file — everything studio-heavy sits behind the lazy load, so docs/www sessions pay nothing for it. Both files are well under Claude Code's large-file warning threshold (~40k chars) and the <200-line adherence guidance, with room to roughly double before it's worth worrying about. ## To test - Open a fresh Claude Code session from the repo root and read any file under `apps/studio/` — `apps/studio/CLAUDE.md` should get pulled into context automatically. - `git check-ignore apps/studio/CLAUDE.md` exits 1 (not ignored); `git check-ignore CLAUDE.local.md` exits 0 (ignored). - Skim both files — every claim has been code-verified (see Accuracy above), but a human sanity pass on the *judgment* calls (what's included/omitted) is welcome. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Refreshed monorepo onboarding conventions with updated tooling requirements, expanded inventory, standardized common scripts, and clearer CI gating and checks. * Added/updated Studio contributor guidance, including the TanStack Start migration rules and Studio development/testing/UI conventions. * Updated Studio component documentation to use named exports. * Refreshed the “Forms” UI pattern guidance and adjusted the referenced UI primitives. * **Chores** * Updated ignore rules so the primary top-level onboarding document is tracked. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
54 lines
6.4 KiB
Markdown
54 lines
6.4 KiB
Markdown
# Supabase Studio
|
|
|
|
Next.js pages router + TanStack Start (mid-migration, see below), React 19. Dev server: `pnpm dev:studio` → http://localhost:8082.
|
|
|
|
## Skills — load before working
|
|
|
|
**Always load the `studio-best-practices` skill before writing or modifying any Studio code.** Then stack the area-specific skills:
|
|
|
|
| Task | Additional skills |
|
|
| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
|
|
| Query/mutation hooks, query keys (`data/**`) | `studio-queries` |
|
|
| UI: pages, forms, tables, charts, sheets, empty states | `studio-ui-patterns` |
|
|
| Displaying API errors | `studio-error-handling` |
|
|
| Tests (deciding, writing, reviewing) | `studio-testing`, then `studio-mock-api-tests` (component/MSW) or `studio-e2e-tests` (Playwright) |
|
|
| PostHog event tracking | `telemetry-standards` |
|
|
| SQL against user databases | `safe-sql-execution` |
|
|
| Logs Explorer SQL, `data/logs` | `clickhouse-logs-queries` |
|
|
| Component API design, boolean-prop refactors | `vercel-composition-patterns` |
|
|
| User-facing copy | `copywriting` |
|
|
|
|
## TanStack Start migration
|
|
|
|
Studio is migrating from the Next.js pages router (`pages/**`) to TanStack Start (`routes/**`). Both runtimes ship side-by-side; the `STUDIO_FRAMEWORK` env var selects which one `pnpm dev`/`build` runs (default: `next`, resolved in `scripts/dispatch.js`). Full route map and strategy: `TANSTACK_MIGRATION.md`.
|
|
|
|
- **Never delete a page file.** Most `routes/**` files are thin wrappers re-exporting the default export of their `pages/**` counterpart, so the Next file is load-bearing for both runtimes until the final cleanup pass.
|
|
- Pure page-body edits propagate to the route automatically. Mirror a change by hand into the corresponding `routes/**` file only when it touches what the route duplicates: `getLayout`/layout wrapping, page titles or other `staticData` (incl. `skip*Layout` flags), `withAuth`, or redirect paths.
|
|
- A new page under `pages/**` needs a matching route under `routes/**` plus a checklist entry in `TANSTACK_MIGRATION.md`.
|
|
- New code uses native TanStack APIs — no `next/router` or `next/link`. The `compat/next/` shims exist only for legacy re-exported pages.
|
|
- `routeTree.gen.ts` is generated by the Vite plugin — never hand-edit.
|
|
|
|
## Orientation
|
|
|
|
- **Data layer** — all platform API calls go through `data/fetchers.ts` (`openapi-fetch`, typed by the generated `api-types` package) with `handleError`; never raw `fetch`. One folder per resource in `data/`, most with a `keys.ts` query-key factory.
|
|
- **State** — valtio for global state (`state/`), nuqs for URL state, react-hook-form + zod for forms.
|
|
- **Platform vs self-hosted** — `IS_PLATFORM` gates platform-only behavior; `withAuth` is a no-op when self-hosted.
|
|
- **Telemetry** — `useTrack()` from `lib/telemetry/track`; event types live in `packages/common/telemetry-constants.ts`.
|
|
- **Tests** — default to including relevant tests with any change: a couple of unit tests for extracted logic, component tests for UI behavior, E2E only when the scope demands it (`studio-testing` has the decision tree). Not every PR needs them, but "no tests" should be a considered choice, not the default. Tooling: vitest + MSW; component tests use `customRender` + `addAPIMock` from `tests/lib/`; unhandled network requests fail tests. Don't `vi.mock('@/data/...')`.
|
|
- **Shortcuts** — use the registry in `state/shortcuts/` and `components/ui/Shortcut*.tsx`; keep `G then …` chords for navigation; no one-off keyboard listeners.
|
|
- **Reuse first** — before writing a new hook or helper, search for an existing one (`hooks/`, `lib/`, `packages/common`, `packages/ui-patterns`). If you do need a new one, make it as reusable as possible: general naming, no page-specific coupling, placed where other callers can find it.
|
|
- Co-locate sub-components with their parent; avoid barrel re-export files.
|
|
|
|
## Defaults that differ here
|
|
|
|
- **ESLint warnings are ratcheted in CI**: the per-rule occurrence count must not increase, so a new `any`, unresolved `exhaustive-deps` warning, or default export fails the build even though it's "only a warning". Check locally with `pnpm --filter studio run lint:ratchet`.
|
|
- **Clipboard**: `copyToClipboard` from `'ui'`, and never `await` anything before calling it (Safari requires the write inside the user gesture; lint-enforced) — pass a Promise as the argument instead.
|
|
- **`useParams()` comes from `'common'`**, not `next/navigation` — it camelCases keys and returns `string | undefined`.
|
|
- **Permissions**: `useAsyncCheckPermissions` from `hooks/misc/useCheckPermissions` (returns `can: true` when self-hosted).
|
|
- **Gating**: `useIsFeatureEnabled` for product features, `useFlag` from `'common'` for feature flags — two different systems.
|
|
- **Dates**: `dayjs` (plugins pre-loaded at both entries, `pages/_app.tsx` and `routes/__root.tsx`), not `date-fns`. **Toasts**: `toast` from `'sonner'`.
|
|
- **Import split**: `'ui'` = primitives, `'ui-patterns'` = composed patterns (`ConfirmationModal`, …), `@ui/*` = alias into `packages/ui/src`. Icons come from `lucide-react`.
|
|
- **New tables** use `@tanstack/react-table`; `react-data-grid` is banned for new code.
|
|
- **Ad-hoc SQL** against the user's database goes through `executeSql` / `useExecuteSqlMutation` (`data/sql/execute-sql-mutation`).
|
|
- **Confirmations**: `ConfirmationModal` / `TextConfirmModal` from `ui-patterns`, never `window.confirm`. Disabled buttons needing an explanation use `ButtonTooltip`; inline warnings use `Admonition`.
|