Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
167 commits
Select commit Hold shift + click to select a range
3e5ed30
Merge pull request #344 from SkyCryptWebsite/dev
DarthGigi Aug 21, 2026
a42bc62
feat: load max-level enchantments from backend
cataladev Sep 13, 2026
22b69c9
refactor: fixing reviews
cataladev Sep 15, 2026
655bcca
fix: deleting old file
cataladev Sep 15, 2026
57e706c
fix: scope enchantment loading to stats
cataladev Sep 16, 2026
1f9c4b4
fix: use generated enchantment response type
cataladev Sep 17, 2026
6ff47f5
feat(stats): add Discord component embeds
DarthGigi Sep 20, 2026
17a2652
chore: version packages (beta) [skip ci]
github-actions[bot] Sep 20, 2026
93f5414
fix(cache): version prerendered endpoint URLs
DarthGigi Sep 20, 2026
a00b55d
chore: version packages (beta) [skip ci]
github-actions[bot] Sep 20, 2026
0e7bc8e
feat(discord-embed): add UTM tracking to profile links
DarthGigi Sep 20, 2026
4d5b17e
Merge pull request #347 from SkyCryptWebsite:dev
DarthGigi Sep 20, 2026
6d56391
chore: version packages (stable) [skip ci]
github-actions[bot] Sep 20, 2026
1ce1abd
Merge pull request #348 from SkyCryptWebsite/changeset-release/prod
github-actions[bot] Sep 20, 2026
dee7882
chore: sync prod into dev [skip ci]
github-actions[bot] Sep 20, 2026
c027c31
fix(discord): use valid rank colors in embeds
DarthGigi Sep 20, 2026
1081ea3
chore: version packages (beta) [skip ci]
github-actions[bot] Sep 20, 2026
12c0efe
Merge pull request #349 from SkyCryptWebsite/dev
DarthGigi Sep 20, 2026
6aa0126
chore: version packages (stable) [skip ci]
github-actions[bot] Sep 20, 2026
16b4a60
Merge pull request #350 from SkyCryptWebsite/changeset-release/prod
github-actions[bot] Sep 20, 2026
33a3ed8
chore: sync prod into dev [skip ci]
github-actions[bot] Sep 20, 2026
72ab679
Fix capitalization in project title in README
DarthGigi Sep 30, 2026
f9541c5
feat: add discord link to the discord embed
DarthGigi Sep 30, 2026
26565f9
chore: oxfmt format
DarthGigi Sep 30, 2026
8c9aa42
Merge pull request #351 from SkyCryptWebsite/dev
DarthGigi Sep 30, 2026
9fdabac
feat: redesign the discord embeds
DarthGigi Oct 10, 2026
5f2d673
chore: version packages (beta) [skip ci]
github-actions[bot] Oct 10, 2026
f0295a4
Merge pull request #352 from SkyCryptWebsite/dev
DarthGigi Oct 10, 2026
95927d1
chore: version packages (stable) [skip ci]
github-actions[bot] Oct 10, 2026
b6f8024
Merge pull request #353 from SkyCryptWebsite/changeset-release/prod
github-actions[bot] Oct 10, 2026
894ca5f
chore: sync prod into dev [skip ci]
github-actions[bot] Oct 10, 2026
c5c63e4
fix: make skills even
DarthGigi Oct 10, 2026
a208462
Merge pull request #354 from SkyCryptWebsite:dev
DarthGigi Oct 10, 2026
a020899
fix: use correct dungeon classes order
DarthGigi Oct 10, 2026
9283efe
fix: update embedGenerator tests for username handling and emoji form…
DarthGigi Oct 10, 2026
7f55043
Merge pull request #355 from SkyCryptWebsite/dev
DarthGigi Oct 10, 2026
2cc636b
fix: update rank display to include plusText in Discord embed
DarthGigi Oct 10, 2026
28fed80
fix: update skill and class terminology in embed descriptions
DarthGigi Oct 10, 2026
23a5235
feat: implement generic title and description functions for SEO
DarthGigi Oct 10, 2026
2b3318c
feat: enhance SEO with structured data and canonical URLs across mult…
DarthGigi Oct 10, 2026
0ee75fb
Merge pull request #356 from SkyCryptWebsite:dev
DarthGigi Oct 10, 2026
e7087dd
feat: add more shadcn-svelte components
DarthGigi Oct 10, 2026
bdd7b17
chore: oxfmt
DarthGigi Oct 10, 2026
4468767
feat(profile): add persistent profile emoji customization
DarthGigi Oct 10, 2026
1e492c4
chore(ui): refresh shared components and generated assets
DarthGigi Oct 10, 2026
17d5428
feat: migrate to sveltekit v3
DarthGigi Oct 10, 2026
86b4d9f
chore: update shadcn-svelte components
DarthGigi Oct 10, 2026
3870b75
fix: add class for selected state in Command.LinkItem
DarthGigi Oct 10, 2026
4e9b8c4
fix: remove the last $lib aliases
DarthGigi Oct 11, 2026
79e390c
feat: migrate to sentry v11
DarthGigi Oct 11, 2026
824a7fd
fix: optimize player image fetching and add error handling for asset …
DarthGigi Oct 11, 2026
463aa9c
feat: add shadcn linting plugin and rules to ESLint configuration
DarthGigi Oct 11, 2026
216bfee
fix: update TypeScript configuration and add missing node type
DarthGigi Oct 11, 2026
e079764
chore: update deps
DarthGigi Oct 11, 2026
40fe07f
fix: shadcn eslint errors
DarthGigi Oct 11, 2026
ae837cc
fix: update skeleton component background color for improved visibility
DarthGigi Oct 11, 2026
236d382
fix: remove unused skeleton loading section from the newsroom component
DarthGigi Oct 11, 2026
c720fa9
fix: update Item.Content class for consistent layout behavior
DarthGigi Oct 11, 2026
2858223
fix: remove unused function from sortTailwindcss and ensure package.j…
DarthGigi Oct 11, 2026
b6ec12e
feat: migrate to shadcn's own scroll fade
DarthGigi Oct 11, 2026
a95d2c2
chore: regenerate orval
DarthGigi Oct 11, 2026
06f285e
feat: add devEngines configuration for pnpm and node
DarthGigi Oct 11, 2026
2c758e5
chore: update pnpm setup action to version 12 in workflows and action…
DarthGigi Oct 11, 2026
8209d92
chore: version packages (beta) [skip ci]
github-actions[bot] Oct 11, 2026
35163ee
fix: prevent duplicate emoji pagination and configure CI database
DarthGigi Oct 11, 2026
a179d97
fix: move DATABASE_URL to job level in Vitest workflow
DarthGigi Oct 11, 2026
a014eb7
test: remove dashboard and server test suites
DarthGigi Oct 11, 2026
47a6b04
fix: improve emoji loading behavior by queuing additional requests
DarthGigi Oct 11, 2026
5c629bd
fix: add BETTER_AUTH_SECRET to Vitest workflow and ensure proper load…
DarthGigi Oct 11, 2026
5d69557
test: remove emoji-picker test suite
DarthGigi Oct 11, 2026
07c14b7
chore: update deps
DarthGigi Oct 11, 2026
71d377f
refactor: simplify schema definition for environment variables
DarthGigi Oct 11, 2026
f8faac5
fix: update Dockerfile to conditionally load SENTRY_AUTH_TOKEN and ad…
DarthGigi Oct 11, 2026
6c212da
feat: integrate Cloudflare Turnstile captcha for enhanced security on…
DarthGigi Oct 11, 2026
a768fb8
refactor: load environment variables using loadEnv
DarthGigi Oct 12, 2026
4c5cf1e
feat: add ORIGIN environment variable for improved configuration in D…
DarthGigi Oct 12, 2026
8b9d3f1
refactor: update prerender configurations to use dynamic inputs for i…
DarthGigi Oct 12, 2026
6b255d1
feat: remove Sentry integration and related configurations
DarthGigi Oct 12, 2026
b5aff64
chore: pnpm prune
DarthGigi Oct 12, 2026
de23081
chore: version packages (beta) [skip ci]
github-actions[bot] Oct 12, 2026
ba9187a
fix: improve error handling in fetchSection and validate query.curren…
DarthGigi Oct 12, 2026
5525eaa
refactor: update configuration files for improved clarity and organiz…
DarthGigi Oct 12, 2026
4c52cb4
feat: add svelte skills
DarthGigi Oct 12, 2026
639cdf0
feat: remove @sveltejs/load-config
DarthGigi Oct 12, 2026
6f3ac2b
feat: add logging for fetch requests in building environment
DarthGigi Oct 12, 2026
82b1b95
fix: improve fetch handling during prerendering to avoid 404 errors
DarthGigi Oct 12, 2026
1fd6b12
chore: update deps
DarthGigi Oct 16, 2026
4f4e4be
chore: update shadcn svelte componentsclear
DarthGigi Oct 16, 2026
1ca5cee
chore: update pnpm version to ^12.11.1
DarthGigi Oct 16, 2026
61c1bf4
chore: update deps
DarthGigi Oct 18, 2026
5e99cc6
Merge remote-tracking branch 'origin/dev' into feat/move-max-enchant-…
DarthGigi Oct 18, 2026
2aad198
fix(stats): derive enchantments type from generated zod schema
DarthGigi Oct 18, 2026
1b8e5f4
fix(theme-editor): fix type errors (type arguments no longer supported)
DarthGigi Oct 18, 2026
b5159f1
Merge pull request #345 from cataladev/feat/move-max-enchant-to-api
DarthGigi Oct 18, 2026
a821a2e
chore: version packages (beta) [skip ci]
github-actions[bot] Oct 18, 2026
ef6fc3e
fix(stats): mount tooltip setup inside stats layout
DarthGigi Oct 18, 2026
dbc47c6
feat(logging): add structured evlog request logging
DarthGigi Oct 19, 2026
2c48254
Merge pull request #357 from SkyCryptWebsite/feat/evlog-logging
DarthGigi Oct 19, 2026
33a07d7
chore: version packages (beta) [skip ci]
github-actions[bot] Oct 19, 2026
858e64b
feat(logging): ship evlog logs to HyperDX instead of Loki
DarthGigi Oct 19, 2026
f7c6f70
Merge pull request #358 from SkyCryptWebsite/feat/hyperdx-logging
DarthGigi Oct 19, 2026
279643b
chore: version packages (beta) [skip ci]
github-actions[bot] Oct 19, 2026
036494e
feat(dashboard): add developer API access request flow
DarthGigi Oct 19, 2026
a2a581d
feat(admin): add staff admin dashboard with review queues and audit log
DarthGigi Oct 19, 2026
3ead035
chore: version packages (beta) [skip ci]
github-actions[bot] Oct 19, 2026
a3ae439
feat(newsroom): replace Payload CMS with a built-in newsroom
DarthGigi Oct 19, 2026
1c80e9a
Merge pull request #359 from SkyCryptWebsite/feat/custom-cms
DarthGigi Oct 19, 2026
f6c38cb
chore: version packages (beta) [skip ci]
github-actions[bot] Oct 19, 2026
cba40c9
feat(pages): add about and legal pages with mdsvex
DarthGigi Oct 19, 2026
64b11ee
feat(header): add account button, newsroom menu and site footer
DarthGigi Oct 19, 2026
d12cdb9
feat: add eslint-disable comments for unknown classes and update link…
DarthGigi Oct 19, 2026
524b7bb
Merge pull request #360 from SkyCryptWebsite/feat/navbar-footer
DarthGigi Oct 19, 2026
f498785
feat: update .gitignore for eslint cache and modify lint script to us…
DarthGigi Oct 20, 2026
476f756
feat(developer): tighten API policy for hobby use only
DarthGigi Oct 20, 2026
843685f
feat: enhance API key management and user roles
DarthGigi Oct 20, 2026
cff8804
chore: version packages (beta) [skip ci]
github-actions[bot] Oct 20, 2026
09786a9
refactor: refactor import paths to remove file extensions for consist…
DarthGigi Oct 20, 2026
ab32c3b
feat(auth): open sign-ups to all Discord users
DarthGigi Oct 20, 2026
85a8e4d
chore: version packages (beta) [skip ci]
github-actions[bot] Oct 20, 2026
963ee2b
fix: update footer grid layout for better responsiveness; enhance das…
DarthGigi Oct 20, 2026
270c063
feat: implement contributor skin fetching and display; add loading sk…
DarthGigi Oct 20, 2026
a5e2966
fix(stats): validate route params and escape backend request paths
DarthGigi Oct 20, 2026
65bacc5
perf: lazy-load the card builder and harden the image proxy
DarthGigi Oct 20, 2026
00a26eb
perf: parallelize stats and card fetches, share live query results
DarthGigi Oct 20, 2026
941a56c
perf: lighter stats assets, lazy-load heavy UI, drop customSession
DarthGigi Oct 20, 2026
3fa9bd5
refactor: remove nested ternaries, preload Montserrat
DarthGigi Oct 20, 2026
e1a7375
chore: update deps
DarthGigi Oct 20, 2026
d2d4273
fix: unnecessary padding causing the header to overflow in safari
DarthGigi Oct 20, 2026
61d9512
chore: version packages (beta) [skip ci]
github-actions[bot] Oct 20, 2026
d18039c
test: remove tests that cannot catch real bugs
DarthGigi Oct 20, 2026
911de6a
fix: update search icon visibility based on hover state
DarthGigi Oct 20, 2026
e92997f
test(theme): run engine spec in the browser project
DarthGigi Oct 20, 2026
648ab0e
feat: serve the beta on sky.shiiyu.moe behind a settings switch
DarthGigi Oct 20, 2026
c680d22
chore: version packages (beta) [skip ci]
github-actions[bot] Oct 20, 2026
25ed772
feat: add Cloudflare Turnstile site key and secret to env example
DarthGigi Oct 20, 2026
723565f
feat: remove PUBLIC_BASE_URL
DarthGigi Oct 20, 2026
ee034ec
Merge branch 'prod' into dev
DarthGigi Oct 21, 2026
3e3ddff
Merge pull request #361 from SkyCryptWebsite/dev
DarthGigi Oct 21, 2026
0b79081
chore: version packages (stable) [skip ci]
github-actions[bot] Oct 21, 2026
d42fb60
Merge pull request #362 from SkyCryptWebsite/changeset-release/prod
github-actions[bot] Oct 21, 2026
6a95738
chore: sync prod into dev [skip ci]
github-actions[bot] Oct 21, 2026
851c401
fix: update Cloudflare storage URL pattern in Vite config
DarthGigi Oct 21, 2026
df4a851
Merge pull request #363 from SkyCryptWebsite:dev
DarthGigi Oct 21, 2026
c8fb6b2
fix: update origin validation logic in client logs handler
DarthGigi Oct 21, 2026
caead8d
Merge pull request #364 from SkyCryptWebsite:dev
DarthGigi Oct 21, 2026
b3f4f4a
fix: resolve href in ListItem component for proper navigation
DarthGigi Oct 21, 2026
944e36d
fix: update cache control for signed-in responses to prevent caching
DarthGigi Oct 21, 2026
b4cb88a
Merge pull request #365 from SkyCryptWebsite/dev
DarthGigi Oct 21, 2026
c688b15
feat: internal API key routes for the Go backend
DarthGigi Oct 21, 2026
5a52f6d
chore: add changeset for API key backend routes
DarthGigi Oct 21, 2026
237e6d3
fix: link the API docs to the api.shiiyu.moe root
DarthGigi Oct 21, 2026
b5d8112
Merge pull request #367 from SkyCryptWebsite/feat/backend-api-key-routes
DarthGigi Oct 21, 2026
29d8001
chore: version packages (beta) [skip ci]
github-actions[bot] Oct 21, 2026
db8da36
refactor: replace displayName with username across components and API…
DarthGigi Oct 21, 2026
32193e6
fix: update frame-ancestors to allow embedding from u.shiiyu.moe
DarthGigi Oct 21, 2026
114f647
fix: add api.shiiyu.moe and beta-api.shiiyu.moe to content security p…
DarthGigi Oct 21, 2026
cbae454
feat: add maintenance bypass token support for CI prerendering
DarthGigi Oct 21, 2026
cd90270
fix: update default server API URL in workflows
DarthGigi Oct 21, 2026
9b3f8d8
Merge pull request #368 from SkyCryptWebsite/dev
DarthGigi Oct 21, 2026
2f1a940
chore: version packages (stable) [skip ci]
github-actions[bot] Oct 21, 2026
6fdb36c
Merge pull request #369 from SkyCryptWebsite/changeset-release/prod
github-actions[bot] Oct 21, 2026
8613290
chore: sync prod into dev [skip ci]
github-actions[bot] Oct 21, 2026
dc72066
chore: update pnpm and node versions in package.json and pnpm-lock.yaml
DarthGigi Oct 21, 2026
787530d
fix: update contributor name reference to username in sitemap handler
DarthGigi Oct 21, 2026
2d61cf3
chore: update deps
DarthGigi Oct 21, 2026
a4856f8
perf(stats): skip skin respin when the route player is unchanged
DarthGigi Oct 21, 2026
6687742
chore: merge upstream/dev into the embed fork
imconnorngl Oct 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
37 changes: 26 additions & 11 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ PUBLIC_COMMIT_HASH=""

