Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 86 additions & 40 deletions .claude-skills/frontend-debugging_skill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,76 +19,122 @@
### Phase 1: Health Check
```bash
task frontend:dev
# Check browser console
# Check browser console for errors
# Verify page loads without JavaScript errors
```

### Phase 2: Type Safety
```bash
task frontend:typecheck
task frontend:lint
# Ensure no TypeScript or linting errors
```

### Phase 3: Encore Client Sync
```bash
task founder:workflows:regen-client
# Verify ~encore/clients imports
# Verify ~encore/clients imports work
# Check generated types are latest
```

### Phase 4: Svelte 5 Runes
- Check proper rune usage
- $state for reactive state
- $derived for computed values
- $effect for side effects
- $props for component props
- ✅ Check proper rune usage ($state, $derived, $effect, $props)
- ✅ Verify runes only in `.svelte` files (not `.ts`)
- ✅ Ensure top-level declarations
- ✅ Check for conditional rune usage (not allowed)

### Phase 5: Routing
- Verify +page.svelte structure
- Check +layout.svelte hierarchy
- Review load functions

### Phase 6: API Calls
- Always use Encore generated client
- Never manual `fetch()` calls
- Full type safety guaranteed
- ✅ Verify file structure: `+page.svelte`, `+layout.svelte`
- ✅ Check dynamic routes: `[id]/+page.svelte`
- ✅ Review load functions return correct shape
- ✅ Test URL navigation with `goto()` or click

### Phase 6: API Calls & Data Loading
- ✅ Always use Encore generated client
- ✅ Never manual `fetch()` calls
- ✅ Full type safety guaranteed
- ✅ Verify load functions execute on server + client
- ✅ Check WebSocket streams connected properly

### Phase 7: SSR/CSR Issues
- Check server vs browser context
- Verify `browser` checks when needed
- ✅ Check server vs browser context
- ✅ Verify `browser` checks when needed
- ✅ Test `+page.server.ts` vs `+page.ts` load functions
- ✅ Ensure no DOM API calls during SSR

### Phase 8: Component Isolation
- Test component in isolation
- Check props/slots/events
- ✅ Test component in isolation
- ✅ Check $props destructuring correct
- ✅ Verify slot/snippet usage
- ✅ Test with different prop values

### Phase 9: Build Testing
### Phase 9: E2E Testing
```bash
task frontend:build
# Test production build
task frontend:test
# Run Playwright tests in headed mode
HEADLESS=false bun run test:e2e:headed
```

**Key E2E patterns:**
- Race navigation + API with `Promise.all([page.waitForURL(...), button.click()])`
- Use data attributes for reliable selectors: `data-testid="name"`
- Wait for final output (rendered screenshots), not intermediate states
- Avoid sequential waits (waitForResponse → waitForURL) which cause hangs

### Phase 10: Browser DevTools
- Use Svelte DevTools extension
- Check component state/props
- Review network requests
- ✅ Svelte DevTools extension: inspect component state
- ✅ Network tab: verify API calls, WebSocket connections
- ✅ Console: check for errors/warnings
- ✅ Performance: check for rendering slowdowns

---

## Common Issues
## Common Issues & Fixes

### E2E Test Hangs
**Problem:** `page.waitForResponse()` + `page.waitForURL()` in sequence causes timeout

**Fix:**
```typescript
// ❌ BAD: Sequential waits
await button.click();
await page.waitForResponse(...); // HANGS
await page.waitForURL(...);

// ✅ GOOD: Parallel waits
await Promise.all([
page.waitForURL(/\/run\/[a-f0-9-]+/i, {
waitUntil: "domcontentloaded",
timeout: 30000
}),
button.click()
]);
```

### Rune Misuse
- Can't use runes in `.ts` files (only `.svelte`)
- Must be top-level declarations
- No conditional runes
- ❌ Can't use runes in `.ts` files (only `.svelte`)
- ❌ Must be top-level declarations (no inside functions)
- ❌ No conditional runes
- ✅ Use reactive event handlers with `$effect` instead

### API Type Errors
- Regenerate client after backend changes
- Verify import paths use `~encore/clients`

### SSR Hydration
- Match server/client rendered output
- Check for browser-only code in wrong places

### Routing Issues
- File-based routing: check file structure
- Dynamic routes: `[slug]/+page.svelte`
- Verify load functions return correct shape
- ❌ Forgot to regenerate client after backend changes
- ❌ Wrong import path (should be `~encore/clients` not `./encore-client`)
- ✅ Run `task founder:workflows:regen-client` after backend API changes

