К основному содержанию
правило

svelte · sanjeed5 — правило для Cursor: Svelte 5, руны и TypeScript

Правило для Cursor задаёт, как писать компоненты Svelte 5: руны вместо старой реактивности, типизация и ключи в списках. Пригодится, если проект уже на Svelte 5.

Установить в Cursor · Вручную: положить файлы Все способы и платформы ↓
.cursor/rules/svelte.mdc
Открыть на GitHub

Что делает svelte

Правило описывает стиль кода для Svelte 5 с TypeScript и подключается к файлам **/*.{svelte,js,ts}. Оно требует lang="ts" во всех блоках <script> и советует держать логику, разметку и стили в одном .svelte-файле, без выноса простых вычислений в отдельные модули.

Реактивность разложена по рунам: состояние через $state, производные значения через $derived, побочные действия через $effect, свойства компонента через $props(). Старый синтаксис вроде export let, $: и on:click помечен как неправильный. Для глобального состояния оставлены stores, но только когда состояние реально общее для многих компонентов.

Из производительности правило требует уникальный ключ в блоках {#each} и динамический импорт для того, что не нужно при первой загрузке. Если ваш проект ещё на Svelte 4, эти примеры конфликтуют с текущим кодом — сначала обновите версию, потом включайте правило. В исходнике разбор типичных ошибок обрывается на разделе про зависимости $effect.

Какие задачи решает

  • перевести компоненты со старой реактивности на руны Svelte 5
  • убрать export let и on:click из нового кода
  • включить проверку типов в блоках <script>
  • починить перерисовку списка через ключ в {#each}
  • отделить производные значения от побочных эффектов

Примеры запросов агенту

  • перепиши этот компонент на руны Svelte 5
  • проверь файл по правилу svelte и покажи отступления
  • добавь типы пропсам через $props()

Как установить svelte

Вручную: положить файлы

.cursor/rules/svelte.mdc

Во frontmatter: description, globs, alwaysApply

По шагам, с командами для каждой платформы: Cursor rules: файлы .mdc, четыре режима и замена .cursorrules

Вопросы о svelte

Как установить правило svelte в Cursor?

Создайте файл .cursor/rules/svelte.mdc в корне проекта и вставьте в него содержимое правила. Cursor подхватит его для файлов, подходящих под маску **/*.{svelte,js,ts}.

Что делает правило svelte?