ADDRESS_HEADER="CF-Connecting-IP"

# Sentry.io
PUBLIC_SENTRY_DSN=""
PUBLIC_SENTRY_HOST=""
PUBLIC_SENTRY_PROJECT_ID=""

# GO API
PUBLIC_API_URL="http://localhost:8080/api/"
PUBLIC_SERVER_API_URL="http://localhost:8080/api/" # If you're using docker, set this to the name of the backend container, e.g. http://skycrypt-backend-1:8080/api/
Expand All @@ -39,16 +34,36 @@ MC_ID_CLIENT_SECRET=""
# https://www.patreon.com/portal/registration/register-clients
PATREON_CLIENT_ID=""
PATREON_CLIENT_SECRET=""
# Numeric campaign ID from the Patreon campaign URL/API response
PATREON_CAMPAIGN_ID=""
PATREON_CREATOR_ACCESS_TOKEN=""
PATREON_CREATOR_REFRESH_TOKEN=""
PUBLIC_PATREON_COLORED_HEART_CENTS="500"
PUBLIC_PATREON_ANY_EMOJI_CENTS="6000"

# Newsroom uploads (Cloudflare R2)
# Create an R2 API token with Object Read & Write on the bucket. The bucket needs a CORS rule allowing PUT with the
# content-type header from your ORIGIN, because browsers upload straight to R2.
R2_ACCOUNT_ID=""
R2_ACCESS_KEY_ID=""
R2_SECRET_ACCESS_KEY=""
R2_BUCKET=""
PUBLIC_MEDIA_URL="" # Public URL of the bucket, e.g. an R2 custom domain like https://media.shiiyu.moe

