

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
1# Supabase Studio23Next.js pages router + TanStack Start (mid-migration, see below), React 19. Dev server: `pnpm dev:studio` → http://localhost:8082.45## Skills — load before working67Load the skills matching the task; stack them when a task spans areas:89| Task | Additional skills |10| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |11| Query/mutation hooks, query keys (`data/**`) | `studio-queries` |12| UI: pages, forms, tables, charts, sheets, empty states | `studio-ui-patterns` |13| Form logic: react-hook-form fields, watch/formState, reset, number inputs | `react-hook-form` |14| Displaying API errors | `studio-error-handling` |15| Tests (deciding, writing, reviewing) | `studio-testing`, then `studio-mock-api-tests` (component/MSW) or `studio-e2e-tests` (Playwright) |16| PostHog event tracking | `telemetry-standards` |17| SQL against user databases | `safe-sql-execution` |18| Logs Explorer SQL, `data/logs` | `clickhouse-logs-queries` |19| Component API design, boolean-prop refactors | `vercel-composition-patterns` |20| User-facing copy | `copywriting` |2122## TanStack Start migration2324Studio 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`.2526- **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.27- 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.28- A new page under `pages/**` needs a matching route under `routes/**` plus a checklist entry in `TANSTACK_MIGRATION.md`.29- New code uses native TanStack APIs — no `next/router` or `next/link`. The `compat/next/` shims exist only for legacy re-exported pages.30- `routeTree.gen.ts` is generated by the Vite plugin — never hand-edit.3132## Orientation3334- **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.35- **State** — valtio for global state (`state/`), nuqs for URL state, react-hook-form + zod for forms.36- **Platform vs self-hosted** — `IS_PLATFORM` gates platform-only behavior; `withAuth` is a no-op when self-hosted.37- **Telemetry** — `useTrack()` from `lib/telemetry/track`; event types live in `packages/common/telemetry-constants.ts`.38- **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/...')`.39- **Shortcuts** — use the registry in `state/shortcuts/` and `components/ui/Shortcut*.tsx`; keep `G then …` chords for navigation; no one-off keyboard listeners.40- **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.41- Co-locate sub-components with their parent; avoid barrel re-export files.4243## Code style4445Older Studio code predates some of these conventions. For new or modified code, follow them rather than mirroring nearby legacy patterns:4647- **Booleans** read as `is`/`has`/`can`/`should`. Derive them from existing state (`const isFormValid = name.length > 0 && email.includes('@')`) — mirroring a derivable value into `useState` synced by `useEffect` is a bug pattern. Give multi-condition logic a name (`const canShowAddButton = !isSchemaLocked && canUpdateColumns && …`) instead of inlining the chain in JSX.48- **Ternaries**: one is fine for a binary choice; never nest them. Anything bigger flattens — early returns in statement position, sibling `&&` blocks in JSX.49- **Fetch states** render with early returns at the top level, or a flat `&&` chain with mutually exclusive guards inline — never a nested ternary:5051```tsx52 // Top level: early return per state53 if (isLoading) return <GenericSkeletonLoader />54 if (isError) return <AlertError error={error} subject="Failed to retrieve data" />55 if (isSuccess && data.length === 0) return <EmptyState />56 return <DataDisplay data={data} />5758 // Inline: flat `&&` blocks, mutually exclusive guards59 <div>60 {isLoading && <ShimmeringLoader />}61 {isError && <AlertError error={error} />}62 {isSuccess && data.length === 0 && <EmptyState />}63 {isSuccess && data.length > 0 && <DataDisplay data={data} />}64 </div>65```6667- **`useEffect` is for synchronizing with external systems** (subscriptions, DOM, timers) — not for deriving data (compute it in render), reacting to user actions (do it in the handler), or fetching (React Query). Older code uses effects for all of these; don't copy it.68- **State** stays as local as possible — lift it only when it's actually shared. Related form fields belong in a single react-hook-form + zod form, not parallel `useState` calls.69- **Component size**: split at ~200–300 lines — or sooner when a component grows multiple distinct UI sections, tangled conditional rendering, or clusters of unrelated `useState`. Extract repeated JSX into small components, non-trivial pure logic into `.utils.ts` functions (which get unit tests), and reusable stateful logic into custom hooks.70- **Memoization is not the default**: `useMemo`/`useCallback` only for measured expense or referential stability a memoized child depends on.71- **TypeScript**: avoid `as` casts — where external data enters, parse it with zod (`schema.parse`/`safeParse`) instead. Model multi-state values as discriminated unions (`{ status: 'success'; data: T } | { status: 'error'; error: Error }`) rather than independent boolean flags.72- **Naming**: prop callbacks are `onX`, internal handlers are `handleX`. Custom hooks return objects, not tuples.73- **Refactoring**: when you move or extract code into a new module, update every importer to point at the new location directly — do **not** leave a re-export shim in the old file "for backward compatibility." It's a one-line import change per consumer, and keeping shims around makes the codebase messy and the true source of a symbol ambiguous.7475## Defaults that differ here7677- **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`.78- **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.79- **`useParams()` comes from `'common'`**, not `next/navigation` — it camelCases keys and returns `string | undefined`.80- **Permissions**: `useAsyncCheckPermissions` from `hooks/misc/useCheckPermissions` (returns `can: true` when self-hosted).81- **Gating**: `useIsFeatureEnabled` for product features, `useFlag` from `'common'` for feature flags — two different systems.82- **Dates**: `dayjs` (plugins pre-loaded at both entries, `pages/_app.tsx` and `routes/__root.tsx`), not `date-fns`. **Toasts**: `toast` from `'sonner'`.83- **Import split**: `'ui'` = primitives, `'ui-patterns'` = composed patterns (`ConfirmationModal`, …), `@ui/*` = alias into `packages/ui/src`. Icons come from `lucide-react`.84- **New tables** use `@tanstack/react-table`; `react-data-grid` is banned for new code.85- **Ad-hoc SQL** against the user's database goes through `executeSql` / `useExecuteSqlMutation` (`data/sql/execute-sql-mutation`).86- **Confirmations**: `ConfirmationModal` / `TextConfirmModal` from `ui-patterns`, never `window.confirm`. Disabled buttons needing an explanation use `ButtonTooltip`; inline warnings use `Admonition`.87
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| supabase/supabase.github/instructions/studio-error-handling.instructions.md · 108k | Copilot instructions | gitdo-not | 57/100 | 14 days ago | |
| supabase/supabase.github/instructions/studio-composition-patterns.instructions.md · 108k | Copilot instructions | stylegitapiui+1 | 61/100 | 14 days ago | |
| supabase/supabase.github/instructions/studio-copy.instructions.md · 108k | Copilot instructions | uiagent-behaviourdocs | 25/100 | 14 days ago | |
| supabase/supabase.github/instructions/studio-shadcn-components.instructions.md · 108k | Copilot instructions | gituido-not | 55/100 | 14 days ago | |
| supabase/supabase.github/instructions/studio-shortcuts.instructions.md · 108k | Copilot instructions | stylegitdo-not | 61/100 | 14 days ago | |
| supabase/supabase.github/instructions/studio-telemetry.instructions.md · 108k | Copilot instructions | stylegitdo-notdocs | 65/100 | 14 days ago | |
| supabase/supabase.github/instructions/studio-testing.instructions.md · 108k | Copilot instructions | testtypestesting-strategygit+1 | 55/100 | 14 days ago | |
| supabase/supabase.claude/CLAUDE.md · 108k | CLAUDE.md | testlint-formatstylearch+1 | 97/100 | 14 days ago | |
| supabase/supabase.github/instructions/studio-e2e-tests.instructions.md · 108k | Copilot instructions | teststyletesting-strategygit+2 | 60/100 | 14 days ago | |
| supabase/supabase.claude/skills/vercel-composition-patterns/AGENTS.md · 108k | AGENTS.md | styleapiuido-not | 45/100 | 14 days ago | |
| supabase/supabase.github/copilot-instructions.md · 108k | Copilot instructions | lint-formatstylegitagent-behaviour | 56/100 | 14 days ago |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| bagisto/bagistoCLAUDE.md · 28k | CLAUDE.md | setupbuildteststyle+5 | 100/100 | 7 days ago | |
| Adit-Jain-srm/NightmareNetCLAUDE.md · 46 | CLAUDE.md | buildtestlint-formatstyle+6 | 100/100 | 14 days ago | |
| tyrchen/geektime-bootcamp-aiw7/genslides/backend/CLAUDE.md · 230 | CLAUDE.md | testlint-formatstylearch+6 | 100/100 | 9 days ago | |
| nimbalyst/nimbalystpackages/android/CLAUDE.md · 1.5k | CLAUDE.md | setupbuildstylearch+2 | 100/100 | 14 days ago | |
| dotCMS/corecore-web/CLAUDE.md · 949 | CLAUDE.md | teststylearchtesting-strategy+3 | 100/100 | 14 days ago | |
| microsoft/playwrightCLAUDE.md · 95k | CLAUDE.md | buildtestlint-formatstyle+7 | 100/100 | 7 days ago | |
| tphakala/birdnet-goCLAUDE.md · 1.6k | CLAUDE.md | buildtestlint-formatstyle+8 | 100/100 | today | |
| dotCMS/coreCLAUDE.md · 949 | CLAUDE.md | setupbuildteststyle+7 | 99/100 | today |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/supabase-supabase-apps-studio-claude)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.