Related Skills: See query-layer for TanStack Query integration. See styling for CSS and Tailwind conventions.
Works with
AI-first code editor with Composer
Before installing skills in Cursor, ensure your development environment meets these requirements:
node --versionsvelteExecute the skills CLI command in your project's root directory to begin installation:
Fetches svelte from epicenterhq/epicenter and configures it for Cursor.
The CLI shows a list of agents. Use arrow keys and space to select Cursor:
Confirm successful installation by checking the skill directory location:
Restart Cursor to activate svelte. Access via /svelte in your agent's command palette.
We perform automated surface-level scans (Gen AI Scanner, Socket, Snyk) during installation. These checks detect common vulnerabilities but do not guarantee complete security. Always review skill source code and verify the publisher's reputation before production use.
Skills execute code in your environment. Always review source, verify the publisher, and test in isolation before production.
Submit your Claude Code skill and start earning
Automate repetitive workflows and reduce manual effort
Example
Generate reports, summarize documents, draft communications
Save 3-5 hours per week on routine tasks
Learn new skills, understand complex topics, get expert guidance
Example
Explain concepts, provide examples, suggest learning resources
Accelerate learning and skill development by 2x
Enhance output quality through reviews, suggestions, and refinements
Example
Review drafts, suggest improvements, catch errors
Improve work quality by 30-40% with less effort
0
total installs
0
this week
4.4K
GitHub stars
0
upvotes
Run in your terminal
0
installs
0
this week
4.4K
stars
Related Skills: See
query-layerfor TanStack Query integration. Seestylingfor CSS and Tailwind conventions.
Use this pattern when you need to:
$derived mappings with satisfies Record lookups.createMutation in .svelte and .execute() in .ts.handle* wrappers into inline template actions.Load these on demand based on what you're working on:
createMutation, .execute(), onSuccess/onError), read references/tanstack-query-mutations.mdfromTable, fromKv, $derived arrays, state factories), read references/reactive-state-pattern.mdSpinner, Empty.*, {#await} blocks), read references/loading-empty-states.md$derived Value Mapping: Use satisfies Record, Not TernariesWhen a $derived expression maps a finite union to output values, use a satisfies Record lookup. Never use nested ternaries. Never use $derived.by() with a switch just to map values.
<!-- Bad: nested ternary in $derived -->
<script lang="ts">
const tooltip = $derived(
syncStatus.current === 'connected'
? 'Connected'
: syncStatus.current === 'connecting'
? 'Connecting…'
: 'Offline',
);
</script>
<!-- Bad: $derived.by with switch for a pure value lookup -->
<script lang="ts">
const tooltip = $derived.by(() => {
switch (syncStatus.current) {
case 'connected': return 'Connected';
case 'connecting': return 'Connecting…';
case 'offline': return 'Offline';
}
});
</script>
<!-- Good: $derived with satisfies Record -->
<script lang="ts">
import type { SyncStatus } from '@epicenter/sync-client';
const tooltip = $derived(
({
connected: 'Connected',
connecting: 'Connecting…',
offline: 'Offline',
} satisfies Record<SyncStatus, string>)[syncStatus.current],
);
</script>
Why satisfies Record wins:
$derived() stays a single expression — no need for $derived.by().Reserve $derived.by() for multi-statement logic where you genuinely need a function body. For value lookups, keep it as $derived() with a record.
as const is unnecessary when using satisfies. satisfies Record<T, string> already validates shape and value types.
See docs/articles/record-lookup-over-nested-ternaries.md for rationale.
Use SvelteMap when items have stable IDs and you need keyed lookup. Use $state for primitives, local UI booleans, and sequential data without identity.
| Data Shape | Use | Example |
|---|---|---|
| Workspace table rows (have IDs) | fromTable() → SvelteMap |
recordings, conversations, notes |
| Workspace KV (single key) | fromKv() |
selectedFolderId, sortBy |
| Browser API keyed data | new SvelteMap() + listeners |
Chrome tabs, windows |
| Primitive value | $state(value) |
$state(false), $state(''), $state(0) |
| Sequential data without IDs | $state<T[]>([]) |
terminal history, command history |
| Ordered list where position matters | $state<T[]>([]) |
open file tab order |
// ❌ BAD: O(n) lookups, coarse reactivity, referential instability
let conversations = $state<Conversation[]>(readAll());
const metadata = $derived(conversations.find((c) => c.id === id)); // O(n) scan
// ✅ GOOD: O(1) lookups, per-key reactivity, stable $derived array
const conversationsMap = fromTable(workspace.tables.conversations);
const conversations = $derived(
conversationsMap.values().toArray().sort((a, b) => b.updatedAt - a.updatedAt),
);
const metadata = $derived(conversationsMap.get(id)); // O(1) lookup
Three problems with $state<T[]> for keyed data:
.find() scans the whole arraySee docs/articles/sveltemap-over-state-for-keyed-collections.md for the full rationale.
When a factory function exposes workspace table data via fromTable, follow this three-layer convention:
// 1. Map — reactive source (private, suffixed with Map)
const foldersMap = fromTable(workspaceClient.tables.folders);
// 2. Derived array — cached materialization (private, no suffix)
const folders = $derived(foldersMap.values().toArray());
// 3. Getter — public API (matches the derived name)
return {
get folders() {
return folders;
},
};
Naming: {name}Map (private source) → {name} (cached derived) → get {name}() (public getter).
Chain operations inside $derived — the entire pipeline is cached:
const tabs = $derived(tabsMap.values().toArray().sort((a, b) => b.savedAt - a.savedAt));
const notes = $derived(allNotes.filter((n) => n.deletedAt === undefined));
See the typescript skill for iterator helpers (.toArray(), .filter(), .find() on IteratorObject).
For component props expecting T[], derive in the script block — never materialize in the template:
<!-- Bad: re-creates array on every render -->
<FujiSidebar entries={entries.values().toArray()} />
<!-- Good: cached via $derived -->
<script>
const entriesArray = $derived(entries.values().toArray());
</script>
<FujiSidebar entries={entriesArray} />
$derived, Not a Plain GetterPut reactive computations in $derived, not inside public getters.
A getter may still be reactive if it reads reactive state, but it recomputes on every access. $derived computes reactively and caches until dependencies change.
Use $derived for the computation. Use the getter only as a pass-through to expose that derived value.
See docs/articles/derived-vs-getter-caching-matters.md for rationale.
State modules use a factory function that returns a flat object with getters and methods, exported as a singleton.
function createBookmarkState() {
const bookmarksMap = fromTable(workspaceClient.tables.bookmarks);
const bookmarks = $derived(bookmarksMap.values().toArray());
return {
get bookmarks() { return bookmarks; },
async add(tab: Tab) { /* ... */ },
remove(id: BookmarkId) { /* ... */ },
};
}
export const bookmarkState = createBookmarkState();
| Concern | Convention | Example |
|---|---|---|
| Export name | xState for domain state; descriptive noun for utilities |
bookmarkState, notesState, deviceConfig, vadRecorder |
| Factory function | createX() matching the export name |
createBookmarkState() |
| File name | Domain name, optionally with -state suffix |
bookmark-state.svelte.ts, auth.svelte.ts |
Use the State suffix when the export name would collide with a key property (bookmarkState.bookmarks, not bookmarks.bookmarks).
| Data Shape | Accessor | Example |
|---|---|---|
| Collection | Named getter | bookmarkState.bookmarks, notesState.notes |
| Single reactive value | .current (Svelte 5 convention) |
selectedFolderId.current, serverUrl.current |
| Keyed lookup | .get(key) |
toolTrustState.get(name), deviceConfig.get(key) |
The .current convention comes from runed (the standard Svelte 5 utility library). All 34+ runed utilities use .current. Never use .value (Vue convention).
For localStorage/sessionStorage persistence, use createPersistedState (single value) or createPersistedMap (typed multi-key config) from @epicenter/svelte.
// Single value — .current accessor
import { createPersistedState } from '@epicenter/svelte'Prerequisites
Time Estimate
15-45 minutes depending on use case complexity
Steps
Common Pitfalls
✓ Do
✗ Don't
💡 Pro Tips
✓ Use when
Use when skill capabilities match your task, clear ROI on time saved, and you can validate outputs. Best for repetitive tasks, learning, and quality improvement.
✗ Avoid when
Avoid when task requires deep expertise you can't validate, involves sensitive decisions, or when learning process is more valuable than speed of completion.
anthropics/claude-code
mblode/agent-skills
github/awesome-copilot
leonxlnx/taste-skill
sickn33/antigravity-awesome-skills
erichowens/some_claude_skills
svelte reduced setup friction for our internal harness; good balance of opinion and flexibility.
I recommend svelte for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.
We added svelte from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.
We added svelte from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.
Useful defaults in svelte — fewer surprises than typical one-off scripts, and it plays nicely with `npx skills` flows.
svelte fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.
svelte reduced setup friction for our internal harness; good balance of opinion and flexibility.
svelte is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.
Keeps context tight: svelte is the kind of skill you can hand to a new teammate without a long onboarding doc.
Registry listing for svelte matched our evaluation — installs cleanly and behaves as described in the markdown.
showing 1-10 of 42