# Payload CMS
PUBLIC_CMS_URL="https://cms.shiiyu.moe"
SERVER_CMS_API_URL="https://cms.shiiyu.moe" # If you're using docker, set this to the name of the CMS container
CMS_API_TOKEN="" # Users API Key generated in CMS admin (Users → API Key tab)
CMS_PREVIEW_TOKEN="" # Must match CMS_PREVIEW_TOKEN in SkyCrypt-CMS .env
# Logging (evlog) - leave empty to log to stdout only
# Base URL of the HyperDX OTLP HTTP intake, e.g. http://skycrypt-hyperdx:4318 (on the Dokploy network)
HYPERDX_OTLP_ENDPOINT=""
# Ingestion key from HyperDX: Team Settings -> API Keys
HYPERDX_API_KEY=""

# Umami Analytics
PUBLIC_UMAMI_WEBSITE_ID=""
PUBLIC_UMAMI_SCRIPT_URL=""
PUBLIC_UMAMI_RECORDER_URL=""
PUBLIC_UMAMI_HOST_URL=""
PUBLIC_UMAMI_ENABLE_HEATMAPS="false"
PUBLIC_UMAMI_ENABLE_HEATMAPS="false"

# Cloudflare Turnstile
# https://developers.cloudflare.com/turnstile/troubleshooting/testing/#test-sitekeys
PUBLIC_TURNSTILE_SITE_KEY="1x00000000000000000000AA"
TURNSTILE_SECRET_KEY="1x0000000000000000000000000000000AA"
5 changes: 2 additions & 3 deletions .github/actions/pnpm-install/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,9 @@ runs:
uses: actions/checkout@v7

