svelte-component-auditor

Audit Svelte and SvelteKit components for performance, accessibility, reactive statement usage, store design, and SSR compatibility. Use when reviewing Svelte codebases, optimizing rendering performance, or enforcing component best practices.

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "svelte-component-auditor" with this command: npx skills add charlie-morrison/svelte-component-auditor

Svelte Component Auditor

Deep audit of Svelte and SvelteKit components. Analyzes reactive declarations, store patterns, accessibility, SSR readiness, and rendering performance. Produces prioritized findings with concrete fixes.

Use when: reviewing a Svelte/SvelteKit project, preparing for production, auditing accessibility, or establishing component quality standards.

Analysis Steps

1. Project Discovery

cat package.json 2>/dev/null | jq '{svelte: .devDependencies.svelte, sveltekit: .devDependencies["@sveltejs/kit"]}'
cat svelte.config.js 2>/dev/null || cat svelte.config.ts 2>/dev/null
find . -name "*.svelte" -not -path '*/node_modules/*' -not -path '*/.svelte-kit/*' | wc -l
find . -path "*/routes/*" -name "+*" -not -path '*/node_modules/*' 2>/dev/null | sort | head -20

Determine: Svelte version (4 vs 5 runes), SvelteKit presence, adapter type, component count, route structure.

2. Reactive Statement Audit

# Reactive declarations ($: label syntax — Svelte 4)
grep -rn '^\s*\$:' --include="*.svelte" . 2>/dev/null | head -25

# Reactive assignments that won't trigger (array mutation)
grep -rn '\$:.*\.push\|\$:.*\.splice\|\$:.*\.sort' --include="*.svelte" . 2>/dev/null | head -15

# Complex reactive chains (>5 per component = smell)
for f in $(find . -name "*.svelte" -not -path '*/node_modules/*' 2>/dev/null); do
  count=$(grep -c '^\s*\$:' "$f" 2>/dev/null)
  if [ "$count" -gt 5 ]; then echo "COMPLEX($count): $f"; fi
done | head -15

# Svelte 5 runes
grep -rn '\$state\|\$derived\|\$effect\|\$props' --include="*.svelte" --include="*.svelte.ts" . 2>/dev/null | head -15

Check for:

  • Mutating arrays in reactive declarations: $: items.push(x) won't trigger — must reassign: items = [...items, x]
  • Circular reactive dependencies: cause runtime errors
  • Over-complex reactive chains: >5 $: declarations signals need for store or utility extraction
  • $effect without cleanup: effects with subscriptions/timers must return a cleanup function

3. Store Design Analysis

grep -rn "writable(\|readable(\|derived(" --include="*.ts" --include="*.js" --include="*.svelte" . 2>/dev/null | grep -v 'venv/' | head -20

# Store subscriptions without unsubscribe (leak in non-component code)
grep -rn "\.subscribe(" --include="*.ts" --include="*.js" . 2>/dev/null | head -15

# Auto-subscription in components ($store)
grep -rn '\$[a-zA-Z]' --include="*.svelte" . 2>/dev/null | grep -v '\$:\|//' | head -15

Flag:

  • Store subscriptions in .ts/.js without unsubscribe: auto-unsubscribe ($store) only works in .svelte files
  • Global stores with SSR: module-scope writable stores cause cross-request data leaks — use context or page data
  • Missing derived stores: repeated computations across components should be derived
  • Overloaded stores: single store managing unrelated concerns — split by domain

4. Performance Analysis

# Large components (>200 lines)
for f in $(find . -name "*.svelte" -not -path '*/node_modules/*' 2>/dev/null); do
  lines=$(wc -l < "$f"); if [ "$lines" -gt 200 ]; then echo "LARGE($lines): $f"; fi
done | sort -t'(' -k1.7 -rn | head -10

# Unkeyed each blocks
grep -rn '{#each' --include="*.svelte" . 2>/dev/null | grep -v '(' | head -15

# bind:this overuse
grep -rn "bind:this" --include="*.svelte" . 2>/dev/null | head -15

