/telemetry-standards
PostHog event tracking standards for Supabase Studio. Use when adding
$ npx -y skills add supabase/supabase --skill telemetry-standards --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/telemetry-standards
Context preview
The summary Claude sees to decide when to auto-load this skill.
PostHog event tracking standards for Supabase Studio. Use when adding
SKILL.md
telemetry-standards.SKILL.mdname: telemetry-standards
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
Standards for PostHog event tracking in `apps/studio/`. Apply these when reviewing PRs that touch tracking or when implementing new tracking.
Event Naming
**Format:** `[object]_[verb]` in snake_case
**Approved verbs only** (canonical list — derived from `packages/common/telemetry-constants.ts`): opened, clicked, submitted, created, removed, updated, intended, evaluated, added, 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
- `component_rendered` → don't track — no user interaction
Property Standards
**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)
- Mixing camelCase and snake_case within the same event
What NOT to Track
- Passive views/renders on page load (`dashboard_viewed`, `sidebar_appeared`, `page_loaded`)
- Component appearances without user interaction
- Generic "viewed" or "seen" events — already captured by pageview events
**DO track:** user clicks, form submissions, explicit opens/closes, user-initiated actions.
**Exception:** `_exposed` events for A/B experiment exposure tracking are valid even though they fire on render.
**Never track PII** (emails, names, IPs, etc.) in event properties.
Required Pattern
Import `useTrack` from `lib/telemetry/track` (within `apps/studio/`). Never use `useSendEventMutation` (deprecated).
import { useTrack } from 'lib/telemetry/track'
const MyComponent = () => {
const track = useTrack()
const handleClick = () => {
track('product_card_clicked', {
productType: 'database',
planTier: 'pro',
source: 'dashboard',
})
}
return <button onClick={handleClick}>Click me</button>
}Event Definitions
All events must be defined as TypeScript interfaces in `packages/common/telemetry-constants.ts`:
/**
* [Event description]
*
* @group Events
* @source [what triggers this event]
*/
export interface MyFeatureClickedEvent {
action: 'my_feature_clicked'
properties: {
/** Description of property */
featureType: string
}
groups: TelemetryGroups
}Add the new interface to the `TelemetryEvent` union type so `useTrack` picks it up. `@group Events` and `@source` must be accurate.
Review Rules
When reviewing a PR, flag these as **required changes:**
1. **Naming violations** — event not following `[object]_[verb]` snake_case, or using an unapproved verb 2. **Property violations** — not camelCase, generic names, or inconsistent with similar events 3. **Deprecated hook** — any usage of `useSendEventMutation` instead of `useTrack` 4. **Unnecessary view tracking** — events that fire on page load without user interaction 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
When checking property consistency, search `packages/common/telemetry-constants.ts` for similar events and verify property names match.
Well-Formed Event Examples
From the actual codebase:
// User copies a connection string
track('connection_string_copied', {
connectionType: 'psql',
connectionMethod: 'transaction_pooler',
connectionTab: 'Connection String',
})
// User enables a feature preview
track('feature_preview_enabled', {
feature: 'realtime_inspector',
})
// User clicks a banner CTA
track('index_advisor_banner_dismiss_button_clicked')
// Experiment exposure (fires on render — valid exception)
track('home_new_experiment_exposed', {
variant: 'treatment',
})Implementing New Tracking
To add tracking for a user action:
1. **Name the event** — `[object]_[verb]` using approved verbs only 2. **Choose properties** — camelCase preferred for new events; check `packages/common/telemetry-constants.ts` for similar events and match their property names and casing 3. **Add interface to telemetry-constants.ts** — with `@group Events` and `@source` JSDoc, add to the `TelemetryEvent` union type 4. **Add to component** — `import { useTrack } from 'lib/telemetry/track'`, call `track('event_name', { properties })`
Verification checklist
- [ ] Event name follows `[object]_[verb]` with approved verb
- [ ] Event name is snake_case
- [ ] Properties are camelCase and self-explanatory
- [ ] Event defined in te
Read more
name: telemetry-standards 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
Standards for PostHog event tracking in `apps/studio/`. Apply these when reviewing PRs that touch tracking or when implementing new tracking.
Event Naming
**Format:** `[object]_[verb]` in snake_case
**Approved verbs only** (canonical list — derived from `packages/common/telemetry-constants.ts`): opened, clicked, submitted, created, removed, updated, intended, evaluated, added, 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
- `component_rendered` → don't track — no user interaction
Property Standards
**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)
- Mixing camelCase and snake_case within the same event
What NOT to Track
- Passive views/renders on page load (`dashboard_viewed`, `sidebar_appeared`, `page_loaded`)
- Component appearances without user interaction
- Generic "viewed" or "seen" events — already captured by pageview events
**DO track:** user clicks, form submissions, explicit opens/closes, user-initiated actions.
**Exception:** `_exposed` events for A/B experiment exposure tracking are valid even though they fire on render.
**Never track PII** (emails, names, IPs, etc.) in event properties.
Required Pattern
Import `useTrack` from `lib/telemetry/track` (within `apps/studio/`). Never use `useSendEventMutation` (deprecated).
import { useTrack } from 'lib/telemetry/track'
const MyComponent = () => {
const track = useTrack()
const handleClick = () => {
track('product_card_clicked', {
productType: 'database',
planTier: 'pro',
source: 'dashboard',
})
}
return <button onClick={handleClick}>Click me</button>
}Event Definitions
All events must be defined as TypeScript interfaces in `packages/common/telemetry-constants.ts`:
/**
* [Event description]
*
* @group Events
* @source [what triggers this event]
*/
export interface MyFeatureClickedEvent {
action: 'my_feature_clicked'
properties: {
/** Description of property */
featureType: string
}
groups: TelemetryGroups
}Add the new interface to the `TelemetryEvent` union type so `useTrack` picks it up. `@group Events` and `@source` must be accurate.
Review Rules
When reviewing a PR, flag these as **required changes:**
1. **Naming violations** — event not following `[object]_[verb]` snake_case, or using an unapproved verb 2. **Property violations** — not camelCase, generic names, or inconsistent with similar events 3. **Deprecated hook** — any usage of `useSendEventMutation` instead of `useTrack` 4. **Unnecessary view tracking** — events that fire on page load without user interaction 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
When checking property consistency, search `packages/common/telemetry-constants.ts` for similar events and verify property names match.
Well-Formed Event Examples
From the actual codebase:
// User copies a connection string
track('connection_string_copied', {
connectionType: 'psql',
connectionMethod: 'transaction_pooler',
connectionTab: 'Connection String',
})
// User enables a feature preview
track('feature_preview_enabled', {
feature: 'realtime_inspector',
})
// User clicks a banner CTA
track('index_advisor_banner_dismiss_button_clicked')
// Experiment exposure (fires on render — valid exception)
track('home_new_experiment_exposed', {
variant: 'treatment',
})Implementing New Tracking
To add tracking for a user action:
1. **Name the event** — `[object]_[verb]` using approved verbs only 2. **Choose properties** — camelCase preferred for new events; check `packages/common/telemetry-constants.ts` for similar events and match their property names and casing 3. **Add interface to telemetry-constants.ts** — with `@group Events` and `@source` JSDoc, add to the `TelemetryEvent` union type 4. **Add to component** — `import { useTrack } from 'lib/telemetry/track'`, call `track('event_name', { properties })`
Verification checklist
- [ ] Event name follows `[object]_[verb]` with approved verb
- [ ] Event name is snake_case
- [ ] Properties are camelCase and self-explanatory
- [ ] Event defined in te
Supabase is the Postgres development platform. We're building the features of Firebase using enterprise-grade open source tools. [x] Hosted Postgres Database. Docs [x] Authentication and Authorization. Docs [x] Auto-generated APIs. [x] REST. Docs [x] GraphQL.
Repo: supabase/supabase
Other skills on supabase.
- /clickhouse-logs-queries
Write, review, and migrate Supabase logs queries against the ClickHouse-backed `logs` table (the `logs.all.otel` analytics endpoint). Use this whenever a task involves Logs Explorer SQL, the `log_attributes` map, querying a log `source` (edge_logs, postgres_logs, auth_logs,
Open skill - /copywriting
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,
Open skill - /dev-toolbar-review
Safety rules for the dev toolbar, PostHog client, and feature flags. Use
Open skill - /docs-content
Write, edit, organize, and review Supabase content anywhere in apps/docs — guides, explainers, tutorials, troubleshooting entries, reference docs, and partials. Use for MDX/TOML authoring, frontmatter, navigation, terminology, links, code samples, content listings, and docs
Open skill - /react-hook-form
Correct React Hook Form usage anywhere in the monorepo — data flow, subscriptions,
Open skill - /safe-sql-execution
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
Open skill