- name: Setup pnpm
uses: pnpm/action-setup@v6
uses: pnpm/setup@v3
with:
version: 11.11.0
run_install: false
version: 12

- name: Setup Node.js
uses: actions/setup-node@v7
Expand Down
67 changes: 67 additions & 0 deletions .github/agents/svelte-file-editor.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
name: svelte-file-editor
description: Specialized Svelte 5 code editor. MUST BE USED PROACTIVELY when creating, editing, or reviewing any .svelte file or .svelte.ts/.svelte.js module and MUST use the tools from the MCP server or the `svelte-file-editor` skill if they are available. Fetches relevant documentation and validates code using the Svelte MCP server tools.
---

You are a Svelte 5 expert responsible for writing, editing, and validating Svelte components and modules. You have access to the Svelte MCP server which provides documentation and code analysis tools. Always use the tools from the Svelte MCP server to fetch documentation with `get_documentation` and validate the code with `svelte_autofixer`. If the autofixer returns any issue or suggestions try to solve them.

If the MCP tools are not available you can use the `svelte-code-writer` skill to learn how to use the `@sveltejs/mcp` cli to access the same tools.

If the skill is not available you can run `npx @sveltejs/mcp@latest -y --help` to learn how to use it.

## Available MCP tools

### 1. list-sections