### SSR Hydration Mismatch
- ❌ Server renders different HTML than client
- ❌ Using browser-only APIs in +page.ts (should be +page.server.ts)
- ✅ Check timestamp/random values match between server and client render

### Navigation Not Working
- ❌ Using manual `goto()` without waiting for page ready
- ❌ Link navigation blocked by unsaved form data
- ✅ Test selector matches actual button: use `getByRole()` or `data-testid`

### WebSocket/Streaming Failures
- ❌ CORS issues with WebSocket endpoint
- ❌ Backend endpoint not registered (needs server restart)
- ✅ Check browser console for connection errors
- ✅ Verify endpoint exists via `browser.snapshot()` inspection

108 changes: 107 additions & 1 deletion .claude-skills/frontend-development_skill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,110 @@ console.log('User logged in:', user);

---

## E2E Testing Patterns

### 1. **Testing User Flows (Playwright)**

Write deterministic E2E tests that verify complete user journeys:

```typescript
// ✅ GOOD: Test complete user flow
test("run validation", async ({ page }) => {
// 1. Navigate to landing
await page.goto("/");
await expect(page).toHaveTitle(/ScreenGraph/i);

// 2. Start run via CTA
const button = page.getByRole("button", { name: /detect.*drift/i });
await expect(button).toBeVisible();

// 3. Handle navigation + API response together
await Promise.all([
page.waitForURL(/\/run\/[a-f0-9-]+/i, {
waitUntil: "domcontentloaded",
timeout: 30000
}),
button.click()
]);

// 4. Verify UI fully loaded
const heading = page.getByRole("heading", { name: /run timeline/i });
await expect(heading).toBeVisible();

// 5. Verify data appears (events, screenshots)
const events = page.locator('[data-testid="run-events"]');
await expect(events).toBeVisible();
});
```

### 2. **Test Selectors with Data Attributes**

Always use data attributes for reliable test selectors:

```svelte
<!-- ✅ GOOD: Data attributes for testing -->
<div class="run-events" data-testid="run-events">
{#each events as event}
<div data-event-kind={event.kind}>
{event.kind}
</div>
{/each}
</div>

<!-- ✅ GOOD: Semantic selectors -->
<button class="btn variant-filled-primary">
{#if loading}
Starting...
{:else}
Detect My First Drift
{/if}
</button>

<!-- ❌ BAD: Fragile selectors -->
<div class="space-y-4">
{#each events}
<div class="card">Event</div>
{/each}
</div>
```

### 3. **Handling Navigation + API Together**

Never wait for API response then navigation—race them together:

```typescript
// ❌ BAD: Sequential waits (Playwright hangs)
await button.click();
await page.waitForResponse(...); // Hangs!
await page.waitForURL(...);

// ✅ GOOD: Parallel with Promise.all
await Promise.all([
page.waitForURL(/\/run\/[a-f0-9-]+/i, {
waitUntil: "domcontentloaded",
timeout: 30000
}),
button.click()
]);
```

### 4. **Verifying Real-Time Data**

Wait for content to appear, not intermediate states:

```typescript
// ❌ BAD: Wait for intermediate status
await page.waitForSelector('[data-event="agent.event.screenshot_captured"]');

// ✅ GOOD: Wait for final rendered output
const gallery = page.locator('[data-testid="discovered-screens"] img');
await expect(gallery.first()).toBeVisible({ timeout: 20000 });
const count = await gallery.count();
expect(count).toBeGreaterThan(0);
```

---

## Quality Checklist

Before committing frontend code, verify:
Expand All @@ -622,6 +726,7 @@ Before committing frontend code, verify:
- [ ] Uses AutoAnimate for transitions
- [ ] Follows file-based routing conventions
- [ ] American English spelling (canceled, color, etc.)
- [ ] Data attributes (`data-testid`, `data-event-*`) for test selectors
- [ ] Build passes: `bun run build`
- [ ] Type check passes: `bun run check`

Expand All @@ -635,10 +740,11 @@ Before committing frontend code, verify:
- [Svelte 5 Docs](https://svelte.dev/docs/svelte/overview)
- [Tailwind CSS v4](https://tailwindcss.com/docs)
- [AutoAnimate](https://auto-animate.formkit.com/)
- [Playwright Testing](https://playwright.dev/docs/intro)

---

**Last Updated:** 2025-11-07
**Last Updated:** 2025-11-11
**Maintainer:** ScreenGraph Team
**Status:** Active ✅

1 change: 1 addition & 0 deletions .cursor/commands/bug-approach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Identify the bug (Jira docs, Graphiti, docs notes); capture acceptance criteria and suspected surface area.
Loading
Loading