Задаёт стиль кода для Svelte 5 с TypeScript: руны $state, $derived, $effect и $props(), типизация в <script lang="ts">, ключи в {#each}. Агент опирается на него, когда пишет или правит компоненты.

Подойдёт ли правило для Svelte 4?

Нет. Примеры построены на рунах Svelte 5, а привычные export let и $: помечены как неправильные, поэтому в проекте на Svelte 4 правило будет спорить с существующим кодом.

Исходный текст

svelte.mdc · CC0-1.0
---
description: Definitive guide for writing clean, performant, and maintainable Svelte 5 applications using the runes API and modern TypeScript practices.
globs: **/*.{svelte,js,ts}
---
# Svelte Best Practices (Svelte 5 + TypeScript)

This guide outlines the definitive best practices for developing Svelte 5 applications with TypeScript. We prioritize explicit reactivity, strong typing, and compiler-driven performance.

## 1. Code Organization and Structure

Always structure your Svelte components for clarity and maintainability.

### 1.1. HTML-First Component Design

Keep your component logic, markup, and styles co-located within the `.svelte` file. This is Svelte's core philosophy.

**❌ BAD: Over-abstracting into separate JS files for simple logic**
```svelte
<!-- MyComponent.svelte -->
<script lang="ts">
  import { calculateValue } from './utils'; // Unnecessary abstraction
  let count = $state(0);
  let computed = $derived(calculateValue(count));
</script>
```

**✅ GOOD: Keep related logic within the component**
```svelte
<!-- MyComponent.svelte -->
<script lang="ts">
  let count = $state(0);
  let computed = $derived(count * 2 + 1); // Simple logic stays here
</script>
```

### 1.2. TypeScript Everywhere

Use `lang="ts"` in all `<script>` tags. Configure `svelte-check` in CI and use the VS Code extension for real-time feedback.

**❌ BAD: Missing `lang="ts"`**
```svelte
<script>
  let name: string = 'world'; // No type checking
</script>
```

**✅ GOOD: Explicitly enable TypeScript**
```svelte
<script lang="ts">
  let name: string = 'world'; // Full type safety
</script>
```

## 2. Component Architecture (Svelte 5 Runes)

Svelte 5's runes API makes reactivity explicit and powerful. Embrace it fully.

### 2.1. Explicit Reactive State with `$state`

Declare all reactive state using `$state`. This makes your component's reactivity clear and refactor-friendly.

**❌ BAD: Implicit reactivity (Svelte 4 style)**
```svelte
<script lang="ts">
  let count = 0; // Not reactive outside top-level
  function increment() { count++; }
</script>
```

**✅ GOOD: Explicit `$state` for all reactive variables**
```svelte
<script lang="ts">
  let count = $state(0); // Clearly reactive
  function increment() { count++; }
</script>
```

### 2.2. Derived State with `$derived`

Use `$derived` for any value that is a pure computation of other reactive state.

**❌ BAD: `$effect` or `$:` for derived values**
```svelte
<script lang="ts">
  let count = $state(0);
  $effect(() => { // Incorrectly using effect for derivation
    console.log('Count changed:', count);
    // This is a side effect, not a derivation
  });
  $: doubled = count * 2; // Svelte 4 style, less explicit
</script>
```

**✅ GOOD: `$derived` for pure computations**
```svelte
<script lang="ts">
  let count = $state(0);
  let doubled = $derived(count * 2); // Clearly a derived value
</script>
```

### 2.3. Side Effects with `$effect`

Reserve `$effect` for actual side effects (e.g., DOM manipulation, API calls, logging).

**❌ BAD: Mixing derivations and effects**
```svelte
<script lang="ts">
  let count = $state(0);
  $: if (count > 5) { // Svelte 4 style, combines derivation and effect
    alert('Count is too high!');
  }
</script>
```

**✅ GOOD: Clear separation of concerns**
```svelte
<script lang="ts">
  let count = $state(0);
  $effect(() => { // Clearly a side effect
    if (count > 5) {
      alert('Count is too high!');
    }
  });
</script>
```

### 2.4. Component Properties with `$props`

Declare all component properties using the `$props()` rune and destructuring. This provides powerful type safety and flexibility.

**❌ BAD: `export let` (Svelte 4 style)**
```svelte
<script lang="ts">
  export let name: string;
  export let age: number = 30;
</script>
```

**✅ GOOD: `$props()` for properties**
```svelte
<script lang="ts">
  interface Props {
    name: string;
    age?: number; // Optional prop
  }
  let { name, age = 30 }: Props = $props();
</script>
```

### 2.5. Event Handling

Remove the `on:` prefix for event handlers. They are now standard properties.

**❌ BAD: `on:click`**
```svelte
<button on:click={() => alert('Clicked!')}>Click me</button>
```

**✅ GOOD: `onclick` (standard HTML attribute)**
```svelte
<button onclick={() => alert('Clicked!')}>Click me</button>
```

### 2.6. Slots and Snippets

Use `{@render}` for rendering slots and snippets, providing type safety and better control over content.

**❌ BAD: Untyped slots**
```svelte
<!-- MyComponent.svelte -->
<slot />
```

**✅ GOOD: Typed snippets for predictable content**
```svelte
<!-- MyComponent.svelte -->
<script lang="ts">
  import type { Snippet } from 'svelte';
  let { header }: { header: Snippet } = $props();
</script>
<div>
  {@render header()}
  <slot />
</div>
```

## 3. State Management

Prioritize local component state with `$state`. Use Svelte stores for truly global or complex cross-component state.

### 3.1. Local State First

Most state should live within the component using `$state`.

**❌ BAD: Over-reliance on global stores for simple component state**
```svelte
// store.ts
import { writable } from 'svelte/store';
export const localCounter = writable(0); // Unnecessary global
```

**✅ GOOD: Use `$state` for component-local reactivity**
```svelte
<script lang="ts">
  let count = $state(0); // Local to this component
</script>
```

### 3.2. Svelte Stores for Global State

For state shared across many components or complex application-wide state, use Svelte's built-in stores.

```ts
// src/lib/stores/auth.ts
import { writable } from 'svelte/store';
export const isAuthenticated = writable(false);
export const user = writable<{ id: string; name: string } | null>(null);
```
```svelte
<!-- AuthStatus.svelte -->
<script lang="ts">
  import { isAuthenticated, user } from '$lib/stores/auth';
</script>
{#if $isAuthenticated}
  <p>Welcome, {$user?.name}!</p>
{:else}
  <p>Please log in.</p>
{/if}
```

## 4. Performance Considerations

SvelteKit handles many optimizations automatically. Supplement these with mindful coding.

### 4.1. `{#each}` with Keys

Always provide a unique `key` to `{#each}` blocks for efficient DOM updates.

**❌ BAD: Missing `key`**
```svelte
{#each items as item}
  <ItemComponent {item} />
{/each}
```

**✅ GOOD: Use a unique `key`**
```svelte
{#each items as item (item.id)}
  <ItemComponent {item} />
{/each}
```

### 4.2. Dynamic Imports for Lazy Loading

Lazy-load components or modules that aren't immediately needed to reduce initial bundle size.

```svelte
<script lang="ts">
  let showModal = $state(false);
  async function openModal() {
    const { default: Modal } = await import('./Modal.svelte');
    // Render Modal component
    showModal = true;
  }
</script>
{#if showModal}
  <Modal />
{/if}
<button onclick={openModal}>Open Modal</button>
```

## 5. Common Pitfalls and Gotchas

Avoid these common mistakes to ensure robust and predictable Svelte applications.

### 5.1. Misunderstanding `$effect` Dependencies

`$effect` runs when its *dependencies* change. Be explicit about what it depends on.

**❌ BAD: Implicit dependencies or missing cleanup**
```svelte
<script lang="ts">
  let count = $state(0);
  $effect(() => {
    // This effect might not re-run if `count` isn't directly used
    // or if `doSomething` has internal state changes not tracked by Svelte.
    doSomething(count);
  });
</script>
```

**✅ GOOD: Explicit dependencies and cleanup**
```svelte
<script lang="ts">
  let count = $state(0);
  $effect(() => {
    const timer = setInterval(() => {
      console.log('Count is', count); // `count` is a dependency
    }, 1000);
    return () => clearInterval(timer); // Cleanup function
  });
</script>
```

### 5.2. Forgetting `generics` Attribute

When creating generic components, remember to add the `generics` attribute to the `<script>` tag.

**❌ BAD: Untyped generic props**
```svelte
<script lang="ts">
  interface Props { items: any[]; } // Loses type safety
  let { items }: Props = $props();
</script>
```

**✅ GOOD: Explicit generics for type safety**
```svelte
<script lang="ts" generics="Item extends { id: string }">
  interface Props { items: Item[]; }
  let { items }: Props = $props();
</script>
```

## 6. Accessibility

Build accessible Svelte applications by default.

### 6.1. Semantic HTML

Always prefer semantic HTML elements over generic `div`s or `span`s.

**❌ BAD: Non-semantic button**
```svelte
<div onclick={handleClick} role="button" tabindex="0">Click me</div>
```

**✅ GOOD: Semantic HTML element**
```svelte
<button onclick={handleClick}>Click me</button>
```

### 6.2. ARIA Attributes

Use ARIA attributes when semantic HTML isn't sufficient, but only when necessary.

```svelte
<label for="username">Username</label>
<input id="username" type="text" aria-describedby="username-hint" />
<p id="username-hint">Your username must be unique.</p>
```

## 7. Testing Approaches

Implement a robust testing strategy for Svelte applications.

### 7.1. Unit Testing with Vitest and Svelte Testing Library

Use `vitest` for your test runner and `@testing-library/svelte` for component testing.

```ts
// src/lib/components/Counter.test.ts
import { render, screen } from '@testing-library/svelte';
import { expect, test } from 'vitest';
import Counter from './Counter.svelte';

test('Counter increments value on click', async () => {
  render(Counter);
  const button = screen.getByRole('button', { name: /Count:/i });
  expect(button).toHaveTextContent('Count: 0');
  await button.click();
  expect(button).toHaveTextContent('Count: 1');
});
```

### 7.2. End-to-End (E2E) Testing

For critical user flows, use `Playwright` or `Cypress`.

```ts
// tests/example.spec.ts (Playwright)
import { test, expect } from '@playwright/test';

test('homepage has title and intro text', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveTitle(/SvelteKit/);
  await expect(page.locator('h1')).toHaveText('Welcome to SvelteKit');
});
```

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Похожие правила IDE

Все правила IDE по теме «Фронтенд и UI» →

Сначала — svelte от других авторов.

svelte PatrickJS Правило для Cursor с набором практик по Svelte: структура компонентов, реактивность, сторы, роутинг через SvelteKit и тесты. Пригодится, когда агент пишет или правит код на Svelte. ★ 41 011звёзд репо svelte-components spences10 Подсказывает агенту, как строить компоненты Svelte: headless-библиотеки, веб-компоненты и формы, которые не оборачивают поля ввода. CX Codex +1 531установок tauri-svelte-typescript-guide-cursorrules-prompt-f PatrickJS Правило для Cursor, которое задаёт агенту стиль работы с десктопными приложениями на Tauri: Svelte во фронтенде, TypeScript для типов. ★ 41 011звёзд репо svelte-code-writer sveltejs Скилл ищет официальную документацию Svelte 5 и проверяет компоненты через autofixer. Пригодится при написании и правке файлов .svelte или .svelte.ts. CX Codex +1 12 900установок svelte-core-bestpractices sveltejs Скилл объясняет агенту, как писать код на Svelte с рунами: $state, $derived, события, стили. Пригодится, когда агент правит компоненты в проекте на Svelte. CX Codex +1 10 900установок svelte-debug davila7 Разбирает ошибки Svelte и SvelteKit по сообщению и стеку: находит причину в компиляции, рантайме или конфиге и предлагает правку. 134установок svelte-runes spences10 Помогает ИИ-агенту писать код на Svelte 5 с рунами без смешивания устаревшего синтаксиса. Пригодится при настройке реактивности, пропсов и миграции компонентов. CX Codex +1 1 000установок

Из того же набора69

unittest Правило задаёт агенту стандарт оформления тестов на unittest: структура каталогов, имена классов и методов, ассерты, моки. ★ 3 579звёзд репо transformers Правило для Cursor задаёт стиль работы с библиотекой 🤗 Transformers: модульные модели, типизация, Trainer вместо ручных циклов обучения. ★ 3 579звёзд репо tornado Правило для Cursor задаёт стиль кода в Tornado: только async/await для ввода-вывода, полные аннотации типов и один обработчик ошибок на всё приложение. ★ 3 579звёзд репо three-js Правило для Cursor задаёт стандарты разработки на three.js: обработка ошибок WebGL, ленивая загрузка ассетов, оптимизация цикла рендера и освобождение ресурсов. ★ 3 579звёзд репо streamlit Правило для Cursor задаёт, как писать приложения на Streamlit: кэшировать тяжёлые операции, держать UI отдельно от логики и разбивать проект на модули. ★ 3 579звёзд репо sqlalchemy Правило для Cursor задаёт стиль SQLAlchemy 2.x: типизированные модели, сессии через контекстный менеджер, select() вместо устаревшего Query. ★ 3 579звёзд репо solidity Правило задаёт стиль и требования к Solidity-коду: фиксированный pragma, кастомные ошибки, защита от реентрантности. Пригодится, когда пишете контракты в Cursor. ★ 3 579звёзд репо shadcn Правило для Cursor задаёт команде единый стиль работы с shadcn/ui: структура папок, типы, варианты через CVA, формы на React Hook Form и Zod. Пригодится, когда компонентов становится много. ★ 3 579звёзд репо

Спонсоры проекта

Компании, которые помогают держать аналитику открытой