Lists all available Svelte 5 and SvelteKit documentation sections with titles and paths. Use this first to discover what documentation is available.

### 2. get-documentation

Retrieves full documentation for specified sections. Accepts a single section name or an array of section names. Use after `list-sections` to fetch relevant docs for the task at hand.

**Example sections:** `$state`, `$derived`, `$effect`, `$props`, `$bindable`, `snippets`, `routing`, `load functions`

### 3. svelte-autofixer

Analyzes Svelte code and returns suggestions to fix issues. Pass the component code directly to this tool. It will detect common mistakes like:

- Using `$effect` instead of `$derived` for computations
- Missing cleanup in effects
- Svelte 4 syntax (`on:click`, `export let`, `<slot>`)
- Missing keys in `{#each}` blocks
- And more

## Workflow

When invoked to work on a Svelte file:

### 1. Gather context (if needed)

If you're uncertain about Svelte 5 syntax or patterns, use the MCP tools:

1. Call `list-sections` to see available documentation
2. Call `get-documentation` with relevant section names

### 2. Read the target file

Read the file to understand the current implementation.

### 3. Make changes

Apply edits following Svelte 5 best practices:

### 4. Validate changes

After editing, ALWAYS call `svelte-autofixer` with the updated code to check for issues.

### 5. Fix any issues

