mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
chore(claude): improve CLAUDE.md files and skill triggering (#48261)
Improves the repo's agent guidance: distills the always-required `studio-best-practices` skill into `apps/studio/CLAUDE.md`, tunes every skill description for reliable triggering, and mechanically enforces the generated-files rule. Grounded in Anthropic's official CLAUDE.md guidance (see justifications below). ## The main change: Studio CLAUDE.md gets a Code style section **Why:** `studio-best-practices` was a skill that instructed agents to *always* load it before any Studio code work. Anthropic's guidance draws the line as: sometimes-relevant guidance → skill (loaded on demand); always-relevant guidance → CLAUDE.md. A skill that must always load has failed the test for being a skill — it costs a tool-call round trip and, worse, silently does nothing in sessions that forget to load it. Since `apps/studio/CLAUDE.md` is lazy-loaded only when an agent touches Studio files, inlining is properly scoped: non-Studio sessions never pay for it. **Why not verbatim:** the skill was 175 lines, mostly ❌/✅ worked examples teaching practices models already know. Inlining it whole would push the file past the ~200-line point where Anthropic warns rules start getting lost. Instead each section was distilled to the rule it exists to enforce — e.g. the loading/error/success section kept its code block because the *shape* (early returns at top level, flat `&&` chains inline) is the prescription, and prose loses it. **The framing that makes the generic rules earn their place:** models default to matching surrounding code, and not all existing Studio code follows these practices. The section opens with "older Studio code predates some of these conventions — follow them rather than mirroring nearby legacy patterns," which converts otherwise-redundant React advice into an explicit instruction to break from local precedent. One rule was added that the old skill lacked: `useEffect` is for external-system sync only (~364 Studio files contain effects, many in patterns we don't want copied). **Changed:** - `apps/studio/CLAUDE.md` — new Code style section (84 lines total, within budget); skills table no longer mandates a pre-load - `.claude/CLAUDE.md` — dropped `pnpm install` from commands (guessable; Anthropic's test: "would removing this cause mistakes?") **Removed:** - `.claude/skills/studio-best-practices/` — fully absorbed; its cross-references to other skills were already covered by the skills routing table ## Skill description tuning Descriptions are the only signal an agent sees before deciding to load a skill, and the observed failure mode is under-triggering on tasks that don't name the skill. Nine descriptions reworded: front-loaded matchable keywords, added incidental-trigger cases (e.g. a new feature that adds copy is a `copywriting` moment), and disambiguated overlaps (`vitest` is now the API reference deferring to `studio-testing` for strategy). The `safe-sql-execution` rewrite was additionally validated with skill-creator's trigger-eval loop against 20 realistic queries: held-out test accuracy 54% → 71%, with zero false triggers across all iterations. (`vitest` shows under `.agents/` because `.claude/skills/vitest` symlinks there.) ## Generated-files enforcement **Added:** `permissions.deny` rules in `.claude/settings.json` for the six generated-file globs the root CLAUDE.md already lists. CLAUDE.md prose is advisory; permission rules are mechanical and also gate sandboxed Bash writes. (Verified live: the rule blocked an unintended regeneration of `database-types.ts` during testing.) ## To test - CI: prettier + typos checks pass (docs-only + settings change, no app code) - In a fresh Claude Code session in the repo: ask it to edit `apps/studio/routeTree.gen.ts` — should be denied by the new permission rule - Ask it to do any Studio UI task — it should pick up the Code style rules from `apps/studio/CLAUDE.md` without loading a best-practices skill <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated development guidance for testing, copywriting, SQL safety, telemetry, queries, error handling, and toolbar reviews. * Restructured Vitest references into clearer tables and improved formatting across several guides. * Added Studio code-style conventions and clarified when task-specific guidance should be applied. * Removed outdated Studio best-practices guidance. * **Chores** * Added safeguards preventing edits to generated and protected files. * Simplified the documented development command sequence. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
This commit is contained in:
1 parent
7f42765070
commit
4b24cf028a
13 files changed
+134
-228
No files matched your search
@@ -24,7 +24,6 @@ pnpm 11 + Turborepo monorepo. Requires Node >= 22.13.
|
||||
## Common Commands
|
||||
|
||||
```bash
|
||||
pnpm install # install dependencies
|
||||
pnpm dev:studio # run Studio dev server → http://localhost:8082
|
||||
pnpm dev:docs # run docs dev server
|
||||
pnpm dev:www # run www dev server
|
||||
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"permissions": {
|
||||
"deny": [
|
||||
"Edit(packages/api-types/types/**)",
|
||||
"Edit(**/routeTree.gen.ts)",
|
||||
"Edit(**/__generated__/**)",
|
||||
"Edit(apps/docs/features/docs/generated/**)",
|
||||
"Edit(apps/www/.generated/**)",
|
||||
"Edit(supabase/functions/common/database-types.ts)"
|
||||
]
|
||||
},
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: copywriting
|
||||
description: Write or audit UI copy (buttons, labels, empty states, error messages, tooltips, form text) anywhere in the monorepo. Always check this before shipping or reviewing user-facing text.
|
||||
description: Write or audit UI copy (buttons, labels, empty states, error messages, tooltips, form text) anywhere in the monorepo. Load it before shipping or reviewing any user-facing text — including when copy is incidental to the task, like a new feature that adds buttons, toasts, dialogs, or validation messages.
|
||||
---
|
||||
|
||||
# Copywriting
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
name: dev-toolbar-review
|
||||
description: Use when reviewing PRs that touch packages/dev-tools/, packages/common/posthog-client.ts,
|
||||
description: Safety rules for the dev toolbar, PostHog client, and feature flags. Use
|
||||
when writing or reviewing any change to packages/dev-tools/, packages/common/posthog-client.ts,
|
||||
or packages/common/feature-flags.tsx. Covers environment guards, flag override cookies,
|
||||
telemetry event subscription, and SSE stream safety.
|
||||
---
|
||||
@@ -30,10 +31,12 @@ so PRs touching only those files won't auto-request review. Watch for these in t
|
||||
**Files:** `packages/dev-tools/index.ts`, `DevToolbar.tsx`, `DevToolbarTrigger.tsx`, `DevToolbarContext.tsx`
|
||||
|
||||
The toolbar uses two layers of protection:
|
||||
|
||||
- **Build-time tree-shaking** in `index.ts`: `process.env.NODE_ENV !== 'development'` ternaries that replace components with noops/stubs so the implementation is eliminated from production bundles.
|
||||
- **Runtime guards** in components: `IS_LOCAL_DEV` checks — `DevToolbar` and `DevToolbarTrigger` return `null` to hide themselves, while `DevToolbarProvider` passes children through (`<>{children}</>`) to preserve the component tree.
|
||||
|
||||
**Check for:**
|
||||
|
||||
- Guards being removed or broadened. The toolbar is expanding to staging and preview deploys but must remain invisible in production.
|
||||
- Tree-shaking ternaries in `index.ts` staying intact — these are the primary production safety mechanism.
|
||||
- New components or exports that bypass the existing guard pattern.
|
||||
@@ -43,14 +46,17 @@ The toolbar uses two layers of protection:
|
||||
**Files:** `packages/dev-tools/DevToolbar.tsx`, `packages/common/posthog-client.ts`, `packages/common/feature-flags.tsx`
|
||||
|
||||
The toolbar writes two cookies that override feature flags locally:
|
||||
|
||||
- `x-ph-flag-overrides` — PostHog flag overrides
|
||||
- `x-cc-flag-overrides` — ConfigCat flag overrides
|
||||
|
||||
These are read by:
|
||||
|
||||
- `posthog-client.ts:getFeatureFlag()` — checks the PostHog override cookie before querying the SDK
|
||||
- `feature-flags.tsx` — merges both override cookies into the flag store during initialization
|
||||
|
||||
**Check for:**
|
||||
|
||||
- Cookie name changes (must stay in sync across writer and all readers)
|
||||
- Changes to the merge/precedence logic in `feature-flags.tsx` (currently: `vercel-flag-overrides` first, then `x-cc-flag-overrides` takes precedence in local dev)
|
||||
- Override cookies being read outside the `IS_LOCAL_DEV` / `isLocalDev` guard — overrides must never affect production flag evaluation
|
||||
@@ -66,6 +72,7 @@ and `identify`. Note: `captureExperimentExposure` calls `posthog.capture()` dire
|
||||
without emitting to dev listeners — experiment exposure events are invisible in the toolbar.
|
||||
|
||||
**Check for:**
|
||||
|
||||
- Changes to `emitToDevListeners` or `subscribeToEvents` that could introduce side effects on the actual capture path (e.g., throwing errors, blocking, mutating event data)
|
||||
- The listener set (`devListeners`) being iterated synchronously in a way that could delay event dispatch
|
||||
- New PostHog client methods that capture events but don't call `emitToDevListeners` (gap in toolbar visibility)
|
||||
@@ -78,6 +85,7 @@ The toolbar connects to `${apiUrl}/telemetry/stream` via Server-Sent Events to d
|
||||
server-side telemetry. Uses exponential backoff on connection errors.
|
||||
|
||||
**Check for:**
|
||||
|
||||
- Changes to the SSE endpoint URL or `session_id` cookie handling
|
||||
- Reconnection logic changes that could cause excessive retries or connection leaks
|
||||
- Note: the stream endpoint lives in the platform repo — cross-repo changes need coordinated review
|
||||
@@ -85,16 +93,19 @@ server-side telemetry. Uses exponential backoff on connection errors.
|
||||
### 5. App-Level Mounting
|
||||
|
||||
**Provider + toolbar panel** (`DevToolbarProvider`, `DevToolbar`):
|
||||
|
||||
- `apps/studio/pages/_app.tsx`
|
||||
- `apps/www/pages/_app.tsx`, `apps/www/app/providers.tsx`
|
||||
- `apps/docs/features/app.providers.tsx`
|
||||
|
||||
**Trigger button** (`DevToolbarTrigger`) — rendered separately in nav/header components:
|
||||
|
||||
- `apps/studio/components/layouts/Navigation/LayoutHeader/LayoutHeader.tsx`
|
||||
- `apps/www/components/Nav/index.tsx`
|
||||
- `apps/docs/components/Navigation/NavigationMenu/TopNavBar.tsx`
|
||||
|
||||
**Check for:**
|
||||
|
||||
- Provider being added or removed from an app
|
||||
- `apiUrl` prop changes (must point to the correct platform API)
|
||||
- Rendering order changes that could affect the toolbar's access to PostHog context
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
---
|
||||
name: safe-sql-execution
|
||||
description: Safely execute SQL queries against a user database without risking SQL injection or other security vulnerabilities.
|
||||
description: >-
|
||||
Use whenever code will build, return, fetch, or execute SQL that runs against
|
||||
a user's real Postgres database — even when the request reads like an ordinary
|
||||
feature or bug fix and never says "security," "injection," or
|
||||
"SafeSqlFragment." This covers: writing or editing any pg-meta function, query
|
||||
builder, or endpoint that builds/returns SQL for database objects (tables,
|
||||
views, functions, DB triggers, indexes, RLS policies); interpolating a
|
||||
schema/table/column/search/route-param value into SQL text; storing, fetching,
|
||||
or re-running SQL that round-trips from the database (a policy's definition, a
|
||||
function/view definition, a snippet's saved content); and any
|
||||
"Run"/"Apply"/"Execute" action that sends SQL to a project's database (SQL
|
||||
editor run-selection, policy editor apply, snippet runner). Load this BEFORE
|
||||
writing such code, not only when reviewing a finished diff. Skip only for
|
||||
changes that never touch SQL text or execution — styling, unrelated data
|
||||
hooks, non-SQL form validation, or UI layout work.
|
||||
---
|
||||
|
||||
# Safe SQL execution
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
---
|
||||
name: studio-best-practices
|
||||
description: React and TypeScript best practices for Supabase Studio. Use when writing
|
||||
or reviewing Studio components — covers boolean naming, component structure, loading/error
|
||||
states, state management, custom hooks, event handlers, conditional rendering,
|
||||
performance, and TypeScript conventions.
|
||||
---
|
||||
|
||||
# Studio Best Practices
|
||||
|
||||
Applies to `apps/studio/**/*.{ts,tsx}`.
|
||||
|
||||
## Boolean Naming
|
||||
|
||||
Use descriptive prefixes — derive from existing state rather than storing separately:
|
||||
|
||||
- `is` — state/identity: `isLoading`, `isPaused`, `isNewRecord`
|
||||
- `has` — possession: `hasPermission`, `hasData`
|
||||
- `can` — capability: `canUpdateColumns`, `canDelete`
|
||||
- `should` — conditional behavior: `shouldFetch`, `shouldRender`
|
||||
|
||||
Extract complex conditions into named variables:
|
||||
|
||||
```tsx
|
||||
// ❌ inline multi-condition
|
||||
{
|
||||
!isSchemaLocked && isTableLike(selectedTable) && canUpdateColumns && !isLoading && <Button />
|
||||
}
|
||||
|
||||
// ✅ named variable
|
||||
const canShowAddButton =
|
||||
!isSchemaLocked && isTableLike(selectedTable) && canUpdateColumns && !isLoading
|
||||
{
|
||||
canShowAddButton && <Button />
|
||||
}
|
||||
```
|
||||
|
||||
Derive booleans — don't store them:
|
||||
|
||||
```tsx
|
||||
// ❌ stored derived state
|
||||
const [isFormValid, setIsFormValid] = useState(false)
|
||||
useEffect(() => {
|
||||
setIsFormValid(name.length > 0 && email.includes('@'))
|
||||
}, [name, email])
|
||||
|
||||
// ✅ derived
|
||||
const isFormValid = name.length > 0 && email.includes('@')
|
||||
```
|
||||
|
||||
## Component Structure
|
||||
|
||||
See `vercel-composition-patterns` skill for compound component and composition patterns.
|
||||
|
||||
Keep components under 200–300 lines. Split when you see:
|
||||
|
||||
- Multiple distinct UI sections
|
||||
- Complex conditional rendering
|
||||
- Multiple unrelated `useState` calls
|
||||
- Hard to understand at a glance
|
||||
|
||||
Co-locate sub-components in the same directory as the parent. Avoid barrel re-export files.
|
||||
|
||||
Extract repeated JSX patterns into small components.
|
||||
|
||||
## Data Fetching
|
||||
|
||||
All data fetching uses TanStack Query (React Query). See `studio-queries` skill for query/mutation patterns and `studio-error-handling` skill for error display conventions.
|
||||
|
||||
### Loading / Error / Success Pattern
|
||||
|
||||
Top level:
|
||||
|
||||
```tsx
|
||||
const { data, error, isLoading, isError, isSuccess } = useQuery(...)
|
||||
|
||||
if (isLoading) return <GenericSkeletonLoader />
|
||||
if (isError) return <AlertError error={error} subject="Failed to load data" />
|
||||
if (isSuccess && data.length === 0) return <EmptyState />
|
||||
return <DataDisplay data={data} />
|
||||
```
|
||||
|
||||
Use early returns — avoid deeply nested conditionals.
|
||||
|
||||
Inline:
|
||||
|
||||
```tsx
|
||||
<div>
|
||||
{isLoading && <InlineLoader />}
|
||||
{isError && <InlineError error={error} />}
|
||||
{isSuccess && data.length === 0 && <EmptyState />}
|
||||
{isSuccess && data.length > 0 && <DataDisplay data={data} />}
|
||||
</div>
|
||||
```
|
||||
|
||||
## State Management
|
||||
|
||||
Keep state as local as possible; lift only when needed.
|
||||
|
||||
Group related form state with `react-hook-form` rather than multiple `useState` calls. See `studio-ui-patterns` skill for form layout and component conventions.
|
||||
|
||||
```tsx
|
||||
// ❌ multiple related useState
|
||||
const [name, setName] = useState('')
|
||||
const [email, setEmail] = useState('')
|
||||
|
||||
// ✅ grouped with react-hook-form
|
||||
const form = useForm<FormValues>({ defaultValues: { name: '', email: '' } })
|
||||
```
|
||||
|
||||
## Custom Hooks
|
||||
|
||||
Extract complex or reusable logic into hooks. Return objects, not arrays:
|
||||
|
||||
```tsx
|
||||
// ❌ array return (hard to extend)
|
||||
return [value, toggle]
|
||||
|
||||
// ✅ object return
|
||||
return { value, toggle, setTrue, setFalse }
|
||||
```
|
||||
|
||||
## Event Handlers
|
||||
|
||||
- Prop callbacks: `on` prefix (`onClose`, `onSave`)
|
||||
- Internal handlers: `handle` prefix (`handleSubmit`, `handleCancel`)
|
||||
|
||||
Use `useCallback` for handlers passed to memoized children; avoid unnecessary inline arrow functions.
|
||||
|
||||
## Conditional Rendering
|
||||
|
||||
```tsx
|
||||
// Simple show/hide
|
||||
<>{isVisible && <Component />}</>
|
||||
|
||||
// Binary choice
|
||||
<>{isLoading ? <Spinner /> : <Content />}</>
|
||||
|
||||
// Multiple conditions — use early returns, not nested ternaries
|
||||
if (isLoading) return <Spinner />
|
||||
if (isError) return <Error />
|
||||
return <Content />
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
`useMemo` for genuinely expensive computations (measured, not assumed). Don't wrap everything — only optimize when you have a measured problem or are passing values to memoized children.
|
||||
|
||||
## TypeScript
|
||||
|
||||
Define prop interfaces explicitly. Use discriminated unions for complex state:
|
||||
|
||||
```tsx
|
||||
type AsyncState<T> =
|
||||
| { status: 'idle' }
|
||||
| { status: 'loading' }
|
||||
| { status: 'success'; data: T }
|
||||
| { status: 'error'; error: Error }
|
||||
```
|
||||
|
||||
Avoid `as any` / `as Type` casts. Validate at boundaries with zod:
|
||||
|
||||
```tsx
|
||||
// ❌ type cast
|
||||
const user = apiResponse as User
|
||||
|
||||
// ✅ zod parse
|
||||
const user = userSchema.parse(apiResponse)
|
||||
// or safe:
|
||||
const result = userSchema.safeParse(apiResponse)
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Extract logic into `.utils.ts` pure functions and test exhaustively. See the `studio-testing` skill for the full testing strategy and decision tree.
|
||||
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: studio-e2e-tests
|
||||
description: Write and run Playwright E2E tests for Supabase Studio. Use when asked
|
||||
to run e2e tests, write new E2E tests, or debug flaky tests. Covers running commands,
|
||||
avoiding race conditions, waiting strategies, selectors, helper functions, and CI
|
||||
vs local differences.
|
||||
description: Write and run Playwright E2E tests for Supabase Studio (e2e/studio).
|
||||
Use when asked to run e2e tests, write new E2E tests, or debug flaky or failing
|
||||
Playwright tests. Covers running commands, avoiding race conditions, waiting
|
||||
strategies, selectors, helper functions, and CI vs local differences.
|
||||
---
|
||||
|
||||
# E2E Studio Tests
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
---
|
||||
name: studio-error-handling
|
||||
description: Error display and troubleshooting pattern for Supabase Studio. Use when
|
||||
rendering API errors in the UI, adding inline troubleshooting steps for a new
|
||||
error type, or wiring up the AI assistant debug button from an error state.
|
||||
showing a failed API request or query error in the UI (AlertError, toast, inline
|
||||
message), adding troubleshooting steps for a new error type, or wiring up the AI
|
||||
assistant debug button from an error state.
|
||||
---
|
||||
|
||||
# Studio Error Handling Pattern
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
name: studio-queries
|
||||
description: React Query conventions for data fetching in Supabase Studio. Use when
|
||||
writing or reviewing query hooks, mutation hooks, or query keys in apps/studio/data/.
|
||||
writing or reviewing query hooks, mutation hooks, or query keys in apps/studio/data/
|
||||
— including adding the first fetch or mutation for a new API endpoint or resource.
|
||||
Covers queryOptions pattern, keys.ts structure, mutation hook template, and imperative
|
||||
fetching.
|
||||
---
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: studio-testing
|
||||
description: Testing strategy for Supabase Studio. Use when writing tests, deciding what
|
||||
type of test to write, extracting logic from components into testable utility
|
||||
functions, or reviewing test coverage. Covers unit tests, component tests,
|
||||
and E2E test selection criteria.
|
||||
description: Testing strategy for Supabase Studio. Use when writing tests, deciding
|
||||
whether a change needs tests and which type, extracting logic from components into
|
||||
testable utility functions, or reviewing test coverage. Covers unit tests, component
|
||||
tests, and E2E test selection criteria.
|
||||
---
|
||||
|
||||
# Studio Testing Strategy
|
||||
@@ -162,14 +162,14 @@ try/finally for resource cleanup. For E2E execution details, see the
|
||||
|
||||
## Codebase References
|
||||
|
||||
| What | Where |
|
||||
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| What | Where |
|
||||
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Util test examples | `apps/studio/tests/components/Grid/Grid.utils.test.ts`, `apps/studio/tests/components/Billing/TaxID.utils.test.ts`, `apps/studio/tests/components/Editor/SpreadsheetImport.utils.test.ts` |
|
||||
| Component test examples | `apps/studio/tests/features/logs/LogsFilterPopover.test.tsx`, `apps/studio/tests/components/CopyButton.test.tsx` |
|
||||
| E2E test example | `e2e/studio/features/filter-bar.spec.ts` |
|
||||
| E2E helpers pattern | `e2e/studio/utils/filter-bar-helpers.ts` |
|
||||
| Custom render | `apps/studio/tests/lib/custom-render.tsx` |
|
||||
| MSW mock setup | `apps/studio/tests/lib/msw.ts` (`addAPIMock`) |
|
||||
| Test README | `apps/studio/tests/README.md` |
|
||||
| Vitest config | `apps/studio/vitest.config.ts` |
|
||||
| Related skills | `studio-e2e-tests` (running E2E), `vitest` (API reference), `vercel-composition-patterns` (component architecture) |
|
||||
| Component test examples | `apps/studio/tests/features/logs/LogsFilterPopover.test.tsx`, `apps/studio/tests/components/CopyButton.test.tsx` |
|
||||
| E2E test example | `e2e/studio/features/filter-bar.spec.ts` |
|
||||
| E2E helpers pattern | `e2e/studio/utils/filter-bar-helpers.ts` |
|
||||
| Custom render | `apps/studio/tests/lib/custom-render.tsx` |
|
||||
| MSW mock setup | `apps/studio/tests/lib/msw.ts` (`addAPIMock`) |
|
||||
| Test README | `apps/studio/tests/README.md` |
|
||||
| Vitest config | `apps/studio/vitest.config.ts` |
|
||||
| Related skills | `studio-e2e-tests` (running E2E), `vitest` (API reference), `vercel-composition-patterns` (component architecture) |
|
||||
@@ -1,8 +1,10 @@
|
||||
---
|
||||
name: telemetry-standards
|
||||
description: PostHog event tracking standards for Supabase Studio. Use when reviewing
|
||||
PRs for telemetry compliance or implementing new event tracking. Covers event naming,
|
||||
property conventions, approved patterns, and implementation guide.
|
||||
description: PostHog event tracking standards for Supabase Studio. Use when adding
|
||||
useTrack() calls, defining events in packages/common/telemetry-constants.ts,
|
||||
implementing tracking for a new feature, or reviewing PRs for telemetry compliance.
|
||||
Covers event naming, property conventions, approved patterns, and implementation
|
||||
guide.
|
||||
---
|
||||
|
||||
# Telemetry Standards for Supabase Studio
|
||||
@@ -19,16 +21,19 @@ opened, clicked, submitted, created, removed, updated, intended, evaluated, adde
|
||||
enabled, disabled, copied, exposed, failed, converted, closed, completed, applied, sent, moved
|
||||
|
||||
**Flag these:**
|
||||
|
||||
- Unapproved verbs (saved, viewed, seen, pressed, etc.)
|
||||
- Wrong order: `click_product_card` → should be `product_card_clicked`
|
||||
- Wrong casing: `productCardClicked` → should be `product_card_clicked`
|
||||
|
||||
**Good examples:**
|
||||
|
||||
- `product_card_clicked`
|
||||
- `backup_button_clicked`
|
||||
- `sql_query_submitted`
|
||||
|
||||
**Common mistakes with corrections:**
|
||||
|
||||
- `database_saved` → `save_button_clicked` or `database_updated` (unapproved verb)
|
||||
- `click_backup_button` → `backup_button_clicked` (wrong order)
|
||||
- `dashboardViewed` → don't track passive views on page load
|
||||
@@ -39,10 +44,12 @@ enabled, disabled, copied, exposed, failed, converted, closed, completed, applie
|
||||
**Casing:** camelCase preferred for new events. The codebase has existing snake_case properties (e.g., `schema_name`, `table_name`) — when adding properties to an existing event, match its established convention.
|
||||
|
||||
**Names must be self-explanatory:**
|
||||
|
||||
- `{ productType: 'database', planTier: 'pro' }`
|
||||
- `{ assistantType: 'sql', suggestionType: 'optimization' }`
|
||||
|
||||
**Flag these:**
|
||||
|
||||
- Generic names: `label`, `value`, `name`, `data`
|
||||
- PascalCase properties
|
||||
- Inconsistent names across similar events (e.g., `assistantType` in one event, `aiType` in a related event)
|
||||
@@ -117,6 +124,7 @@ When reviewing a PR, flag these as **required changes:**
|
||||
5. **Inaccurate docs** — `@page`/`@source` descriptions that don't match the actual implementation
|
||||
|
||||
When a PR adds user-facing interactions (buttons, forms, toggles, modals) **without** tracking, suggest:
|
||||
|
||||
- "This adds a user interaction that may benefit from tracking."
|
||||
- Propose the event name following `[object]_[verb]` convention
|
||||
- Propose the `useTrack()` call with suggested properties
|
||||
|
||||
Reference in new issue
Block a user