diff --git a/.changeset/README.md b/.changeset/README.md
new file mode 100644
index 000000000000..e5b6d8d6a67a
--- /dev/null
+++ b/.changeset/README.md
@@ -0,0 +1,8 @@
+# Changesets
+
+Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
+with multi-package repos, or single-package repos to help you version and publish your code. You can
+find the full documentation for it [in our repository](https://github.com/changesets/changesets)
+
+We have a quick list of common questions to get you started engaging with this project in
+[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
diff --git a/.changeset/config.json b/.changeset/config.json
new file mode 100644
index 000000000000..b56077a9220c
--- /dev/null
+++ b/.changeset/config.json
@@ -0,0 +1,11 @@
+{
+ "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
+ "changelog": ["@svitejs/changesets-changelog-github-compact", { "repo": "sveltejs/svelte" }],
+ "commit": false,
+ "fixed": [],
+ "linked": [],
+ "access": "public",
+ "baseBranch": "main",
+ "bumpVersionsWithWorkspaceProtocolOnly": true,
+ "ignore": ["!(@sveltejs/*|svelte)"]
+}
diff --git a/.editorconfig b/.editorconfig
index ed2a319d5843..2f52d9993f71 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -11,6 +11,5 @@ trim_trailing_whitespace = true
[test/**/expected.css]
insert_final_newline = false
-[{package.json,.travis.yml,.eslintrc.json}]
+[package.json]
indent_style = space
-indent_size = 2
diff --git a/.eslintignore b/.eslintignore
deleted file mode 100644
index bfe7b1fa9544..000000000000
--- a/.eslintignore
+++ /dev/null
@@ -1,15 +0,0 @@
-**/_actual.js
-**/expected.js
-_output
-test/*/samples/*/output.js
-node_modules
-
-# output files
-animate/*.js
-esing/*.js
-internal/*.js
-motion/*.js
-store/*.js
-transition/*.js
-index.js
-compiler.js
diff --git a/.eslintrc.js b/.eslintrc.js
deleted file mode 100644
index 946a157e40c8..000000000000
--- a/.eslintrc.js
+++ /dev/null
@@ -1,88 +0,0 @@
-module.exports = {
- root: true,
- rules: {
- indent: 'off',
- 'no-unused-vars': 'off',
- semi: [2, 'always'],
- 'keyword-spacing': [2, { before: true, after: true }],
- 'space-before-blocks': [2, 'always'],
- 'no-mixed-spaces-and-tabs': [2, 'smart-tabs'],
- 'no-cond-assign': 0,
- 'object-shorthand': [2, 'always'],
- 'no-const-assign': 2,
- 'no-class-assign': 2,
- 'no-this-before-super': 2,
- 'no-var': 2,
- 'no-unreachable': 2,
- 'valid-typeof': 2,
- 'quote-props': [2, 'as-needed'],
- 'one-var': [2, 'never'],
- 'prefer-arrow-callback': 2,
- 'prefer-const': [2, { destructuring: 'all' }],
- 'arrow-spacing': 2,
- 'no-inner-declarations': 0,
- 'require-atomic-updates': 'off',
- '@typescript-eslint/indent': 'off',
- '@typescript-eslint/camelcase': 'off',
- '@typescript-eslint/no-use-before-define': 'off',
- '@typescript-eslint/array-type': ['error', 'array-simple'],
- '@typescript-eslint/explicit-function-return-type': 'off',
- '@typescript-eslint/no-explicit-any': 'off',
- '@typescript-eslint/explicit-member-accessibility': 'off',
- '@typescript-eslint/no-unused-vars': [
- 'error',
- {
- argsIgnorePattern: '^_'
- }
- ],
- '@typescript-eslint/no-object-literal-type-assertion': 'off',
- '@typescript-eslint/no-unused-vars': 'off',
- '@typescript-eslint/prefer-interface': 'off'
- },
- globals: {
- globalThis: false
- },
- env: {
- es6: true,
- browser: true,
- node: true,
- mocha: true
- },
- extends: [
- 'eslint:recommended',
- 'plugin:import/errors',
- 'plugin:import/warnings',
- 'plugin:import/typescript',
- 'plugin:@typescript-eslint/recommended'
- ],
- parserOptions: {
- ecmaVersion: 9,
- sourceType: 'module'
- },
- plugins: ['svelte3'],
- settings: {
- 'import/core-modules': [
- 'svelte',
- 'svelte/internal',
- 'svelte/store',
- 'svelte/easing',
- 'estree'
- ],
- 'svelte3/compiler': require('./compiler')
- },
- overrides: [
- {
- files: ['*.js'],
- rules: {
- '@typescript-eslint/no-var-requires': 'off'
- }
- },
- {
- files: ['*.svelte'],
- processor: 'svelte3/svelte3',
- rules: {
- '@typescript-eslint/indent': 'off'
- }
- }
- ]
-};
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000000..a299a4435ae8
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,3 @@
+/site/** -linguist-detectable
+/test/**/samples/** -linguist-detectable
+/**/*.svelte linguist-detectable
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 000000000000..d632634540e5
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+open_collective: svelte
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 6871094f5cac..220af118345e 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,17 +1,20 @@
-------
+---
Before filing an issue we'd appreciate it if you could take a moment to ensure
there isn't already an open issue or pull-request.
------
+---
If there's an existing issue, please add a :+1: reaction to the description of
the issue. One way we prioritize issues is by the number of :+1: reactions on
their descriptions. Please DO NOT add `+1` or :+1: comments.
### Feature requests and proposals
+
We're excited to hear how we can make Svelte better. Please add as much detail
-as you can on your use case.
+as you can on your use case. To propose an implementation of a large feature or
+change, please create an [RFC](https://github.com/sveltejs/rfcs).
### Bugs
+
If you're filing an issue about a bug please include as much information
as you can including the following.
@@ -20,7 +23,6 @@ as you can including the following.
- Svelte version (Please check you can reproduce the issue with the latest release!)
- Whether your project uses Webpack or Rollup
-- *Repeatable steps to reproduce the issue*
+- _Repeatable steps to reproduce the issue_
-Thanks for being part of Svelte!
--------
+## Thanks for being part of Svelte!
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index f5369e999177..000000000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,52 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve
-title: ''
-labels: 'Bug'
-assignees: ''
-
----
-
-**Describe the bug**
-A clear and concise description of what the bug is.
-
-**Logs**
-Please include browser console and server logs around the time this bug occurred.
-
-**To Reproduce**
-To help us help you, if you've found a bug please consider the following:
-
-* If you can demonstrate the bug using https://svelte.dev/repl, please do.
-* If that's not possible, we recommend creating a small repo that illustrates the problem.
-* Reproductions should be small, self-contained, correct examples – http://sscce.org.
-
-Occasionally, this won't be possible, and that's fine – we still appreciate you raising the issue. But please understand that Svelte is run by unpaid volunteers in their free time, and issues that follow these instructions will get fixed faster.
-
-**Expected behavior**
-A clear and concise description of what you expected to happen.
-
-**Stacktraces**
-If you have a stack trace to include, we recommend putting inside a `` block for the sake of the thread's readability:
-
-
- Stack trace
-
- Stack trace goes here...
-
-
-**Information about your Svelte project:**
-- Your browser and the version: (e.x. Chrome 52.1, Firefox 48.0, IE 10)
-
-- Your operating system: (e.x. OS X 10, Ubuntu Linux 19.10, Windows XP, etc)
-
-- Svelte version (Please check you can reproduce the issue with the latest release!)
-
-- Whether your project uses Webpack or Rollup
-
-**Severity**
-How severe an issue is this bug to you? Is this annoying, blocking some users, blocking an upgrade or blocking your usage of Svelte entirely?
-
-Note: the more honest and specific you are here the more we will take you seriously.
-
-**Additional context**
-Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 000000000000..2e484e5ca26d
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,50 @@
+name: "\U0001F41E Bug report"
+description: Report an issue with Svelte
+labels: ['triage: bug']
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to fill out this bug report!
+ - type: textarea
+ id: bug-description
+ attributes:
+ label: Describe the bug
+ description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description. Thanks!
+ placeholder: Bug description
+ validations:
+ required: true
+ - type: textarea
+ id: reproduction
+ attributes:
+ label: Reproduction
+ description: Please provide a link to a repo or REPL that can reproduce the problem you ran into. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "need reproduction" label. If no reproduction is provided within a reasonable time-frame, the issue will be closed.
+ placeholder: Reproduction
+ validations:
+ required: true
+ - type: textarea
+ id: logs
+ attributes:
+ label: Logs
+ description: 'Please include browser console and server logs around the time this bug occurred. Optional if provided reproduction. Please try not to insert an image but copy paste the log text.'
+ render: shell
+ - type: textarea
+ id: system-info
+ attributes:
+ label: System Info
+ description: Output of `npx envinfo --system --npmPackages svelte,rollup,webpack --binaries --browsers`
+ render: shell
+ placeholder: System, Binaries, Browsers
+ validations:
+ required: true
+ - type: dropdown
+ id: severity
+ attributes:
+ label: Severity
+ description: Select the severity of this issue
+ options:
+ - annoyance
+ - blocking an upgrade
+ - blocking all usage of svelte
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 000000000000..ee3e5a41b982
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+blank_issues_enabled: false
+contact_links:
+ - name: Discord Chat
+ url: https://svelte.dev/chat
+ about: Ask questions and discuss with other Svelte users in real time.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index e533c21c96fa..000000000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,23 +0,0 @@
----
-name: Feature request
-about: Suggest an idea for this project
-title: ''
-labels: 'New Feature'
-assignees: ''
-
----
-
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. For example: I'm always frustrated when [...]
-
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.
-
-**Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
-
-**How important is this feature to you?**
-Note: the more honest and specific you are here the more we will take you seriously.
-
-**Additional context**
-Add any other context or screenshots about the feature request here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 000000000000..d79e8b2e21f3
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,35 @@
+name: 'Feature Request'
+description: Request a new Svelte feature
+labels: [enhancement]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to request this feature! If your feature request is complex or substantial enough to warrant in-depth discussion, maintainers may close the issue and ask you to open an [RFC](https://github.com/sveltejs/rfcs).
+ - type: textarea
+ id: problem
+ attributes:
+ label: Describe the problem
+ description: Please provide a clear and concise description the problem this feature would solve. The more information you can provide here, the better.
+ placeholder: I'm always frustrated when...
+ validations:
+ required: true
+ - type: textarea
+ id: solution
+ attributes:
+ label: Describe the proposed solution
+ description: Please provide a clear and concise description of what you would like to happen.
+ placeholder: I would like to see...
+ validations:
+ required: true
+ - type: dropdown
+ id: importance
+ attributes:
+ label: Importance
+ description: How important is this feature to you?
+ options:
+ - nice to have
+ - would make my life easier
+ - i cannot use svelte without it
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/questions-and-help.md b/.github/ISSUE_TEMPLATE/questions-and-help.md
deleted file mode 100644
index a6e0dc6e19a2..000000000000
--- a/.github/ISSUE_TEMPLATE/questions-and-help.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-name: Questions and help
-about: If you think you need help with something related to Svelte
-title: ''
-labels: 'Question'
-assignees: ''
-
----
-
-This issue tracker is intended to collect bug reports and feature requests.
-
-For help with installation, information on how features work, or questions about specific features of Svelte, please come and join us in the [Svelte Discord](https://svelte.dev/chat), or ask your question on [Stack Overflow](https://stackoverflow.com/questions/tagged/svelte). Any issues open for help requests will be closed to keep from clogging up the issue tracker.
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 1e77e0337aca..aa5f9732b6d3 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,8 +1,11 @@
+### Before submitting the PR, please make sure you do the following
+- [ ] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
+- [ ] Prefix your PR title with `feat:`, `fix:`, `chore:`, or `docs:`.
+- [ ] This message body should clearly illustrate what problems it solves.
+- [ ] Ideally, include a test that fails without this PR but passes with it.
+- [ ] If this PR changes code within `packages/svelte/src`, add a changeset (`npx changeset`).
-### Before submitting the PR, please make sure you do the following
-- [ ] It's really useful if your PR relates to an outstanding issue, so please reference it in your PR, or create an explanatory one for discussion. In many cases features are absent for a reason.
-- [ ] This message body should clearly illustrate what problems it solves. If there are related issues, remember to reference them.
-- [ ] Ideally, include a test that fails without this PR but passes with it. PRs will only be merged once they pass CI. (Remember to `npm run lint`!)
-### Tests
-- [ ] Run the tests tests with `npm test` or `yarn test`)
+### Tests and linting
+
+- [ ] Run the tests with `pnpm test` and lint the project with `pnpm lint`
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2488902b249a..cf73a1f6cb02 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,25 +1,79 @@
name: CI
-on: [push, pull_request]
+on:
+ push:
+ branches: [main]
+ pull_request:
+permissions:
+ contents: read # to fetch code (actions/checkout)
+
+env:
+ # We only install Chromium manually
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1'
+
jobs:
Tests:
+ permissions: {}
runs-on: ${{ matrix.os }}
+ timeout-minutes: 15
strategy:
matrix:
- node-version: [8, 10, 12]
- os: [ubuntu-latest, windows-latest, macOS-latest]
+ include:
+ - node-version: 18
+ os: windows-latest
+ - node-version: 18
+ os: macOS-latest
+ - node-version: 18
+ os: ubuntu-latest
+ - node-version: 20
+ os: ubuntu-latest
+ - node-version: 22
+ os: ubuntu-latest
+
steps:
- - run: git config --global core.autocrlf false
- - uses: actions/checkout@v1
- - uses: actions/setup-node@v1
- with:
- node-version: ${{ matrix.node-version }}
- - run: npm install
- - run: npm test
- env:
- CI: true
+ - uses: actions/checkout@v4
+ - uses: pnpm/action-setup@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: ${{ matrix.node-version }}
+ cache: pnpm
+ - run: pnpm install --frozen-lockfile
+ - run: pnpm playwright install chromium
+ - run: pnpm test
+ env:
+ CI: true
Lint:
+ permissions: {}
runs-on: ubuntu-latest
+ timeout-minutes: 5
steps:
- - uses: actions/checkout@v1
- - uses: actions/setup-node@v1
- - run: 'npm i && npm run lint'
+ - uses: actions/checkout@v4
+ - uses: pnpm/action-setup@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 18
+ cache: pnpm
+ - name: install
+ run: pnpm install --frozen-lockfile
+ - name: type check
+ run: pnpm check
+ - name: lint
+ if: (${{ success() }} || ${{ failure() }}) # ensures this step runs even if previous steps fail (avoids multiple runs uncovering different issues at different steps)
+ run: pnpm lint
+ - name: build and check generated types
+ if: (${{ success() }} || ${{ failure() }}) # ensures this step runs even if previous steps fail
+ run: pnpm build && { [ "`git status --porcelain=v1`" == "" ] || (echo "Generated types have changed — please regenerate types locally with `cd packages/svelte && pnpm generate:types` and commit the changes after you have reviewed them"; git diff; exit 1); }
+ Benchmarks:
+ permissions: {}
+ runs-on: ubuntu-latest
+ timeout-minutes: 15
+ steps:
+ - uses: actions/checkout@v4
+ - uses: pnpm/action-setup@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 18
+ cache: pnpm
+ - run: pnpm install --frozen-lockfile
+ - run: pnpm bench
+ env:
+ CI: true
diff --git a/.github/workflows/ecosystem-ci-trigger.yml b/.github/workflows/ecosystem-ci-trigger.yml
new file mode 100644
index 000000000000..71df3242e8f1
--- /dev/null
+++ b/.github/workflows/ecosystem-ci-trigger.yml
@@ -0,0 +1,94 @@
+name: ecosystem-ci trigger
+
+on:
+ issue_comment:
+ types: [created]
+
+jobs:
+ trigger:
+ runs-on: ubuntu-latest
+ if: github.repository == 'sveltejs/svelte' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/ecosystem-ci run')
+ steps:
+ - uses: GitHubSecurityLab/actions-permissions/monitor@v1
+ - uses: actions/github-script@v6
+ with:
+ script: |
+ const user = context.payload.sender.login
+ console.log(`Validate user: ${user}`)
+
+ let hasTriagePermission = false
+ try {
+ const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ username: user,
+ });
+ hasTriagePermission = data.user.permissions.triage
+ } catch (e) {
+ console.warn(e)
+ }
+
+ if (hasTriagePermission) {
+ console.log('Allowed')
+ await github.rest.reactions.createForIssueComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ comment_id: context.payload.comment.id,
+ content: '+1',
+ })
+ } else {
+ console.log('Not allowed')
+ await github.rest.reactions.createForIssueComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ comment_id: context.payload.comment.id,
+ content: '-1',
+ })
+ throw new Error('not allowed')
+ }
+ - uses: actions/github-script@v6
+ id: get-pr-data
+ with:
+ script: |
+ console.log(`Get PR info: ${context.repo.owner}/${context.repo.repo}#${context.issue.number}`)
+ const { data: pr } = await github.rest.pulls.get({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: context.issue.number
+ })
+ return {
+ num: context.issue.number,
+ branchName: pr.head.ref,
+ repo: pr.head.repo.full_name
+ }
+ - id: generate-token
+ uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92 #keep pinned for security reasons, currently 1.8.0
+ with:
+ app_id: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_ID }}
+ private_key: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_PRIVATE_KEY }}
+ repository: '${{ github.repository_owner }}/svelte-ecosystem-ci'
+ - uses: actions/github-script@v6
+ id: trigger
+ env:
+ COMMENT: ${{ github.event.comment.body }}
+ with:
+ github-token: ${{ steps.generate-token.outputs.token }}
+ result-encoding: string
+ script: |
+ const comment = process.env.COMMENT.trim()
+ const prData = ${{ steps.get-pr-data.outputs.result }}
+
+ const suite = comment.split('\n')[0].replace(/^\/ecosystem-ci run/, '').trim()
+
+ await github.rest.actions.createWorkflowDispatch({
+ owner: context.repo.owner,
+ repo: 'svelte-ecosystem-ci',
+ workflow_id: 'ecosystem-ci-from-pr.yml',
+ ref: 'main',
+ inputs: {
+ prNumber: '' + prData.num,
+ branchName: prData.branchName,
+ repo: prData.repo,
+ suite: suite === '' ? '-' : suite
+ }
+ })
diff --git a/.github/workflows/pkg.pr.new-comment.yml b/.github/workflows/pkg.pr.new-comment.yml
new file mode 100644
index 000000000000..3f1fca5a0bea
--- /dev/null
+++ b/.github/workflows/pkg.pr.new-comment.yml
@@ -0,0 +1,116 @@
+name: Update pkg.pr.new comment
+
+on:
+ workflow_run:
+ workflows: ['Publish Any Commit']
+ types:
+ - completed
+
+permissions:
+ pull-requests: write
+
+jobs:
+ build:
+ name: 'Update comment'
+ runs-on: ubuntu-latest
+ steps:
+ - uses: GitHubSecurityLab/actions-permissions/monitor@v1
+ - name: Download artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: output
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ run-id: ${{ github.event.workflow_run.id }}
+
+ - run: ls -R .
+ - name: 'Post or update comment'
+ uses: actions/github-script@v6
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const fs = require('fs');
+ const output = JSON.parse(fs.readFileSync('output.json', 'utf8'));
+
+ const bot_comment_identifier = ``;
+
+ const body = (number) => `${bot_comment_identifier}
+
+ [Playground](https://svelte.dev/playground?version=pr-${number})
+
+ \`\`\`
+ ${output.packages.map((p) => `pnpm add https://pkg.pr.new/${p.name}@${number}`).join('\n')}
+ \`\`\`
+ `;
+
+ async function find_bot_comment(issue_number) {
+ if (!issue_number) return null;
+ const comments = await github.rest.issues.listComments({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: issue_number,
+ });
+ return comments.data.find((comment) =>
+ comment.body.includes(bot_comment_identifier)
+ );
+ }
+
+ async function create_or_update_comment(issue_number) {
+ if (!issue_number) {
+ console.log('No issue number provided. Cannot post or update comment.');
+ return;
+ }
+
+ const existing_comment = await find_bot_comment(issue_number);
+ if (existing_comment) {
+ await github.rest.issues.updateComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ comment_id: existing_comment.id,
+ body: body(issue_number),
+ });
+ } else {
+ await github.rest.issues.createComment({
+ issue_number: issue_number,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ body: body(issue_number),
+ });
+ }
+ }
+
+ async function log_publish_info() {
+ const svelte_package = output.packages.find(p => p.name === 'svelte');
+ const svelte_sha = svelte_package.url.replace(/^.+@([^@]+)$/, '$1');
+ console.log('\n' + '='.repeat(50));
+ console.log('Publish Information');
+ console.log('='.repeat(50));
+ console.log('\nPublished Packages:');
+ console.log(output.packages.map((p) => `${p.name} - pnpm add https://pkg.pr.new/${p.name}@${p.url.replace(/^.+@([^@]+)$/, '$1')}`).join('\n'));
+ if(svelte_sha){
+ console.log('\nPlayground URL:');
+ console.log(`\nhttps://svelte.dev/playground?version=commit-${svelte_sha}`)
+ }
+ console.log('\n' + '='.repeat(50));
+ }
+
+ if (output.event_name === 'pull_request') {
+ if (output.number) {
+ await create_or_update_comment(output.number);
+ }
+ } else if (output.event_name === 'push') {
+ const pull_requests = await github.rest.pulls.list({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ state: 'open',
+ head: `${context.repo.owner}:${output.ref.replace('refs/heads/', '')}`,
+ });
+
+ if (pull_requests.data.length > 0) {
+ await create_or_update_comment(pull_requests.data[0].number);
+ } else {
+ console.log(
+ 'No open pull request found for this push. Logging publish information to console:'
+ );
+ await log_publish_info();
+ }
+ }
diff --git a/.github/workflows/pkg.pr.new.yml b/.github/workflows/pkg.pr.new.yml
new file mode 100644
index 000000000000..b1ba217e5a0f
--- /dev/null
+++ b/.github/workflows/pkg.pr.new.yml
@@ -0,0 +1,42 @@
+name: Publish Any Commit
+on: [push, pull_request]
+
+jobs:
+ build:
+ permissions: {}
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - uses: pnpm/action-setup@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 22.x
+ cache: pnpm
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Build
+ run: pnpm build
+
+ - run: pnpx pkg-pr-new publish --comment=off --json output.json --compact --no-template './packages/svelte'
+ - name: Add metadata to output
+ uses: actions/github-script@v6
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const fs = require('fs');
+ const output = JSON.parse(fs.readFileSync('output.json', 'utf8'));
+ output.number = context.issue.number;
+ output.event_name = context.eventName;
+ output.ref = context.ref;
+ fs.writeFileSync('output.json', JSON.stringify(output), 'utf8');
+ - name: Upload output
+ uses: actions/upload-artifact@v4
+ with:
+ name: output
+ path: ./output.json
+
+ - run: ls -R .
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 000000000000..6debe5662a88
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,48 @@
+name: Release
+
+on:
+ push:
+ branches:
+ - main
+
+permissions: {}
+jobs:
+ release:
+ # prevents this action from running on forks
+ if: github.repository == 'sveltejs/svelte'
+ permissions:
+ contents: write # to create release (changesets/action)
+ id-token: write # OpenID Connect token needed for provenance
+ pull-requests: write # to create pull request (changesets/action)
+ name: Release
+ runs-on: ubuntu-latest
+ steps:
+ - uses: GitHubSecurityLab/actions-permissions/monitor@v1
+ - name: Checkout Repo
+ uses: actions/checkout@v4
+ with:
+ # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
+ fetch-depth: 0
+ - uses: pnpm/action-setup@v4
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: 18.x
+ cache: pnpm
+
+ - name: Install
+ run: pnpm install --frozen-lockfile
+
+ - name: Build
+ run: pnpm build && { [ "`git status --porcelain=v1`" == "" ] || (echo "Generated types have changed — please regenerate types locally with `cd packages/svelte && pnpm generate:types` and commit the changes after you have reviewed them"; git diff; exit 1); }
+
+ - name: Create Release Pull Request or Publish to npm
+ id: changesets
+ uses: changesets/action@v1
+ with:
+ version: pnpm changeset:version
+ publish: pnpm changeset:publish
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ NPM_CONFIG_PROVENANCE: true
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 7a1424492996..d50343766485 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,40 +1,26 @@
+# Dependency directories
+node_modules/
+
+# IDE related
.idea
+
+# Test coverage
+coverage
+*.lcov
+
+# Optional eslint cache
+.eslintcache
+
+# dotenv environment variables file
+.env
+.env.test
+
+# build output
+.vercel
+
+# OS-specific
.DS_Store
-.nyc_output
-node_modules
-*.map
-/src/compiler/compile/internal_exports.ts
-/compiler.d.ts
-/compiler.*js
-/index.*js
-/internal
-/store
-/easing
-/motion
-/transition
-/animate
-/scratch/
-/coverage/
-/coverage.lcov
-/test/*/samples/_
-/test/sourcemaps/samples/*/output.js
-/test/sourcemaps/samples/*/output.js.map
-/test/sourcemaps/samples/*/output.css
-/test/sourcemaps/samples/*/output.css.map
-/yarn-error.log
-_actual*.*
-_output
-/types
-
-/site/cypress/screenshots/
-/site/__sapper__/
-/site/.env
-/site/.sessions
-/site/static/svelte-app.json
-/site/static/contributors.jpg
-/site/static/workers
-/site/static/organisations
-/site/scripts/svelte-app
-/site/scripts/community
-/site/src/routes/_contributors.js
-/site/src/routes/_components/WhosUsingSvelte.svelte
+
+tmp
+
+benchmarking/compare/.results
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 000000000000..33484750d05a
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+playwright_skip_browser_download=1
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 000000000000..d5c124353c37
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,47 @@
+documentation/docs/
+
+packages/**/dist/*.js
+packages/**/build/*.js
+packages/**/npm/**/*
+packages/**/config/*.js
+
+# packages/svelte
+packages/svelte/messages/**/*.md
+packages/svelte/src/compiler/errors.js
+packages/svelte/src/compiler/warnings.js
+packages/svelte/src/internal/client/errors.js
+packages/svelte/src/internal/client/warnings.js
+packages/svelte/src/internal/shared/errors.js
+packages/svelte/src/internal/shared/warnings.js
+packages/svelte/src/internal/server/errors.js
+packages/svelte/tests/migrate/samples/*/output.svelte
+packages/svelte/tests/**/*.svelte
+packages/svelte/tests/**/_expected*
+packages/svelte/tests/**/_actual*
+packages/svelte/tests/**/expected*
+packages/svelte/tests/**/_output
+packages/svelte/tests/**/shards/*.test.js
+packages/svelte/tests/hydration/samples/*/_expected.html
+packages/svelte/tests/hydration/samples/*/_override.html
+packages/svelte/types
+packages/svelte/compiler/index.js
+playgrounds/sandbox/input/**.svelte
+playgrounds/sandbox/output
+
+# sites/svelte.dev
+sites/svelte.dev/static/svelte-app.json
+sites/svelte.dev/scripts/svelte-app/
+sites/svelte.dev/src/routes/_components/Supporters/contributors.jpg
+sites/svelte.dev/src/routes/_components/Supporters/contributors.js
+sites/svelte.dev/src/routes/_components/Supporters/donors.jpg
+sites/svelte.dev/src/routes/_components/Supporters/donors.js
+sites/svelte.dev/src/lib/generated
+
+**/node_modules
+**/.svelte-kit
+**/.vercel
+.github/CODEOWNERS
+.prettierignore
+.changeset
+pnpm-lock.yaml
+pnpm-workspace.yaml
diff --git a/.prettierrc b/.prettierrc
index 81451039faf5..c4fd5d9f2f73 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,3 +1,28 @@
-useTabs: true
-singleQuote: true
-trailingComma: es5
+{
+ "useTabs": true,
+ "singleQuote": true,
+ "trailingComma": "none",
+ "printWidth": 100,
+ "plugins": ["prettier-plugin-svelte"],
+ "overrides": [
+ {
+ "files": ["*.svelte"],
+ "options": {
+ "bracketSameLine": false
+ }
+ },
+ {
+ "files": ["README.md", "packages/*/README.md", "**/package.json"],
+ "options": {
+ "useTabs": false,
+ "tabWidth": 2
+ }
+ },
+ {
+ "files": ["sites/svelte-5-preview/src/routes/docs/content/**/*.md"],
+ "options": {
+ "printWidth": 60
+ }
+ }
+ ]
+}
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 000000000000..142965ada292
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,14 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "Run sandbox",
+ "program": "${workspaceFolder}/playgrounds/sandbox/run.js",
+ "env": {
+ "NODE_OPTIONS": "--stack-trace-limit=10000"
+ }
+ }
+ ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000000..21a2a11c84e3
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,6 @@
+{
+ "search.exclude": {
+ "sites/svelte-5-preview/static/*": true
+ },
+ "typescript.tsdk": "node_modules/typescript/lib"
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index 25c0aa209326..000000000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,1816 +0,0 @@
-# Svelte changelog
-
-## Unreleased
-
-* Prevent text input cursor jumping in Safari with one-way binding ([#3449](https://github.com/sveltejs/svelte/issues/3449))
-* Expose compiler version in dev events ([#4047](https://github.com/sveltejs/svelte/issues/4047))
-* Don't run actions before their element is in the document ([#4166](https://github.com/sveltejs/svelte/issues/4166))
-* Fix reactive assignments with destructuring and stores where the destructured value should be undefined ([#4170](https://github.com/sveltejs/svelte/issues/4170))
-* Fix hydrating `{:else}` in `{#each}` ([#4202](https://github.com/sveltejs/svelte/issues/4202))
-* Do not automatically declare variables in reactive declarations when assigning to a member expression ([#4212](https://github.com/sveltejs/svelte/issues/4212))
-
-## 3.16.7
-
-* Also apply actions in the order they're given along with other directives ([#2446](https://github.com/sveltejs/svelte/issues/2446), [#4156](https://github.com/sveltejs/svelte/pull/4156))
-* Check whether a dynamic event handler is a function before calling it ([#4090](https://github.com/sveltejs/svelte/issues/4090))
-* Correctly mark event handlers as dynamic when they involve an expression used in a `bind:` elsewhere ([#4155](https://github.com/sveltejs/svelte/pull/4155))
-
-## 3.16.6
-
-* Fix CSS specificity bug when encapsulating styles ([#1277](https://github.com/sveltejs/svelte/issues/1277))
-* Apply directives in the order they're given ([#2446](https://github.com/sveltejs/svelte/issues/2446))
-* Fix destructuring in `let:` directives ([#2751](https://github.com/sveltejs/svelte/issues/2751))
-* Preserve whitespace around ``s in `
` will result in `
hello
world
` (the `
` autoclosed the `
` because `
` cannot contain block-level elements)
+- `` will result in `` (the `
` is removed)
+- `
cell
` will result in `
cell
` (a `` is auto-inserted)
+
+This code will work when the component is rendered on the client (which is why this is a warning rather than an error), but if you use server rendering it will cause hydration to fail.
+
+### non_reactive_update
+
+```
+`%name%` is updated, but is not declared with `$state(...)`. Changing its value will not correctly trigger updates
+```
+
+This warning is thrown when the compiler detects the following:
+- a variable was declared without `$state` or `$state.raw`
+- the variable is reassigned
+- the variable is read in a reactive context
+
+In this case, changing the value will not correctly trigger updates. Example:
+
+```svelte
+
+
+
This value updates: {reactive}
+
This value does not update: {stale}
+
+
+```
+
+To fix this, wrap your variable declaration with `$state`.
+
+### options_deprecated_accessors
+
+```
+The `accessors` option has been deprecated. It will have no effect in runes mode
+```
+
+### options_deprecated_immutable
+
+```
+The `immutable` option has been deprecated. It will have no effect in runes mode
+```
+
+### options_missing_custom_element
+
+```
+The `customElement` option is used when generating a custom element. Did you forget the `customElement: true` compile option?
+```
+
+### options_removed_enable_sourcemap
+
+```
+The `enableSourcemap` option has been removed. Source maps are always generated now, and tooling can choose to ignore them
+```
+
+### options_removed_hydratable
+
+```
+The `hydratable` option has been removed. Svelte components are always hydratable now
+```
+
+### options_removed_loop_guard_timeout
+
+```
+The `loopGuardTimeout` option has been removed
+```
+
+### options_renamed_ssr_dom
+
+```
+`generate: "dom"` and `generate: "ssr"` options have been renamed to "client" and "server" respectively
+```
+
+### perf_avoid_inline_class
+
+```
+Avoid 'new class' — instead, declare the class at the top level scope
+```
+
+### perf_avoid_nested_class
+
+```
+Avoid declaring classes below the top level scope
+```
+
+### reactive_declaration_invalid_placement
+
+```
+Reactive declarations only exist at the top level of the instance script
+```
+
+### reactive_declaration_module_script_dependency
+
+```
+Reassignments of module-level declarations will not cause reactive statements to update
+```
+
+### script_context_deprecated
+
+```
+`context="module"` is deprecated, use the `module` attribute instead
+```
+
+```svelte
+
+```
+
+### script_unknown_attribute
+
+```
+Unrecognized attribute — should be one of `generics`, `lang` or `module`. If this exists for a preprocessor, ensure that the preprocessor removes it
+```
+
+### slot_element_deprecated
+
+```
+Using `` to render parent content is deprecated. Use `{@render ...}` tags instead
+```
+
+See [the migration guide](v5-migration-guide#Snippets-instead-of-slots) for more info.
+
+### state_referenced_locally
+
+```
+This reference only captures the initial value of `%name%`. Did you mean to reference it inside a %type% instead?
+```
+
+This warning is thrown when the compiler detects the following:
+
+- A reactive variable is declared
+- ...and later reassigned...
+- ...and referenced in the same scope
+
+This 'breaks the link' to the original state declaration. For example, if you pass the state to a function, the function loses access to the state once it is reassigned:
+
+```svelte
+
+
+
+
+```
+
+```svelte
+
+
+
+
+
The count is {count}
+```
+
+To fix this, reference the variable such that it is lazily evaluated. For the above example, this can be achieved by wrapping `count` in a function:
+
+```svelte
+
+
+
+
+```
+
+```svelte
+
+
+
+
+
The count is {+++count()+++}
+```
+
+For more info, see [Passing state into functions]($state#Passing-state-into-functions).
+
+### store_rune_conflict
+
+```
+It looks like you're using the `$%name%` rune, but there is a local binding called `%name%`. Referencing a local variable with a `$` prefix will create a store subscription. Please rename `%name%` to avoid the ambiguity
+```
+
+### svelte_component_deprecated
+
+```
+`` is deprecated in runes mode — components are dynamic by default
+```
+
+In previous versions of Svelte, the component constructor was fixed when the component was rendered. In other words, if you wanted `` to re-render when `X` changed, you would either have to use `` or put the component inside a `{#key X}...{/key}` block.
+
+In Svelte 5 this is no longer true — if `X` changes, `` re-renders.
+
+In some cases `` syntax can be used as a replacement; a lowercased variable with property access is recognized as a component in Svelte 5.
+
+For complex component resolution logic, an intermediary, capitalized variable may be necessary. E.g. in places where `@const` can be used:
+
+
+```svelte
+{#each items as item}
+ ------
+ +++{@const Component = item.condition ? Y : Z}+++
+ ++++++
+{/each}
+```
+
+A derived value may be used in other contexts:
+
+
+```svelte
+
+
+------
+++++++
+```
+
+### svelte_element_invalid_this
+
+```
+`this` should be an `{expression}`. Using a string attribute value will cause an error in future versions of Svelte
+```
+
+### svelte_self_deprecated
+
+```
+`` is deprecated — use self-imports (e.g. `import %name% from './%basename%'`) instead
+```
+
+See [the note in the docs](legacy-svelte-self) for more info.
+
+### unknown_code
+
+```
+`%code%` is not a recognised code
+```
+
+```
+`%code%` is not a recognised code (did you mean `%suggestion%`?)
+```
diff --git a/documentation/docs/98-reference/.generated/server-errors.md b/documentation/docs/98-reference/.generated/server-errors.md
new file mode 100644
index 000000000000..c3e8b53c3145
--- /dev/null
+++ b/documentation/docs/98-reference/.generated/server-errors.md
@@ -0,0 +1,9 @@
+
+
+### lifecycle_function_unavailable
+
+```
+`%name%(...)` is not available on the server
+```
+
+Certain methods such as `mount` cannot be invoked while running in a server context. Avoid calling them eagerly, i.e. not during render.
diff --git a/documentation/docs/98-reference/.generated/shared-errors.md b/documentation/docs/98-reference/.generated/shared-errors.md
new file mode 100644
index 000000000000..6c31aaafd0df
--- /dev/null
+++ b/documentation/docs/98-reference/.generated/shared-errors.md
@@ -0,0 +1,110 @@
+
+
+### invalid_default_snippet
+
+```
+Cannot use `{@render children(...)}` if the parent component uses `let:` directives. Consider using a named snippet instead
+```
+
+This error would be thrown in a setup like this:
+
+```svelte
+
+
+ {entry}
+
+```
+
+```svelte
+
+
+
+
+ {#each items as item}
+
{@render children(item)}
+ {/each}
+
+```
+
+Here, `List.svelte` is using `{@render children(item)` which means it expects `Parent.svelte` to use snippets. Instead, `Parent.svelte` uses the deprecated `let:` directive. This combination of APIs is incompatible, hence the error.
+
+### invalid_snippet_arguments
+
+```
+A snippet function was passed invalid arguments. Snippets should only be instantiated via `{@render ...}`
+```
+
+### lifecycle_outside_component
+
+```
+`%name%(...)` can only be used during component initialisation
+```
+
+Certain lifecycle methods can only be used during component initialisation. To fix this, make sure you're invoking the method inside the _top level of the instance script_ of your component.
+
+```svelte
+
+
+
+```
+
+### snippet_without_render_tag
+
+```
+Attempted to render a snippet without a `{@render}` block. This would cause the snippet code to be stringified instead of its content being rendered to the DOM. To fix this, change `{snippet}` to `{@render snippet()}`.
+```
+
+A component throwing this error will look something like this (`children` is not being rendered):
+
+```svelte
+
+
+{children}
+```
+
+...or like this (a parent component is passing a snippet where a non-snippet value is expected):
+
+```svelte
+
+
+ {#snippet label()}
+ Hi!
+ {/snippet}
+
+```
+
+```svelte
+
+
+
+
+
{label}
+```
+
+### store_invalid_shape
+
+```
+`%name%` is not a store with a `subscribe` method
+```
+
+### svelte_element_invalid_this_value
+
+```
+The `this` prop on `` must be a string, if defined
+```
diff --git a/documentation/docs/98-reference/.generated/shared-warnings.md b/documentation/docs/98-reference/.generated/shared-warnings.md
new file mode 100644
index 000000000000..f449a4031ebf
--- /dev/null
+++ b/documentation/docs/98-reference/.generated/shared-warnings.md
@@ -0,0 +1,28 @@
+
+
+### dynamic_void_element_content
+
+```
+`` is a void element — it cannot have content
+```
+
+Elements such as `` cannot have content, any children passed to these elements will be ignored.
+
+### state_snapshot_uncloneable
+
+```
+Value cannot be cloned with `$state.snapshot` — the original value was returned
+```
+
+```
+The following properties cannot be cloned with `$state.snapshot` — the return value contains the originals:
+
+%properties%
+```
+
+`$state.snapshot` tries to clone the given value in order to return a reference that no longer changes. Certain objects may not be cloneable, in which case the original value is returned. In the following example, `property` is cloned, but `window` is not, because DOM elements are uncloneable:
+
+```js
+const object = $state({ property: 'this is cloneable', window })
+const snapshot = $state.snapshot(object);
+```
diff --git a/documentation/docs/98-reference/20-svelte.md b/documentation/docs/98-reference/20-svelte.md
new file mode 100644
index 000000000000..3295ab68de65
--- /dev/null
+++ b/documentation/docs/98-reference/20-svelte.md
@@ -0,0 +1,5 @@
+---
+title: svelte
+---
+
+> MODULE: svelte
diff --git a/documentation/docs/98-reference/21-svelte-action.md b/documentation/docs/98-reference/21-svelte-action.md
new file mode 100644
index 000000000000..53423ec4090e
--- /dev/null
+++ b/documentation/docs/98-reference/21-svelte-action.md
@@ -0,0 +1,5 @@
+---
+title: svelte/action
+---
+
+> MODULE: svelte/action
diff --git a/documentation/docs/98-reference/21-svelte-animate.md b/documentation/docs/98-reference/21-svelte-animate.md
new file mode 100644
index 000000000000..e8f135d07de0
--- /dev/null
+++ b/documentation/docs/98-reference/21-svelte-animate.md
@@ -0,0 +1,5 @@
+---
+title: svelte/animate
+---
+
+> MODULE: svelte/animate
diff --git a/documentation/docs/98-reference/21-svelte-compiler.md b/documentation/docs/98-reference/21-svelte-compiler.md
new file mode 100644
index 000000000000..a6cc99d3b155
--- /dev/null
+++ b/documentation/docs/98-reference/21-svelte-compiler.md
@@ -0,0 +1,5 @@
+---
+title: svelte/compiler
+---
+
+> MODULE: svelte/compiler
diff --git a/documentation/docs/98-reference/21-svelte-easing.md b/documentation/docs/98-reference/21-svelte-easing.md
new file mode 100644
index 000000000000..3f47963cde9a
--- /dev/null
+++ b/documentation/docs/98-reference/21-svelte-easing.md
@@ -0,0 +1,5 @@
+---
+title: svelte/easing
+---
+
+> MODULE: svelte/easing
diff --git a/documentation/docs/98-reference/21-svelte-events.md b/documentation/docs/98-reference/21-svelte-events.md
new file mode 100644
index 000000000000..00c7a14ee203
--- /dev/null
+++ b/documentation/docs/98-reference/21-svelte-events.md
@@ -0,0 +1,5 @@
+---
+title: svelte/events
+---
+
+> MODULE: svelte/events
diff --git a/documentation/docs/98-reference/21-svelte-legacy.md b/documentation/docs/98-reference/21-svelte-legacy.md
new file mode 100644
index 000000000000..f313baca0b45
--- /dev/null
+++ b/documentation/docs/98-reference/21-svelte-legacy.md
@@ -0,0 +1,7 @@
+---
+title: svelte/legacy
+---
+
+This module provides various functions for use during the migration, since some features can't be replaced one to one with new features. All imports are marked as deprecated and should be migrated away from over time.
+
+> MODULE: svelte/legacy
diff --git a/documentation/docs/98-reference/21-svelte-motion.md b/documentation/docs/98-reference/21-svelte-motion.md
new file mode 100644
index 000000000000..f1d5a6ce5757
--- /dev/null
+++ b/documentation/docs/98-reference/21-svelte-motion.md
@@ -0,0 +1,5 @@
+---
+title: svelte/motion
+---
+
+> MODULE: svelte/motion
diff --git a/documentation/docs/98-reference/21-svelte-reactivity-window.md b/documentation/docs/98-reference/21-svelte-reactivity-window.md
new file mode 100644
index 000000000000..cc544dc5ba3f
--- /dev/null
+++ b/documentation/docs/98-reference/21-svelte-reactivity-window.md
@@ -0,0 +1,15 @@
+---
+title: svelte/reactivity/window
+---
+
+This module exports reactive versions of various `window` values, each of which has a reactive `current` property that you can reference in reactive contexts (templates, [deriveds]($derived) and [effects]($effect)) without using [``](svelte-window) bindings or manually creating your own event listeners.
+
+```svelte
+
+
+
{innerWidth.current}x{innerHeight.current}
+```
+
+> MODULE: svelte/reactivity/window
diff --git a/documentation/docs/98-reference/21-svelte-reactivity.md b/documentation/docs/98-reference/21-svelte-reactivity.md
new file mode 100644
index 000000000000..8070331f481b
--- /dev/null
+++ b/documentation/docs/98-reference/21-svelte-reactivity.md
@@ -0,0 +1,7 @@
+---
+title: svelte/reactivity
+---
+
+Svelte provides reactive versions of various built-ins like [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) and [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) that can be used just like their native counterparts, as well as a handful of additional utilities for handling reactivity.
+
+> MODULE: svelte/reactivity
diff --git a/documentation/docs/98-reference/21-svelte-server.md b/documentation/docs/98-reference/21-svelte-server.md
new file mode 100644
index 000000000000..7a3fc3c6a2ba
--- /dev/null
+++ b/documentation/docs/98-reference/21-svelte-server.md
@@ -0,0 +1,5 @@
+---
+title: svelte/server
+---
+
+> MODULE: svelte/server
diff --git a/documentation/docs/98-reference/21-svelte-store.md b/documentation/docs/98-reference/21-svelte-store.md
new file mode 100644
index 000000000000..23ff6c5e376f
--- /dev/null
+++ b/documentation/docs/98-reference/21-svelte-store.md
@@ -0,0 +1,5 @@
+---
+title: svelte/store
+---
+
+> MODULE: svelte/store
diff --git a/documentation/docs/98-reference/21-svelte-transition.md b/documentation/docs/98-reference/21-svelte-transition.md
new file mode 100644
index 000000000000..396bc0aebf69
--- /dev/null
+++ b/documentation/docs/98-reference/21-svelte-transition.md
@@ -0,0 +1,5 @@
+---
+title: svelte/transition
+---
+
+> MODULE: svelte/transition
diff --git a/documentation/docs/98-reference/30-compiler-errors.md b/documentation/docs/98-reference/30-compiler-errors.md
new file mode 100644
index 000000000000..ae22029155d3
--- /dev/null
+++ b/documentation/docs/98-reference/30-compiler-errors.md
@@ -0,0 +1,5 @@
+---
+title: 'Compiler errors'
+---
+
+@include .generated/compile-errors.md
diff --git a/documentation/docs/98-reference/30-compiler-warnings.md b/documentation/docs/98-reference/30-compiler-warnings.md
new file mode 100644
index 000000000000..43ba71250f5b
--- /dev/null
+++ b/documentation/docs/98-reference/30-compiler-warnings.md
@@ -0,0 +1,21 @@
+---
+title: 'Compiler warnings'
+---
+
+Svelte warns you at compile time if it catches potential mistakes, such as writing inaccessible markup.
+
+Some warnings may be incorrect in your concrete use case. You can disable such false positives by placing a `` comment above the line that causes the warning. Example:
+
+```svelte
+
+
+```
+
+You can list multiple rules in a single comment (separated by commas), and add an explanatory note (in parentheses) alongside them:
+
+```svelte
+
+
...
+```
+
+@include .generated/compile-warnings.md
diff --git a/documentation/docs/98-reference/30-runtime-errors.md b/documentation/docs/98-reference/30-runtime-errors.md
new file mode 100644
index 000000000000..43ce98958751
--- /dev/null
+++ b/documentation/docs/98-reference/30-runtime-errors.md
@@ -0,0 +1,15 @@
+---
+title: 'Runtime errors'
+---
+
+## Client errors
+
+@include .generated/client-errors.md
+
+## Server errors
+
+@include .generated/server-errors.md
+
+## Shared errors
+
+@include .generated/shared-errors.md
diff --git a/documentation/docs/98-reference/30-runtime-warnings.md b/documentation/docs/98-reference/30-runtime-warnings.md
new file mode 100644
index 000000000000..edc5890ac0fa
--- /dev/null
+++ b/documentation/docs/98-reference/30-runtime-warnings.md
@@ -0,0 +1,11 @@
+---
+title: 'Runtime warnings'
+---
+
+## Client warnings
+
+@include .generated/client-warnings.md
+
+## Shared warnings
+
+@include .generated/shared-warnings.md
diff --git a/documentation/docs/98-reference/index.md b/documentation/docs/98-reference/index.md
new file mode 100644
index 000000000000..b98302768eb0
--- /dev/null
+++ b/documentation/docs/98-reference/index.md
@@ -0,0 +1,3 @@
+---
+title: Reference
+---
diff --git a/documentation/docs/99-legacy/00-legacy-overview.md b/documentation/docs/99-legacy/00-legacy-overview.md
new file mode 100644
index 000000000000..638a77ec1a76
--- /dev/null
+++ b/documentation/docs/99-legacy/00-legacy-overview.md
@@ -0,0 +1,14 @@
+---
+title: Overview
+---
+
+Svelte 5 introduced some significant changes to Svelte's API, including [runes](what-are-runes), [snippets](snippet) and event attributes. As a result, some Svelte 3/4 features are deprecated (though supported for now, unless otherwise specified) and will eventually be removed. We recommend that you incrementally [migrate your existing code](v5-migration-guide).
+
+The following pages document these features for
+
+- people still using Svelte 3/4
+- people using Svelte 5, but with components that haven't yet been migrated
+
+Since Svelte 3/4 syntax still works in Svelte 5, we will distinguish between _legacy mode_ and _runes mode_. Once a component is in runes mode (which you can opt into by using runes, or by explicitly setting the `runes: true` compiler option), legacy mode features are no longer available.
+
+If you're exclusively interested in the Svelte 3/4 syntax, you can browse its documentation at [v4.svelte.dev](https://v4.svelte.dev).
diff --git a/documentation/docs/99-legacy/01-legacy-let.md b/documentation/docs/99-legacy/01-legacy-let.md
new file mode 100644
index 000000000000..0d1a0a72bf11
--- /dev/null
+++ b/documentation/docs/99-legacy/01-legacy-let.md
@@ -0,0 +1,34 @@
+---
+title: Reactive let/var declarations
+---
+
+In runes mode, reactive state is explicitly declared with the [`$state` rune]($state).
+
+In legacy mode, variables declared at the top level of a component are automatically considered _reactive_. Reassigning or mutating these variables (`count += 1` or `object.x = y`) will cause the UI to update.
+
+```svelte
+
+
+
+```
+
+Because Svelte's legacy mode reactivity is based on _assignments_, using array methods like `.push()` and `.splice()` won't automatically trigger updates. A subsequent assignment is required to 'tell' the compiler to update the UI:
+
+```svelte
+
+```
diff --git a/documentation/docs/99-legacy/02-legacy-reactive-assignments.md b/documentation/docs/99-legacy/02-legacy-reactive-assignments.md
new file mode 100644
index 000000000000..5abd481bfc74
--- /dev/null
+++ b/documentation/docs/99-legacy/02-legacy-reactive-assignments.md
@@ -0,0 +1,87 @@
+---
+title: Reactive $: statements
+---
+
+In runes mode, reactions to state updates are handled with the [`$derived`]($derived) and [`$effect`]($effect) runes.
+
+In legacy mode, any top-level statement (i.e. not inside a block or a function) can be made reactive by prefixing it with a `$:` [label](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label). These statements run after other code in the `
+```
+
+Statements are ordered _topologically_ by their dependencies and their assignments: since the `console.log` statement depends on `sum`, `sum` is calculated first even though it appears later in the source.
+
+Multiple statements can be combined by putting them in a block:
+
+```js
+// @noErrors
+$: {
+ // recalculate `total` when `items` changes
+ total = 0;
+
+ for (const item of items) {
+ total += item.value;
+ }
+}
+```
+
+The left-hand side of a reactive assignments can be an identifier, or it can be a destructuring assignment:
+
+```js
+// @noErrors
+$: ({ larry, moe, curly } = stooges);
+```
+
+## Understanding dependencies
+
+The dependencies of a `$:` statement are determined at compile time — they are whichever variables are referenced (but not assigned to) inside the statement.
+
+In other words, a statement like this will _not_ re-run when `count` changes, because the compiler cannot 'see' the dependency:
+
+```js
+// @noErrors
+let count = 0;
+let double = () => count * 2;
+
+$: doubled = double();
+```
+
+Similarly, topological ordering will fail if dependencies are referenced indirectly: `z` will never update, because `y` is not considered 'dirty' when the update occurs. Moving `$: z = y` below `$: setY(x)` will fix it:
+
+```svelte
+
+```
+
+## Browser-only code
+
+Reactive statements run during server-side rendering as well as in the browser. This means that any code that should only run in the browser must be wrapped in an `if` block:
+
+```js
+// @noErrors
+$: if (browser) {
+ document.title = title;
+}
+```
diff --git a/documentation/docs/99-legacy/03-legacy-export-let.md b/documentation/docs/99-legacy/03-legacy-export-let.md
new file mode 100644
index 000000000000..877e105b1fa2
--- /dev/null
+++ b/documentation/docs/99-legacy/03-legacy-export-let.md
@@ -0,0 +1,72 @@
+---
+title: export let
+---
+
+In runes mode, [component props](basic-markup#Component-props) are declared with the [`$props`]($props) rune, allowing parent components to pass in data.
+
+In legacy mode, props are marked with the `export` keyword, and can have a default value:
+
+```svelte
+
+```
+
+The default value is used if it would otherwise be `undefined` when the component is created.
+
+> [!NOTE] Unlike in runes mode, if the parent component changes a prop from a defined value to `undefined`, it does not revert to the initial value.
+
+Props without default values are considered _required_, and Svelte will print a warning during development if no value is provided, which you can squelch by specifying `undefined` as the default value:
+
+```js
+export let foo +++= undefined;+++
+```
+
+## Component exports
+
+An exported `const`, `class` or `function` declaration is _not_ considered a prop — instead, it becomes part of the component's API:
+
+```svelte
+
+
+```
+
+```svelte
+
+
+
+
+
+
+```
+
+## Renaming props
+
+The `export` keyword can appear separately from the declaration. This is useful for renaming props, for example in the case of a reserved word:
+
+```svelte
+
+
+```
diff --git a/documentation/docs/99-legacy/04-legacy-$$props-and-$$restProps.md b/documentation/docs/99-legacy/04-legacy-$$props-and-$$restProps.md
new file mode 100644
index 000000000000..33cac97035af
--- /dev/null
+++ b/documentation/docs/99-legacy/04-legacy-$$props-and-$$restProps.md
@@ -0,0 +1,30 @@
+---
+title: $$props and $$restProps
+---
+
+In runes mode, getting an object containing all the props that were passed in is easy, using the [`$props`]($props) rune.
+
+In legacy mode, we use `$$props` and `$$restProps`:
+
+- `$$props` contains all the props that were passed in, including ones that are not individually declared with the `export` keyword
+- `$$restProps` contains all the props that were passed in _except_ the ones that were individually declared
+
+For example, a `