If the autofixer reports problems, fix them and re-validate until no issues remain.

## Output format

After completing your work, provide:

1. Summary of changes made
2. Any issues found and fixed by the autofixer
3. Recommendations for further improvements (if any)
64 changes: 64 additions & 0 deletions .github/skills/svelte-code-writer/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
name: svelte-code-writer
description: CLI tools for Svelte 5 documentation lookup and code analysis. MUST be used whenever creating, editing or analyzing any Svelte component (.svelte) or Svelte module (.svelte.ts/.svelte.js). If possible, this skill should be executed within the svelte-file-editor agent for optimal results.
---

## CLI tools

You have access to `@sveltejs/mcp` CLI for Svelte-specific assistance. Use these commands via `npx`:

### List documentation sections

```bash
npx @sveltejs/mcp list-sections
```

Lists all available Svelte 5 and SvelteKit documentation sections with titles and paths.

### Get documentation

```bash
npx @sveltejs/mcp get-documentation "<section1>,<section2>,..."
```

Retrieves full documentation for specified sections. Use after `list-sections` to fetch relevant docs.

**Example:**

```bash
npx @sveltejs/mcp get-documentation "$state,$derived,$effect"
```

### Svelte autofixer

```bash
npx @sveltejs/mcp svelte-autofixer "<code_or_path>" [options]
```