Flag:

  • Unkeyed each blocks: {#each items as item} without key causes full list re-renders on any change
  • Components >300 lines: decompose into sub-components
  • Excessive bind:this: direct DOM manipulation bypasses reactivity

5. Accessibility Audit

# Images without alt
grep -rn '<img' --include="*.svelte" . 2>/dev/null | grep -v 'alt=' | head -15

# Click handlers on non-interactive elements
grep -rn 'on:click' --include="*.svelte" . 2>/dev/null \
  | grep '<div\|<span\|<li\|<p' | head -15

# Form inputs without labels
grep -rn '<input' --include="*.svelte" . 2>/dev/null \
  | grep -v 'aria-label\|id=.*label\|type="hidden"\|type="submit"' | head -15

# Focus management
grep -rn 'focus()\|tabindex\|aria-live\|aria-expanded' --include="*.svelte" . 2>/dev/null | head -10

Flag with WCAG reference:

  • Images without alt: WCAG 1.1.1 — all <img> must have alt (empty for decorative)
  • Click on non-interactive elements: WCAG 4.1.2 — use <button> or add role="button" + tabindex="0" + keyboard handler
  • Inputs without labels: WCAG 1.3.1 — every form control needs an accessible name
  • No aria-live regions: WCAG 4.1.3 — dynamic status messages need aria-live="polite"

6. SSR Compatibility

# Browser-only APIs used outside onMount
grep -rn 'window\.\|document\.\|localStorage\|sessionStorage\|navigator\.' \
  --include="*.svelte" --include="*.ts" . 2>/dev/null \
  | grep -v 'node_modules\|\.svelte-kit\|onMount\|onDestroy\|browser' | head -15

# $app/environment browser guard
grep -rn "import.*browser.*\$app" --include="*.svelte" --include="*.ts" . 2>/dev/null | head -10

# Data fetching in components instead of load functions
grep -rn "fetch(" --include="*.svelte" . 2>/dev/null | grep -v 'node_modules' | head -10

# Private env leaked to client
grep -rn '\$env/static/private\|\$env/dynamic/private' --include="*.svelte" . 2>/dev/null | head -5

Flag:

  • Browser APIs outside lifecycle hooks: window, document, localStorage at top level crash SSR
  • Missing browser guard: import { browser } from $app/environment to guard browser-only code
  • Cross-request state pollution: module-level mutable state shared across SSR requests
  • Private env in client code: $env/static/private imported in .svelte files leaks secrets
  • Fetching in components: SvelteKit load functions provide streaming, caching, and SSR — component fetch loses these

7. Component API Surface

grep -rn 'export let ' --include="*.svelte" . 2>/dev/null | head -15
grep -rn 'export let [a-zA-Z]*;$' --include="*.svelte" . 2>/dev/null | head -10
grep -rn "createEventDispatcher\|setContext\|getContext" --include="*.svelte" . 2>/dev/null | head -15
grep -rn '\$\$props\|\$\$restProps' --include="*.svelte" . 2>/dev/null | head -10

Flag:

  • Props without defaults: no compile-time enforcement that callers provide them
  • $$props/$$restProps overuse: bypasses Svelte's prop tracking, prevents tree-shaking
  • Missing slot fallback content: <slot>fallback</slot> provides better DX
  • Untyped context: setContext/getContext should use typed keys

Output Template

# Svelte Component Audit — [Project Name]

## Summary
- Components: N | Svelte: 4.x/5.x | SvelteKit: yes/no
- Critical: N | Warnings: N | A11y violations: N

## Critical Findings
### [C1] SSR Crash — `window.innerWidth` at top level
- **File**: src/routes/dashboard/+page.svelte:8
- **Fix**: Move inside `onMount(() => { ... })`

### [C2] Cross-Request State Leak
- **File**: src/lib/stores/user.ts:3 — module-scope writable
- **Fix**: Initialize in load functions or context API

## Accessibility Violations
| Rule | Count | Severity | Files |
|------|-------|----------|-------|
| img-alt-missing | N | Critical | file1, file2 |
| click-on-div | N | High | file3 |
| input-no-label | N | High | file4 |

## Performance Issues
| Issue | File | Fix |
|-------|------|-----|
| Unkeyed each block | List.svelte:24 | Add `(item.id)` key |
| 450-line component | Dashboard.svelte | Split into sub-components |

## Recommendations
1. Fix N SSR-breaking browser API usages
2. Add keys to N each blocks
3. Resolve N accessibility violations
4. Move N module-scope stores to context/load for SSR safety
5. Add `+error.svelte` at route group levels

Tips

  • Run npx svelte-check for type errors, a11y warnings, and unused CSS
  • Use @sveltejs/enhanced-img for automatic image optimization in SvelteKit
  • Enable compilerOptions.runes: true in svelte.config.js to start Svelte 5 migration
  • Use {#key expression} to force-recreate a component when data changes
  • Test SSR locally with adapter-node before deploying to catch browser API issues

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

Profiling Driven Performance Optimization

Optimize code performance by first refactoring to a well-factored structure, then running a profiler to find actual hot spots, and applying targeted optimiza...

Registry SourceRecently Updated
1670Profile unavailable
Coding

Rau — 前端全栈AI时代工程心智

Rau — 顶级前端工程师虚拟心智模型。 融合 Guillermo Rauch(Vercel CEO / Next.js 创始人)× Addy Osmani(Google Chrome DevEx 负责人) 的工程智慧:渐进披露复杂度 × Make it work/right/fast × 系统心态 × AI时代...

Registry SourceRecently Updated
1010Profile unavailable
Coding

Frontend Architecture Pro

Provide technical UX architecture and CSS systems to establish design tokens, layout frameworks, component structure, responsive breakpoints, and theme toggles.

Registry SourceRecently Updated
1470Profile unavailable
Coding

UI Designer

Design and improve UI components and systems with pixel-perfect, accessible, scalable designs including tokens, libraries, theming, and handoff specs.

Registry SourceRecently Updated
1790Profile unavailable