mirror of
https://github.com/supabase/supabase.git
synced 2026-10-08 19: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>
6.4 KiB
6.4 KiB
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 theirpages/**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 otherstaticData(incl.skip*Layoutflags),withAuth, or redirect paths. - A new page under
pages/**needs a matching route underroutes/**plus a checklist entry inTANSTACK_MIGRATION.md. - New code uses native TanStack APIs — no
next/routerornext/link. Thecompat/next/shims exist only for legacy re-exported pages. routeTree.gen.tsis 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 generatedapi-typespackage) withhandleError; never rawfetch. One folder per resource indata/, most with akeys.tsquery-key factory. - State — valtio for global state (
state/), nuqs for URL state, react-hook-form + zod for forms. - Platform vs self-hosted —
IS_PLATFORMgates platform-only behavior;withAuthis a no-op when self-hosted. - Telemetry —
useTrack()fromlib/telemetry/track; event types live inpackages/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-testinghas the decision tree). Not every PR needs them, but "no tests" should be a considered choice, not the default. Tooling: vitest + MSW; component tests usecustomRender+addAPIMockfromtests/lib/; unhandled network requests fail tests. Don'tvi.mock('@/data/...'). - Shortcuts — use the registry in
state/shortcuts/andcomponents/ui/Shortcut*.tsx; keepG 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, unresolvedexhaustive-depswarning, or default export fails the build even though it's "only a warning". Check locally withpnpm --filter studio run lint:ratchet. - Clipboard:
copyToClipboardfrom'ui', and neverawaitanything before calling it (Safari requires the write inside the user gesture; lint-enforced) — pass a Promise as the argument instead. useParams()comes from'common', notnext/navigation— it camelCases keys and returnsstring | undefined.- Permissions:
useAsyncCheckPermissionsfromhooks/misc/useCheckPermissions(returnscan: truewhen self-hosted). - Gating:
useIsFeatureEnabledfor product features,useFlagfrom'common'for feature flags — two different systems. - Dates:
dayjs(plugins pre-loaded at both entries,pages/_app.tsxandroutes/__root.tsx), notdate-fns. Toasts:toastfrom'sonner'. - Import split:
'ui'= primitives,'ui-patterns'= composed patterns (ConfirmationModal, …),@ui/*= alias intopackages/ui/src. Icons come fromlucide-react. - New tables use
@tanstack/react-table;react-data-gridis banned for new code. - Ad-hoc SQL against the user's database goes through
executeSql/useExecuteSqlMutation(data/sql/execute-sql-mutation). - Confirmations:
ConfirmationModal/TextConfirmModalfromui-patterns, neverwindow.confirm. Disabled buttons needing an explanation useButtonTooltip; inline warnings useAdmonition.