Analyzes Svelte code and suggests fixes for common issues.

**Options:**

- `--async` - Enable async Svelte mode (default: false)
- `--svelte-version` - Target version: 4 or 5 (default: 5)

**Examples:**

```bash
# Analyze inline code (escape $ as \$)
npx @sveltejs/mcp svelte-autofixer '<script>let count = \$state(0);</script>'

# Analyze a file
npx @sveltejs/mcp svelte-autofixer ./src/lib/Component.svelte

# Target Svelte 4
npx @sveltejs/mcp svelte-autofixer ./Component.svelte --svelte-version 4
```

**Important:** When passing code with runes (`$state`, `$derived`, etc.) via the terminal, escape the `$` character as `\$` to prevent shell variable substitution.

## Workflow

1. **Uncertain about syntax?** Run `list-sections` then `get-documentation` for relevant topics
2. **Reviewing/debugging?** Run `svelte-autofixer` on the code to detect issues
3. **Always validate** - Run `svelte-autofixer` before finalizing any Svelte component
176 changes: 176 additions & 0 deletions .github/skills/svelte-core-bestpractices/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
---
name: svelte-core-bestpractices
description: Guidance on writing fast, robust, modern Svelte code. Load this skill whenever in a Svelte project and asked to write/edit or analyze a Svelte component or module. Covers reactivity, event handling, styling, integration with libraries and more.
---

## `$state`

Only use the `$state` rune for variables that should be _reactive_ — in other words, variables that cause an `$effect`, `$derived` or template expression to update. Everything else can be a normal variable.

Objects and arrays (`$state({...})` or `$state([...])`) are made deeply reactive, meaning mutation will trigger updates. This has a trade-off: in exchange for fine-grained reactivity, the objects must be proxied, which has performance overhead. In cases where you're dealing with large objects that are only ever reassigned (rather than mutated), use `$state.raw` instead. This is often the case with API responses, for example.

## `$derived`

To compute something from state, use `$derived` rather than `$effect`:

```js
// do this
let square = $derived(num * num);

// don't do this
let square;

$effect(() => {
square = num * num;
});
```

> [!NOTE] `$derived` is given an expression, _not_ a function. If you need to use a function (because the expression is complex, for example) use `$derived.by`.

Deriveds are writable — you can assign to them, just like `$state`, except that they will re-evaluate when their expression changes.

If the derived expression is an object or array, it will be returned as-is — it is _not_ made deeply reactive. You can, however, use `$state` inside `$derived.by` in the rare cases that you need this.

## `$effect`

Effects are an escape hatch and should mostly be avoided. In particular, avoid updating state inside effects.

- If you need to sync state to an external library such as D3, it is often neater to use [`{@attach ...}`](references/attach.md)
- If you need to run some code in response to user interaction, put the code directly in an event handler or use a [function binding](references/bind.md) as appropriate
- If you need to log values for debugging purposes, use [`$inspect`](references/inspect.md)
- If you need to observe something external to Svelte, use [`createSubscriber`](references/svelte-reactivity.md)

Never wrap the contents of an effect in `if (browser) {...}` or similar — effects do not run on the server.

## `$props`

Treat props as though they will change. For example, values that depend on props should usually use `$derived`:

```js
// @errors: 2451
let { type } = $props();

// do this
let color = $derived(type === 'danger' ? 'red' : 'green');

// don't do this — `color` will not update if `type` changes
let color = type === 'danger' ? 'red' : 'green';
```

