mirror of
https://github.com/supabase/supabase.git
synced 2026-05-07 01:10:15 -04:00
4295e41e81
Migrates all studio-related Cursor rules to Claude skills and adds a top-level `.claude/CLAUDE.md` for project context. Docs rules left in place. **Decisions:** - Only studio + testing rules migrated — docs rules intentionally left in `.cursor/rules/docs/` - Vitest skill already shared via symlink (`.claude/skills/vitest` → `.agents/skills/vitest`) — nothing to migrate - Grouped ~21 granular cursor rules into 5 new skills + 1 updated skill by topic - `studio-architecture` skill fully merged into `CLAUDE.md` and deleted to avoid overlap - Skills are self-contained (content inlined, not relying on sub-files) since Claude reads SKILL.md first - Skills cross-reference each other inline where relevant (e.g. best-practices → testing, error-handling, queries) - No `paths` frontmatter — would auto-inject full skill content on every matching file. Current description-based matching is more selective and token-efficient. **Removed:** - `.cursor/rules/studio/` (21 rule files covering architecture, best practices, UI patterns, queries, styling, etc.) - `.cursor/rules/testing/` (e2e-studio + unit-integration rules) - `.cursor/rules/studio-useStaticEffectEvent.mdc` - `.claude/skills/studio-architecture/` — fully merged into CLAUDE.md to avoid duplication - `.claude/skills/studio-testing/rules/` — orphaned sub-files after inlining content into SKILL.md **Added:** - `.claude/CLAUDE.md` — concise monorepo overview with structure, commands, and conventions. Absorbs studio-architecture content. References `studio-*` skills for detail. - `.claude/skills/studio-best-practices/` — boolean naming, component structure, loading/error/success patterns, state management, hooks, TypeScript conventions. Cross-references `vercel-composition-patterns`, `studio-ui-patterns`, `studio-queries`, `studio-error-handling`, and `studio-testing` inline where relevant. - `.claude/skills/studio-ui-patterns/` — layout, forms, tables, charts, empty states, navigation, cards, alerts, sheets. Grouped from ~10 separate cursor rules into one cohesive skill. - `.claude/skills/studio-queries/` — React Query `queryOptions` pattern, `keys.ts` structure, mutation hook template, imperative fetching. - `.claude/skills/use-static-effect-event/` — the `useStaticEffectEvent` hook: when to use, when not to, patterns, implementation. **Changed:** - `.claude/skills/studio-e2e-tests/` — renamed from `e2e-studio-tests` for `studio-*` naming consistency. Merged race condition, waiting strategy, test structure, assertion, and cleanup patterns from the cursor e2e rule. - `.claude/skills/studio-testing/` — inlined key content from sub-rule files directly into SKILL.md so it's self-contained. Removed broken `AGENTS.md` reference. Deleted orphaned `rules/` sub-files. - `.claude/skills/vercel-composition-patterns/` — added note that Studio uses React 18, so React 19 patterns should be skipped. - `.gitignore` — added `!.claude/CLAUDE.md` exception so it's tracked. ## To test - Open Claude Code in the repo, verify `.claude/CLAUDE.md` loads as project context - Ask Claude about Studio conventions and verify it references the right skills - Check that `studio-*` skills appear in the skill list --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2.2 KiB
2.2 KiB
applyTo
| applyTo |
|---|
| e2e/studio/**,apps/studio/** |
Studio E2E Test Review Rules
All comments are advisory.
Selector Priority (best to worst)
-
getByRolewith accessible name — most robust, tests accessibilitypage.getByRole('button', { name: 'Save' }) -
getByTestId— stable, explicit test hookspage.getByTestId('table-editor-side-panel') -
getByTextwith exact match — good for unique textpage.getByText('Data API Access', { exact: true }) -
locatorwith CSS — use sparingly, more fragilepage.locator('[data-state="open"]')
Patterns to Flag
-
XPath selectors — fragile to DOM changes
// BAD locator('xpath=ancestor::div[contains(@class, "space-y")]') -
Parent traversal with
locator('..')— breaks when structure changes// BAD element.locator('..').getByRole('button') -
waitForTimeout— never use; wait for something specific instead// BAD await page.waitForTimeout(1000) // GOOD — wait for UI element await expect(page.getByText('Success')).toBeVisible() // GOOD — wait for API response const apiPromise = waitForApiResponse(page, 'pg-meta', ref, 'query?key=table-create') await saveButton.click() await apiPromise -
force: trueon clicks — make elements visible first instead// BAD await menuButton.click({ force: true }) // GOOD — hover to reveal, then click await tableRow.hover() await expect(menuButton).toBeVisible() await menuButton.click() -
Broad
filter({ hasText })on generic elements — may match multiple elements; scope to specific containers instead
Good Practices to Encourage
- Scope selectors to containers:
page.getByTestId('side-panel').getByRole('switch') - Add
aria-labelto icon-only buttons in source code for better test selectors - Use
test.describe.configure({ mode: 'serial' })for tests sharing database state - Add messages to expects:
await expect(locator, 'why').toBeVisible({ timeout: 30000 })
Canonical standard: .claude/skills/studio-e2e-tests/SKILL.md