supabase/supabase
Patterns and conventions
Conventions that the existing code consistently follows. New code should mirror them.
TypeScript
- The whole repo is TS / TSX. Plain
.jsis reserved for tool config (postcss.config.cjs,tailwind.config.js). - Strict mode is on.
pnpm typecheckrunstsc --noEmitper package via Turborepo (pnpm typecheckat the root passes--continue). anyis heavily discouraged — Studio's eslint ratchet specifically tracks@typescript-eslint/no-explicit-anyand only allows it to decrease over time.- Shared
tsconfiglives inpackages/tsconfig. Apps and packages extend from there.
React
Hooks-first. Class components are not in use.
React-Query (
@tanstack/react-queryv5) is the data-fetching standard for Studio. The convention is one folder per domain inapps/studio/data/<domain>/:apps/studio/data/auth/ ├── auth-config-query.ts ├── auth-config-update-mutation.ts ├── user-query.ts ├── user-update-mutation.ts └── keys.ts // exposes `authKeys` for invalidation*-query.ts→useQuerywrappers.*-mutation.ts→useMutationwrappers (also export an<X>Variablestype).keys.ts→ strongly-typed query-key factories.
valtiois the small global-state library used for ephemeral cross-component state in Studio (apps/studio/state/).react-hook-form+zodfor forms.@hookform/resolversties them together.
File and folder names
- Studio components folders are PascalCase (
Auth/,BranchManagement/,SQLEditor/). - Files within a feature are PascalCase for components (
UserDropdown.tsx) and kebab-case for hooks / utilities (error-patterns.ts,handle-error.ts). - Data-layer files are kebab-case (
auth-config-query.ts). - New shared UI components in
packages/uiuse kebab-case file names (button.tsx).
Styling
- Tailwind only. No CSS modules. No inline styles for design tokens.
- Use semantic tokens —
bg-muted,text-foreground-light,border-default,text-brand, etc. Hardcoded hex /gray-*is a code smell. - Tailwind config is rooted at the workspace; per-package
tailwind.config.jsfiles are stubs for IntelliSense. - Class composition uses
cn()from'ui'(aclsx+tailwind-mergewrapper).
Imports
Never import workspace packages by relative path. Always use the alias:
import { useUserQuery } from 'data/auth/user-query'; import { Button } from 'ui';ESLint's
no-restricted-importsis ratcheted in Studio — moving a file shouldn't introduce new banned import paths.Re-exports from barrel files are discouraged in Studio;
eslint-plugin-barrel-filesflags them.Imports are auto-sorted by
@ianvs/prettier-plugin-sort-imports(Prettier).
Naming
React-Query keys use a per-domain factory:
export const authKeys = { all: () => ['auth'] as const, user: (id: string) => ['auth', 'user', id] as const, };Mutation hook names are imperative:
useUpdateAuthConfigMutation,useDeleteUserMutation.Query hook names are descriptive:
useAuthConfigQuery,useUserQuery.
Error handling
- Studio's data layer centralizes error normalization in
apps/studio/data/handleError.tsanderror-patterns.ts. New fetchers should go through these helpers so users see consistent messages. - UI surfaces use
react-error-boundaryand Studio'scomponents/interfaces/ErrorHandling/for top-level boundaries.
SQL
- All Studio SQL is generated from
packages/pg-meta/src/*rather than written ad-hoc. Each generator returns a{ sql, zod }pair so callers can validate the response shape with Zod. - Never interpolate user input into SQL strings.
packages/pg-meta/src/pg-format/provides safeformat/literal/identhelpers. - A custom Studio ESLint rule,
studio/require-safe-sql-fragment(inapps/studio/eslint-rules/), enforces this on new code.
Telemetry
- All product events live in
packages/common/telemetry-constants.ts. Adding a new event means adding a typed constant there, then dispatching it via the helpers inpackages/common/telemetry.tsx. - Studio uses PostHog through
packages/common/posthog-client.ts. Consent is handled bypackages/common/consent-state.ts.
Feature flags
- Server-evaluated flags are read through
packages/common/configcat.ts. - Client-side enabled-features are exposed via
packages/common/feature-flags.tsxandpackages/common/enabled-features/. - Adding a new flag: extend the type union in
enabled-features/, add the ConfigCat key, and gate the feature behinduseFlag('your-flag').
Markdown / docs
- Docs use MDX with several custom remark/rehype plugins under
apps/docs/lib/mdx/. apps/docs/spec/holds the SDK / Config / CLI specs that drive generated reference pages — change the spec, not the rendered page.- Linting is performed by
supa-mdx-lint(rootsupa-mdx-lint.config.toml).
Common workflows captured as repo idioms
- Adding a redirect: extend
apps/www/lib/redirects.js. - Adding a Studio feature flag toggle: usually under
components/interfaces/Settings/FeaturePreviews/plus a ConfigCat entry. - Adding a new design-system component: edit
packages/uiorpackages/ui-patterns, then updateapps/design-system/config/docs.ts,content/docs/, andregistry/. Re-runpnpm --filter design-system build:registry. - Adding a
/go/*page: add a typed page object inapps/www/_go/, register inapps/www/_go/index.tsx. The routeapp/go/[slug]/page.tsxpicks it up automatically.
Cross-reference
- Lint rules and ratchet behavior: Tooling
- Data-fetching layout in detail:
packages/api-types,packages/pg-meta - UI conventions:
packages/ui
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.