## `$inspect.trace`

`$inspect.trace` is a debugging tool for reactivity. If something is not updating properly or running more than it should you can add `$inspect.trace(label)` as the first line of an `$effect` or `$derived.by` (or any function they call) to trace their dependencies and discover which one triggered an update.

## Events

Any element attribute starting with `on` is treated as an event listener:

```svelte
<button onclick={() => {...}}>click me</button>

<!-- attribute shorthand also works -->
<button {onclick}>...</button>

<!-- so do spread attributes -->
<button {...props}>...</button>
```

If you need to attach listeners to `window` or `document` you can use `<svelte:window>` and `<svelte:document>`:

```svelte
<svelte:window onkeydown={...} />
<svelte:document onvisibilitychange={...} />
```

Avoid using `onMount` or `$effect` for this.

## Snippets

[Snippets](references/snippet.md) are a way to define reusable chunks of markup that can be instantiated with the [`{@render ...}`](references/render.md) tag, or passed to components as props. They must be declared within the template.

```svelte
{#snippet greeting(name)}
<p>hello {name}!</p>
{/snippet}

{@render greeting('world')}
```

> [!NOTE] Snippets declared at the top level of a component (i.e. not inside elements or blocks) can be referenced inside `<script>`. A snippet that doesn't reference component state is also available in a `<script module>`, in which case it can be exported for use by other components.

## Each blocks

Prefer to use [keyed each blocks](references/each.md) — this improves performance by allowing Svelte to surgically insert or remove items rather than updating the DOM belonging to existing items.

> [!NOTE] The key _must_ uniquely identify the object. Do not use the index as a key.

Avoid destructuring if you need to mutate the item (with something like `bind:value={item.count}`, for example).

## Using JavaScript variables in CSS

If you have a JS variable that you want to use inside CSS you can set a CSS custom property with the `style:` directive.

```svelte
<div style:--columns={columns}>...</div>
```

You can then reference `var(--columns)` inside the component's `<style>`.

## Styling child components

The CSS in a component's `<style>` is scoped to that component. If a parent component needs to control the child's styles, the preferred way is to use CSS custom properties:

```svelte
<!-- Parent.svelte -->
<Child --color="red" />

<!-- Child.svelte -->
<h1>Hello</h1>

<style>
h1 {
color: var(--color);
}
</style>
```

If this is impossible (for example, the child component comes from a library) you can use `:global` to override styles:

```svelte
<div>
<Child />
</div>

<style>
div :global {
h1 {
color: red;
}
}
</style>
```

## Context

Consider using context instead of declaring state in a shared module. This will scope the state to the part of the app that needs it, and eliminate the possibility of it leaking between users when server-side rendering.

Use `createContext` rather than `setContext` and `getContext`, as it provides type safety.

## Async Svelte

If using version 5.36 or higher, you can use [await expressions](references/await-expressions.md) and [hydratable](references/hydratable.md) to use promises directly inside components. Note that these require the `experimental.async` option to be enabled in `svelte.config.js` as they are not yet considered fully stable.

## Avoid legacy features

Always use runes mode for new code, and avoid features that have more modern replacements:

- use `$state` instead of implicit reactivity (e.g. `let count = 0; count += 1`)
- use `$derived` and `$effect` instead of `$:` assignments and statements (but only use effects when there is no better solution)
- use `$props` instead of `export let`, `$$props` and `$$restProps`
- use `onclick={...}` instead of `on:click={...}`
- use `{#snippet ...}` and `{@render ...}` instead of `<slot>` and `$$slots` and `<svelte:fragment>`
- use `<DynamicComponent>` instead of `<svelte:component this={DynamicComponent}>`
- use `import Self from './ThisComponent.svelte'` and `<Self>` instead of `<svelte:self>`
- use classes with `$state` fields to share reactivity between components, instead of using stores
- use `{@attach ...}` instead of `use:action`
- use clsx-style arrays and objects in `class` attributes, instead of the `class:` directive
Loading
Loading