diff --git a/.cursor/rules/actor-core-rules.mdc b/.cursor/rules/actor-core-rules.mdc
index 4de859b00..c407cdbf0 100644
--- a/.cursor/rules/actor-core-rules.mdc
+++ b/.cursor/rules/actor-core-rules.mdc
@@ -1,6 +1,6 @@
---
description: ActorCore rules
-globs:
+globs:
alwaysApply: false
---
# ActorCore Development Guide
@@ -59,11 +59,11 @@ When importing from workspace packages, always check the package's `package.json
- **Formatting:** Uses Biome for consistent formatting
- **Imports:** Organized imports enforced, unused imports warned
- **TypeScript:** Strict mode enabled, target ESNext
-- **Naming:**
+- **Naming:**
- camelCase for variables, functions
- PascalCase for classes, interfaces, types
- UPPER_CASE for constants
-- **Error Handling:**
+- **Error Handling:**
- Use `UserError` for client-safe errors
- Use `InternalError` for internal errors
@@ -105,7 +105,7 @@ When importing from workspace packages, always check the package's `package.json
- `createState()`: Function that returns initial actor state
- `onStart(c)`: Called any time actor is started (after restart/upgrade)
-- `onStateChange(c, newState)`: Called when actor state changes
+- `onStateChange(c,prevState, newState)`: Called when actor state changes
- `onBeforeConnect(c)`: Called when new client connects
- `onConnect(c)`: Executed after client connection succeeds
- `onDisconnect(c)`: Called when client disconnects
@@ -144,4 +144,4 @@ When importing from workspace packages, always check the package's `package.json
- Use `assertUnreachable(x: never)` for exhaustive type checking
- Add proper JSDoc comments for public APIs
- Run `yarn check-types` regularly during development
-- Use `tsx` CLI to execute TypeScript scripts directly
\ No newline at end of file
+- Use `tsx` CLI to execute TypeScript scripts directly
diff --git a/.gitignore b/.gitignore
index fbba480f7..696fba77e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -93,7 +93,12 @@ out
# Nuxt.js build / generate output
.nuxt
-dist
+
+# Build output - ignore dist folders except in packages/actor
+dist/
+packages/*/dist/
+examples/*/dist/
+!packages/actor/dist/
# Gatsby files
.cache/
diff --git a/examples/svelte/.gitignore b/examples/svelte/.gitignore
new file mode 100644
index 000000000..3b462cb0c
--- /dev/null
+++ b/examples/svelte/.gitignore
@@ -0,0 +1,23 @@
+node_modules
+
+# Output
+.output
+.vercel
+.netlify
+.wrangler
+/.svelte-kit
+/build
+
+# OS
+.DS_Store
+Thumbs.db
+
+# Env
+.env
+.env.*
+!.env.example
+!.env.test
+
+# Vite
+vite.config.js.timestamp-*
+vite.config.ts.timestamp-*
diff --git a/examples/svelte/.npmrc b/examples/svelte/.npmrc
new file mode 100644
index 000000000..b6f27f135
--- /dev/null
+++ b/examples/svelte/.npmrc
@@ -0,0 +1 @@
+engine-strict=true
diff --git a/examples/svelte/README.md b/examples/svelte/README.md
new file mode 100644
index 000000000..75842c404
--- /dev/null
+++ b/examples/svelte/README.md
@@ -0,0 +1,38 @@
+# sv
+
+Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
+
+## Creating a project
+
+If you're seeing this, you've probably already done this step. Congrats!
+
+```sh
+# create a new project in the current directory
+npx sv create
+
+# create a new project in my-app
+npx sv create my-app
+```
+
+## Developing
+
+Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
+
+```sh
+npm run dev
+
+# or start the server and open the app in a new browser tab
+npm run dev -- --open
+```
+
+## Building
+
+To create a production version of your app:
+
+```sh
+npm run build
+```
+
+You can preview the production build with `npm run preview`.
+
+> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
diff --git a/examples/svelte/backend/index.ts b/examples/svelte/backend/index.ts
new file mode 100644
index 000000000..ed20d2c55
--- /dev/null
+++ b/examples/svelte/backend/index.ts
@@ -0,0 +1,9 @@
+import { registry } from "./registry";
+
+export type Registry = typeof registry;
+
+registry.runServer({
+ cors: {
+ origin: "http://localhost:5173",
+ },
+});
diff --git a/examples/svelte/backend/registry.ts b/examples/svelte/backend/registry.ts
new file mode 100644
index 000000000..575edd974
--- /dev/null
+++ b/examples/svelte/backend/registry.ts
@@ -0,0 +1,25 @@
+import { actor, setup } from "@rivetkit/actor";
+
+export const counter = actor({
+ onAuth: () => {
+ // Configure auth here
+ },
+ state: { count: 0 },
+ actions: {
+ increment: (c, x: number) => {
+ console.log("incrementing by", x);
+ c.state.count += x;
+ c.broadcast("newCount", c.state.count);
+ return c.state.count;
+ },
+ reset: (c) => {
+ c.state.count = 0;
+ c.broadcast("newCount", c.state.count);
+ return c.state.count;
+ },
+ },
+});
+
+export const registry = setup({
+ use: { counter },
+});
diff --git a/examples/svelte/package.json b/examples/svelte/package.json
new file mode 100644
index 000000000..b0595b124
--- /dev/null
+++ b/examples/svelte/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "svelte-rivetkit-example",
+ "private": true,
+ "version": "0.0.1",
+ "type": "module",
+ "scripts": {
+ "dev": "run-p dev:web dev:api",
+ "dev:web": "vite dev",
+ "dev:api": "tsx --watch backend/index.ts",
+ "build": "vite build",
+ "preview": "vite preview",
+ "prepare": "svelte-kit sync || echo ''",
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
+ },
+ "devDependencies": {
+ "@rivetkit/actor": "workspace:*",
+ "@rivetkit/svelte": "workspace:*",
+ "@sveltejs/adapter-auto": "^6.0.0",
+ "@sveltejs/kit": "^2.22.0",
+ "@sveltejs/vite-plugin-svelte": "^6.0.0",
+ "@types/node": "^22.13.9",
+ "svelte": "^5.0.0",
+ "svelte-check": "^4.0.0",
+ "typescript": "^5.0.0",
+ "vite": "^7.0.4",
+ "npm-run-all": "^4.1.5",
+ "tsx": "^3.12.7"
+ }
+}
diff --git a/examples/svelte/src/app.d.ts b/examples/svelte/src/app.d.ts
new file mode 100644
index 000000000..da08e6da5
--- /dev/null
+++ b/examples/svelte/src/app.d.ts
@@ -0,0 +1,13 @@
+// See https://svelte.dev/docs/kit/types#app.d.ts
+// for information about these interfaces
+declare global {
+ namespace App {
+ // interface Error {}
+ // interface Locals {}
+ // interface PageData {}
+ // interface PageState {}
+ // interface Platform {}
+ }
+}
+
+export {};
diff --git a/examples/svelte/src/app.html b/examples/svelte/src/app.html
new file mode 100644
index 000000000..f273cc58f
--- /dev/null
+++ b/examples/svelte/src/app.html
@@ -0,0 +1,11 @@
+
+
+
+
+
+ %sveltekit.head%
+
+
+
%sveltekit.body%
+
+
diff --git a/examples/svelte/src/lib/actor-client.ts b/examples/svelte/src/lib/actor-client.ts
new file mode 100644
index 000000000..3e1952c67
--- /dev/null
+++ b/examples/svelte/src/lib/actor-client.ts
@@ -0,0 +1,5 @@
+import { createClient, createRivetKit } from "@rivetkit/svelte";
+import type { Registry } from "../../backend";
+
+const client = createClient(`http://localhost:8080`);
+export const { useActor } = createRivetKit(client);
diff --git a/examples/svelte/src/lib/assets/favicon.svg b/examples/svelte/src/lib/assets/favicon.svg
new file mode 100644
index 000000000..cc5dc66a3
--- /dev/null
+++ b/examples/svelte/src/lib/assets/favicon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/examples/svelte/src/lib/index.ts b/examples/svelte/src/lib/index.ts
new file mode 100644
index 000000000..856f2b6c3
--- /dev/null
+++ b/examples/svelte/src/lib/index.ts
@@ -0,0 +1 @@
+// place files you want to import through the `$lib` alias in this folder.
diff --git a/examples/svelte/src/routes/+layout.server.ts b/examples/svelte/src/routes/+layout.server.ts
new file mode 100644
index 000000000..a3d15781a
--- /dev/null
+++ b/examples/svelte/src/routes/+layout.server.ts
@@ -0,0 +1 @@
+export const ssr = false;
diff --git a/examples/svelte/src/routes/+layout.svelte b/examples/svelte/src/routes/+layout.svelte
new file mode 100644
index 000000000..20f8d044f
--- /dev/null
+++ b/examples/svelte/src/routes/+layout.svelte
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+{@render children?.()}
diff --git a/examples/svelte/src/routes/+page.svelte b/examples/svelte/src/routes/+page.svelte
new file mode 100644
index 000000000..31fdeeb0f
--- /dev/null
+++ b/examples/svelte/src/routes/+page.svelte
@@ -0,0 +1,40 @@
+
+
+
+
Counter: {count}
+
+
+
diff --git a/examples/svelte/static/robots.txt b/examples/svelte/static/robots.txt
new file mode 100644
index 000000000..b6dd6670c
--- /dev/null
+++ b/examples/svelte/static/robots.txt
@@ -0,0 +1,3 @@
+# allow crawling everything by default
+User-agent: *
+Disallow:
diff --git a/examples/svelte/svelte.config.js b/examples/svelte/svelte.config.js
new file mode 100644
index 000000000..ee7b6dcdc
--- /dev/null
+++ b/examples/svelte/svelte.config.js
@@ -0,0 +1,24 @@
+import adapter from "@sveltejs/adapter-auto";
+import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
+
+/** @type {import('@sveltejs/kit').Config} */
+const config = {
+ // Consult https://svelte.dev/docs/kit/integrations
+ // for more information about preprocessors
+ preprocess: vitePreprocess(),
+
+ kit: {
+ // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
+ // If your environment is not supported, or you settled on a specific environment, switch out the adapter.
+ // See https://svelte.dev/docs/kit/adapters for more information about adapters.
+ adapter: adapter(),
+ alias: {
+ $: "./src",
+ "$/*": "./src/*",
+ $backend: "./backend",
+ "$backend/*": "./backend/*",
+ },
+ },
+};
+
+export default config;
diff --git a/examples/svelte/tsconfig.json b/examples/svelte/tsconfig.json
new file mode 100644
index 000000000..3fa098ab6
--- /dev/null
+++ b/examples/svelte/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "extends": "./.svelte-kit/tsconfig.json",
+ "compilerOptions": {
+ "allowJs": true,
+ "checkJs": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "strict": true,
+ "moduleResolution": "bundler",
+ "baseUrl": "./",
+ "paths": {
+ "$/": ["./src/"],
+ "$backend/": ["./backend/"]
+ }
+ }
+ // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
+ // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
+ //
+ // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
+ // from the referenced tsconfig.json - TypeScript does not merge them in
+}
diff --git a/examples/svelte/turbo.json b/examples/svelte/turbo.json
new file mode 100644
index 000000000..95960709b
--- /dev/null
+++ b/examples/svelte/turbo.json
@@ -0,0 +1,4 @@
+{
+ "$schema": "https://turbo.build/schema.json",
+ "extends": ["//"]
+}
diff --git a/examples/svelte/vite.config.ts b/examples/svelte/vite.config.ts
new file mode 100644
index 000000000..6b9eb5d39
--- /dev/null
+++ b/examples/svelte/vite.config.ts
@@ -0,0 +1,6 @@
+import { sveltekit } from "@sveltejs/kit/vite";
+import { defineConfig } from "vite";
+
+export default defineConfig({
+ plugins: [sveltekit()],
+});
diff --git a/examples/sync/tsconfig.json b/examples/sync/tsconfig.json
index 4232a7296..670d5b1d3 100644
--- a/examples/sync/tsconfig.json
+++ b/examples/sync/tsconfig.json
@@ -15,6 +15,6 @@
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
- "include": ["src", "tests"],
+ "include": ["src", "backend"],
"exclude": ["node_modules", "dist"]
}
diff --git a/package.json b/package.json
index 3f9f44d26..c754cea57 100644
--- a/package.json
+++ b/package.json
@@ -37,5 +37,10 @@
"@hono/node-ws": "^1.1.7",
"esbuild": "^0.25.1"
},
- "packageManager": "pnpm@10.7.1+sha512.2d92c86b7928dc8284f53494fb4201f983da65f0fb4f0d40baafa5cf628fa31dae3e5968f12466f17df7e97310e30f343a648baea1b9b350685dafafffdf5808"
+ "packageManager": "pnpm@10.7.1+sha512.2d92c86b7928dc8284f53494fb4201f983da65f0fb4f0d40baafa5cf628fa31dae3e5968f12466f17df7e97310e30f343a648baea1b9b350685dafafffdf5808",
+ "pnpm": {
+ "onlyBuiltDependencies": [
+ "esbuild"
+ ]
+ }
}
diff --git a/packages/actor/dist/client.cjs b/packages/actor/dist/client.cjs
new file mode 100644
index 000000000..b97d204bc
--- /dev/null
+++ b/packages/actor/dist/client.cjs
@@ -0,0 +1,3 @@
+"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _createStarExport(obj) { Object.keys(obj) .filter((key) => key !== "default" && key !== "__esModule") .forEach((key) => { if (exports.hasOwnProperty(key)) { return; } Object.defineProperty(exports, key, {enumerable: true, configurable: true, get: () => obj[key]}); }); }// src/client.ts
+var _client = require('@rivetkit/core/client'); _createStarExport(_client);
+//# sourceMappingURL=client.cjs.map
\ No newline at end of file
diff --git a/packages/actor/dist/client.cjs.map b/packages/actor/dist/client.cjs.map
new file mode 100644
index 000000000..e3db939c2
--- /dev/null
+++ b/packages/actor/dist/client.cjs.map
@@ -0,0 +1 @@
+{"version":3,"sources":["/Users/josi/Documents/ShiftLabs/Projects/rivetkit/packages/actor/dist/client.cjs","../src/client.ts"],"names":[],"mappings":"AAAA;ACAA,2EAAc","file":"/Users/josi/Documents/ShiftLabs/Projects/rivetkit/packages/actor/dist/client.cjs","sourcesContent":[null,"export * from \"@rivetkit/core/client\";\n"]}
\ No newline at end of file
diff --git a/packages/actor/dist/client.d.cts b/packages/actor/dist/client.d.cts
new file mode 100644
index 000000000..d1b593b7b
--- /dev/null
+++ b/packages/actor/dist/client.d.cts
@@ -0,0 +1,5 @@
+export * from '@rivetkit/core/client';
+import '@rivetkit/core/errors';
+import '@rivetkit/core/log';
+import '@rivetkit/core';
+import '@rivetkit/core/test';
diff --git a/packages/actor/dist/client.d.ts b/packages/actor/dist/client.d.ts
new file mode 100644
index 000000000..7657d1596
--- /dev/null
+++ b/packages/actor/dist/client.d.ts
@@ -0,0 +1,5 @@
+export * from "@rivetkit/core/client";
+import "@rivetkit/core/errors";
+import "@rivetkit/core/log";
+import "@rivetkit/core";
+import "@rivetkit/core/test";
diff --git a/packages/actor/dist/client.js b/packages/actor/dist/client.js
new file mode 100644
index 000000000..95f65ea7c
--- /dev/null
+++ b/packages/actor/dist/client.js
@@ -0,0 +1,3 @@
+// src/client.ts
+export * from "@rivetkit/core/client";
+//# sourceMappingURL=client.js.map
diff --git a/packages/actor/dist/client.js.map b/packages/actor/dist/client.js.map
new file mode 100644
index 000000000..09d2cd2c5
--- /dev/null
+++ b/packages/actor/dist/client.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/client.ts"],"sourcesContent":["export * from \"@rivetkit/core/client\";\n"],"mappings":";AAAA,cAAc;","names":[]}
\ No newline at end of file
diff --git a/packages/actor/dist/errors.cjs b/packages/actor/dist/errors.cjs
new file mode 100644
index 000000000..970bd23a1
--- /dev/null
+++ b/packages/actor/dist/errors.cjs
@@ -0,0 +1,3 @@
+"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _createStarExport(obj) { Object.keys(obj) .filter((key) => key !== "default" && key !== "__esModule") .forEach((key) => { if (exports.hasOwnProperty(key)) { return; } Object.defineProperty(exports, key, {enumerable: true, configurable: true, get: () => obj[key]}); }); }// src/errors.ts
+var _errors = require('@rivetkit/core/errors'); _createStarExport(_errors);
+//# sourceMappingURL=errors.cjs.map
\ No newline at end of file
diff --git a/packages/actor/dist/errors.cjs.map b/packages/actor/dist/errors.cjs.map
new file mode 100644
index 000000000..3669f0751
--- /dev/null
+++ b/packages/actor/dist/errors.cjs.map
@@ -0,0 +1 @@
+{"version":3,"sources":["/Users/josi/Documents/ShiftLabs/Projects/rivetkit/packages/actor/dist/errors.cjs","../src/errors.ts"],"names":[],"mappings":"AAAA;ACAA,2EAAc","file":"/Users/josi/Documents/ShiftLabs/Projects/rivetkit/packages/actor/dist/errors.cjs","sourcesContent":[null,"export * from \"@rivetkit/core/errors\";\n"]}
\ No newline at end of file
diff --git a/packages/actor/dist/errors.d.cts b/packages/actor/dist/errors.d.cts
new file mode 100644
index 000000000..162d2c1ba
--- /dev/null
+++ b/packages/actor/dist/errors.d.cts
@@ -0,0 +1 @@
+export * from '@rivetkit/core/errors';
diff --git a/packages/actor/dist/errors.d.ts b/packages/actor/dist/errors.d.ts
new file mode 100644
index 000000000..ef2b8676a
--- /dev/null
+++ b/packages/actor/dist/errors.d.ts
@@ -0,0 +1 @@
+export * from "@rivetkit/core/errors";
diff --git a/packages/actor/dist/errors.js b/packages/actor/dist/errors.js
new file mode 100644
index 000000000..f6a9f276d
--- /dev/null
+++ b/packages/actor/dist/errors.js
@@ -0,0 +1,3 @@
+// src/errors.ts
+export * from "@rivetkit/core/errors";
+//# sourceMappingURL=errors.js.map
diff --git a/packages/actor/dist/errors.js.map b/packages/actor/dist/errors.js.map
new file mode 100644
index 000000000..4d55ed9c2
--- /dev/null
+++ b/packages/actor/dist/errors.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/errors.ts"],"sourcesContent":["export * from \"@rivetkit/core/errors\";\n"],"mappings":";AAAA,cAAc;","names":[]}
\ No newline at end of file
diff --git a/packages/actor/dist/log.cjs b/packages/actor/dist/log.cjs
new file mode 100644
index 000000000..8dd16117a
--- /dev/null
+++ b/packages/actor/dist/log.cjs
@@ -0,0 +1,3 @@
+"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _createStarExport(obj) { Object.keys(obj) .filter((key) => key !== "default" && key !== "__esModule") .forEach((key) => { if (exports.hasOwnProperty(key)) { return; } Object.defineProperty(exports, key, {enumerable: true, configurable: true, get: () => obj[key]}); }); }// src/log.ts
+var _log = require('@rivetkit/core/log'); _createStarExport(_log);
+//# sourceMappingURL=log.cjs.map
\ No newline at end of file
diff --git a/packages/actor/dist/log.cjs.map b/packages/actor/dist/log.cjs.map
new file mode 100644
index 000000000..d25b8b262
--- /dev/null
+++ b/packages/actor/dist/log.cjs.map
@@ -0,0 +1 @@
+{"version":3,"sources":["/Users/josi/Documents/ShiftLabs/Projects/rivetkit/packages/actor/dist/log.cjs","../src/log.ts"],"names":[],"mappings":"AAAA;ACAA,kEAAc","file":"/Users/josi/Documents/ShiftLabs/Projects/rivetkit/packages/actor/dist/log.cjs","sourcesContent":[null,"export * from \"@rivetkit/core/log\";\n"]}
\ No newline at end of file
diff --git a/packages/actor/dist/log.d.cts b/packages/actor/dist/log.d.cts
new file mode 100644
index 000000000..ac3f460ea
--- /dev/null
+++ b/packages/actor/dist/log.d.cts
@@ -0,0 +1 @@
+export * from '@rivetkit/core/log';
diff --git a/packages/actor/dist/log.d.ts b/packages/actor/dist/log.d.ts
new file mode 100644
index 000000000..dd1ff77fe
--- /dev/null
+++ b/packages/actor/dist/log.d.ts
@@ -0,0 +1 @@
+export * from "@rivetkit/core/log";
diff --git a/packages/actor/dist/log.js b/packages/actor/dist/log.js
new file mode 100644
index 000000000..96ecf2866
--- /dev/null
+++ b/packages/actor/dist/log.js
@@ -0,0 +1,3 @@
+// src/log.ts
+export * from "@rivetkit/core/log";
+//# sourceMappingURL=log.js.map
diff --git a/packages/actor/dist/log.js.map b/packages/actor/dist/log.js.map
new file mode 100644
index 000000000..00e32eacf
--- /dev/null
+++ b/packages/actor/dist/log.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/log.ts"],"sourcesContent":["export * from \"@rivetkit/core/log\";\n"],"mappings":";AAAA,cAAc;","names":[]}
\ No newline at end of file
diff --git a/packages/actor/dist/mod.cjs b/packages/actor/dist/mod.cjs
new file mode 100644
index 000000000..e32fe24db
--- /dev/null
+++ b/packages/actor/dist/mod.cjs
@@ -0,0 +1,3 @@
+"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _createStarExport(obj) { Object.keys(obj) .filter((key) => key !== "default" && key !== "__esModule") .forEach((key) => { if (exports.hasOwnProperty(key)) { return; } Object.defineProperty(exports, key, {enumerable: true, configurable: true, get: () => obj[key]}); }); }// src/mod.ts
+var _core = require('@rivetkit/core'); _createStarExport(_core);
+//# sourceMappingURL=mod.cjs.map
\ No newline at end of file
diff --git a/packages/actor/dist/mod.cjs.map b/packages/actor/dist/mod.cjs.map
new file mode 100644
index 000000000..cf0966536
--- /dev/null
+++ b/packages/actor/dist/mod.cjs.map
@@ -0,0 +1 @@
+{"version":3,"sources":["/Users/josi/Documents/ShiftLabs/Projects/rivetkit/packages/actor/dist/mod.cjs","../src/mod.ts"],"names":[],"mappings":"AAAA;ACAA,gEAAc","file":"/Users/josi/Documents/ShiftLabs/Projects/rivetkit/packages/actor/dist/mod.cjs","sourcesContent":[null,"export * from \"@rivetkit/core\";\n"]}
\ No newline at end of file
diff --git a/packages/actor/dist/mod.d.cts b/packages/actor/dist/mod.d.cts
new file mode 100644
index 000000000..4a4a25ff6
--- /dev/null
+++ b/packages/actor/dist/mod.d.cts
@@ -0,0 +1 @@
+export * from '@rivetkit/core';
diff --git a/packages/actor/dist/mod.d.ts b/packages/actor/dist/mod.d.ts
new file mode 100644
index 000000000..d00787ee2
--- /dev/null
+++ b/packages/actor/dist/mod.d.ts
@@ -0,0 +1 @@
+export * from "@rivetkit/core";
diff --git a/packages/actor/dist/mod.js b/packages/actor/dist/mod.js
new file mode 100644
index 000000000..0a2ea159c
--- /dev/null
+++ b/packages/actor/dist/mod.js
@@ -0,0 +1,3 @@
+// src/mod.ts
+export * from "@rivetkit/core";
+//# sourceMappingURL=mod.js.map
diff --git a/packages/actor/dist/mod.js.map b/packages/actor/dist/mod.js.map
new file mode 100644
index 000000000..7f62cc3d3
--- /dev/null
+++ b/packages/actor/dist/mod.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/mod.ts"],"sourcesContent":["export * from \"@rivetkit/core\";\n"],"mappings":";AAAA,cAAc;","names":[]}
\ No newline at end of file
diff --git a/packages/actor/dist/test.cjs b/packages/actor/dist/test.cjs
new file mode 100644
index 000000000..22c09e7c5
--- /dev/null
+++ b/packages/actor/dist/test.cjs
@@ -0,0 +1,3 @@
+"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _createStarExport(obj) { Object.keys(obj) .filter((key) => key !== "default" && key !== "__esModule") .forEach((key) => { if (exports.hasOwnProperty(key)) { return; } Object.defineProperty(exports, key, {enumerable: true, configurable: true, get: () => obj[key]}); }); }// src/test.ts
+var _test = require('@rivetkit/core/test'); _createStarExport(_test);
+//# sourceMappingURL=test.cjs.map
\ No newline at end of file
diff --git a/packages/actor/dist/test.cjs.map b/packages/actor/dist/test.cjs.map
new file mode 100644
index 000000000..8b1139df2
--- /dev/null
+++ b/packages/actor/dist/test.cjs.map
@@ -0,0 +1 @@
+{"version":3,"sources":["/Users/josi/Documents/ShiftLabs/Projects/rivetkit/packages/actor/dist/test.cjs","../src/test.ts"],"names":[],"mappings":"AAAA;ACAA,qEAAc","file":"/Users/josi/Documents/ShiftLabs/Projects/rivetkit/packages/actor/dist/test.cjs","sourcesContent":[null,"export * from \"@rivetkit/core/test\";\n"]}
\ No newline at end of file
diff --git a/packages/actor/dist/test.d.cts b/packages/actor/dist/test.d.cts
new file mode 100644
index 000000000..7b539cbee
--- /dev/null
+++ b/packages/actor/dist/test.d.cts
@@ -0,0 +1 @@
+export * from '@rivetkit/core/test';
diff --git a/packages/actor/dist/test.d.ts b/packages/actor/dist/test.d.ts
new file mode 100644
index 000000000..1356b6872
--- /dev/null
+++ b/packages/actor/dist/test.d.ts
@@ -0,0 +1 @@
+export * from "@rivetkit/core/test";
diff --git a/packages/actor/dist/test.js b/packages/actor/dist/test.js
new file mode 100644
index 000000000..111c48292
--- /dev/null
+++ b/packages/actor/dist/test.js
@@ -0,0 +1,3 @@
+// src/test.ts
+export * from "@rivetkit/core/test";
+//# sourceMappingURL=test.js.map
diff --git a/packages/actor/dist/test.js.map b/packages/actor/dist/test.js.map
new file mode 100644
index 000000000..de6a64cdb
--- /dev/null
+++ b/packages/actor/dist/test.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/test.ts"],"sourcesContent":["export * from \"@rivetkit/core/test\";\n"],"mappings":";AAAA,cAAc;","names":[]}
\ No newline at end of file
diff --git a/packages/frameworks/svelte/.gitignore b/packages/frameworks/svelte/.gitignore
new file mode 100644
index 000000000..294b38578
--- /dev/null
+++ b/packages/frameworks/svelte/.gitignore
@@ -0,0 +1,24 @@
+node_modules
+
+# Output
+.output
+.vercel
+.netlify
+.wrangler
+/.svelte-kit
+/build
+/dist
+
+# OS
+.DS_Store
+Thumbs.db
+
+# Env
+.env
+.env.*
+!.env.example
+!.env.test
+
+# Vite
+vite.config.js.timestamp-*
+vite.config.ts.timestamp-*
diff --git a/packages/frameworks/svelte/.npmrc b/packages/frameworks/svelte/.npmrc
new file mode 100644
index 000000000..b6f27f135
--- /dev/null
+++ b/packages/frameworks/svelte/.npmrc
@@ -0,0 +1 @@
+engine-strict=true
diff --git a/packages/frameworks/svelte/README.md b/packages/frameworks/svelte/README.md
new file mode 100644
index 000000000..db0de8214
--- /dev/null
+++ b/packages/frameworks/svelte/README.md
@@ -0,0 +1,342 @@
+# RivetKit Svelte
+
+A Svelte 5 integration for [RivetKit](https://rivetkit.com) that provides reactive actor connections using Svelte's new runes system.
+
+## Installation
+
+```sh
+pnpm add @rivetkit/svelte
+
+# or
+
+npm i @rivetkit/svelte
+```
+
+## Overview
+
+RivetKit Svelte provides seamless integration between RivetKit's actor system and Svelte 5's reactive runes. It allows you to connect to RivetKit actors from your Svelte components with automatic reactivity, real-time event handling, and type safety.
+
+## Features
+
+- **Svelte 5 Runes Integration** - Built specifically for Svelte 5's new reactivity system
+- **Real-time Actor Connections** - Connect to RivetKit actors with automatic state synchronization
+- **Event Handling** - Listen to actor events with automatic cleanup
+- **Type Safety** - Full TypeScript support with proper type inference
+- **SSR Compatible** - Works with SvelteKit's server-side rendering
+- **Automatic Reconnection** - Handles connection states and errors gracefully
+
+## Quick Start
+
+### Step 1: Set Up Your RivetKit Backend
+
+First, create your RivetKit actors and registry. Here's a simple counter example:
+
+```typescript
+// backend/registry.ts
+import { actor, setup } from "@rivetkit/actor";
+
+export const counter = actor({
+ onAuth: () => {
+ // Configure auth here if needed
+ },
+ state: { count: 0 },
+ actions: {
+ increment: (c, x: number) => {
+ console.log("incrementing by", x);
+ c.state.count += x;
+ c.broadcast("newCount", c.state.count);
+ return c.state.count;
+ },
+ reset: (c) => {
+ c.state.count = 0;
+ c.broadcast("newCount", c.state.count);
+ return c.state.count;
+ },
+ },
+});
+
+export const registry = setup({
+ use: { counter },
+});
+```
+
+### Step 2: Start Your RivetKit Server
+
+```typescript
+// backend/index.ts
+import { registry } from "./registry";
+
+export type Registry = typeof registry;
+
+registry.runServer({
+ cors: {
+ origin: "http://localhost:5173", // Your Svelte app URL
+ },
+});
+```
+
+### Step 3: Create the Client Connection
+
+In your Svelte app, create a client connection to your RivetKit server:
+
+```typescript
+// src/lib/actor-client.ts
+import { createClient, createRivetKit } from "@rivetkit/svelte";
+import type { Registry } from "../../backend";
+
+const client = createClient(`http://localhost:8080`);
+export const { useActor } = createRivetKit(client);
+```
+
+### Step 4: Use Actors in Your Svelte Components
+
+Now you can use the `useActor` function in your Svelte 5 components:
+
+```svelte
+
+
+
+
+
Counter: {count}
+
+
+
+```
+
+## Core Concepts
+
+### useActor Hook
+
+The `useActor` function is the main way to connect to RivetKit actors from your Svelte components. It returns a reactive object with the following properties:
+
+- **`connection`** - The actor connection object for calling actions
+- **`handle`** - The actor handle for advanced operations
+- **`isConnected`** - Boolean indicating if the actor is connected
+- **`isConnecting`** - Boolean indicating if the actor is currently connecting
+- **`isError`** - Boolean indicating if there's an error
+- **`error`** - The error object if one exists
+- **`useEvent`** - Function to listen for actor events
+
+### Actor Options
+
+When calling `useActor`, you need to provide:
+
+```typescript
+const actor = useActor({
+ name: 'counter', // The actor name from your registry
+ key: ['test-counter'], // Unique key for this actor instance
+ params: { /* ... */ }, // Optional parameters
+ enabled: true // Optional, defaults to true
+});
+```
+
+## Event Handling
+
+### Using useEvent
+
+The `useEvent` function allows you to listen for events broadcast by actors:
+
+```svelte
+
+```
+
+### Alternative Event Listening
+
+You can also listen to events directly on the connection:
+
+```svelte
+
+```
+
+## Advanced Usage
+
+### Conditional Actor Connections
+
+You can conditionally enable/disable actor connections:
+
+```svelte
+
+```
+
+### Multiple Actor Instances
+
+You can connect to multiple instances of the same actor:
+
+```svelte
+
+```
+
+### Error Handling
+
+Handle connection errors gracefully:
+
+```svelte
+
+
+{#if actor?.isError}
+
+ Connection failed: {actor.error?.message}
+
+{:else if actor?.isConnecting}
+
Connecting...
+{:else if actor?.isConnected}
+
Connected!
+{/if}
+```
+
+## API Reference
+
+### createClient(url: string)
+
+Creates a client connection to your RivetKit server.
+
+```typescript
+import { createClient } from "@rivetkit/svelte";
+
+const client = createClient("http://localhost:8080");
+```
+
+### createRivetKit(client: Client)
+
+Creates the RivetKit integration with your client.
+
+```typescript
+import { createRivetKit } from "@rivetkit/svelte";
+
+const { useActor } = createRivetKit(client);
+```
+
+### useActor(options: ActorOptions)
+
+Connects to a RivetKit actor and returns reactive state.
+
+**Parameters:**
+- `name: string` - The actor name from your registry
+- `key: string | string[]` - Unique identifier for the actor instance
+- `params?: Record` - Optional parameters to pass to the actor
+- `enabled?: boolean` - Whether the connection is enabled (default: true)
+
+**Returns:**
+- `connection` - Actor connection for calling actions
+- `handle` - Actor handle for advanced operations
+- `isConnected` - Connection status
+- `isConnecting` - Loading state
+- `isError` - Error state
+- `error` - Error object
+- `useEvent` - Function to listen for events
+
+## TypeScript Support
+
+RivetKit Svelte provides full TypeScript support. Make sure to type your registry:
+
+```typescript
+// backend/index.ts
+export type Registry = typeof registry;
+
+// frontend/actor-client.ts
+import type { Registry } from "../../backend";
+const client = createClient("http://localhost:8080");
+```
+
+## SvelteKit Integration
+
+RivetKit Svelte works seamlessly with SvelteKit. The library automatically detects browser environment and handles SSR appropriately.
+
+```svelte
+
+
+```
+
+## Examples
+
+Check out the `examples` folder in this repository for a complete working example with:
+- Backend RivetKit server setup
+- Frontend Svelte integration
+- Real-time counter with events
+- TypeScript configuration
+
+## Contributing
+
+Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.
+
+## License
+
+MIT License - see LICENSE file for details.
diff --git a/packages/frameworks/svelte/package.json b/packages/frameworks/svelte/package.json
new file mode 100644
index 000000000..a11e15420
--- /dev/null
+++ b/packages/frameworks/svelte/package.json
@@ -0,0 +1,53 @@
+{
+ "name": "@rivetkit/svelte",
+ "version": "0.9.9",
+ "license": "Apache-2.0",
+ "keywords": [
+ "rivetkit",
+ "svelte",
+ "framework",
+ "actors",
+ "stateful",
+ "serverless"
+ ],
+ "sideEffects": false,
+ "type": "module",
+ "files": [
+ "dist",
+ "package.json"
+ ],
+ "exports": {
+ ".": {
+ "import": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ },
+ "require": {
+ "types": "./dist/index.d.cts",
+ "default": "./dist/index.cjs"
+ }
+ }
+ },
+ "scripts": {
+ "dev": "vite build --watch",
+ "build": "tsc && vite build",
+ "check-types": "tsc --noEmit",
+ "check": "tsc --noEmit"
+ },
+ "peerDependencies": {
+ "@rivetkit/core": "*",
+ "svelte": "^5.0.0"
+ },
+ "dependencies": {
+ "@rivetkit/framework-base": "workspace:*",
+ "esm-env": "^1.2.1"
+ },
+ "devDependencies": {
+ "@rivetkit/core": "workspace:*",
+ "svelte": "^5.0.0",
+ "typescript": "^5.5.2",
+ "vite": "^6.3.5",
+ "vite-plugin-dts": "^4.5.4"
+ },
+ "stableVersion": "0.8.0"
+}
diff --git a/packages/frameworks/svelte/src/app.d.ts b/packages/frameworks/svelte/src/app.d.ts
new file mode 100644
index 000000000..da08e6da5
--- /dev/null
+++ b/packages/frameworks/svelte/src/app.d.ts
@@ -0,0 +1,13 @@
+// See https://svelte.dev/docs/kit/types#app.d.ts
+// for information about these interfaces
+declare global {
+ namespace App {
+ // interface Error {}
+ // interface Locals {}
+ // interface PageData {}
+ // interface PageState {}
+ // interface Platform {}
+ }
+}
+
+export {};
diff --git a/packages/frameworks/svelte/src/app.html b/packages/frameworks/svelte/src/app.html
new file mode 100644
index 000000000..ed39a5af8
--- /dev/null
+++ b/packages/frameworks/svelte/src/app.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ %sveltekit.head%
+
+
+
%sveltekit.body%
+
+
diff --git a/packages/frameworks/svelte/src/index.ts b/packages/frameworks/svelte/src/index.ts
new file mode 100644
index 000000000..d2a27dea3
--- /dev/null
+++ b/packages/frameworks/svelte/src/index.ts
@@ -0,0 +1 @@
+export * from "./rivet.svelte.js";
diff --git a/packages/frameworks/svelte/src/lib/index.ts b/packages/frameworks/svelte/src/lib/index.ts
new file mode 100644
index 000000000..d2a27dea3
--- /dev/null
+++ b/packages/frameworks/svelte/src/lib/index.ts
@@ -0,0 +1 @@
+export * from "./rivet.svelte.js";
diff --git a/packages/frameworks/svelte/src/lib/rivet.svelte.ts b/packages/frameworks/svelte/src/lib/rivet.svelte.ts
new file mode 100644
index 000000000..21ab40e12
--- /dev/null
+++ b/packages/frameworks/svelte/src/lib/rivet.svelte.ts
@@ -0,0 +1,190 @@
+import type {
+ ActorConn,
+ ActorHandle,
+ AnyActorDefinition,
+ Client,
+ ExtractActorsFromRegistry,
+} from "@rivetkit/core/client";
+import {
+ type ActorOptions,
+ type AnyActorRegistry,
+ type CreateRivetKitOptions,
+ createRivetKit as createVanillaRivetKit,
+} from "@rivetkit/framework-base";
+import { useStore } from "@tanstack/svelte-store";
+
+export interface ActorStateReference {
+ /**
+ * The unique identifier for the actor.
+ * This is a hash generated from the actor's options.
+ * It is used to identify the actor instance in the store.
+ * @internal
+ */
+ hash: string;
+ /**
+ * The state of the actor, derived from the store.
+ * This includes the actor's connection and handle.
+ */
+ handle: ActorHandle | null;
+ /**
+ * The connection to the actor.
+ * This is used to communicate with the actor in realtime.
+ */
+ connection: ActorConn | null;
+ /**
+ * Whether the actor is enabled.
+ */
+ isConnected?: boolean;
+ /**
+ * Whether the actor is currently connecting, indicating that a connection attempt is in progress.
+ */
+ isConnecting?: boolean;
+ /**
+ * Whether there was an error connecting to the actor.
+ */
+ isError?: boolean;
+ /**
+ * The error that occurred while trying to connect to the actor, if any.
+ */
+ error: Error | null;
+ /**
+ * Options for the actor, including its name, key, parameters, and whether it is enabled.
+ */
+ opts: {
+ name: keyof AD;
+ /**
+ * Unique key for the actor instance.
+ * This can be a string or an array of strings to create multiple instances.
+ * @example "abc" or ["abc", "def"]
+ */
+ key: string | string[];
+ /**
+ * Parameters for the actor.
+ * These are additional options that can be passed to the actor.
+ */
+ params?: Record;
+ /** Region to create the actor in if it doesn't exist. */
+ createInRegion?: string;
+ /** Input data to pass to the actor. */
+ createWithInput?: unknown;
+ /**
+ * Whether the actor is enabled.
+ * Defaults to true.
+ */
+ enabled?: boolean;
+ };
+}
+
+export { createClient } from "@rivetkit/core/client";
+
+export function createRivetKit(
+ client: Client,
+ opts: CreateRivetKitOptions = {},
+) {
+ const { getOrCreateActor } = createVanillaRivetKit<
+ Registry,
+ ExtractActorsFromRegistry,
+ keyof ExtractActorsFromRegistry
+ >(client, opts);
+
+ /**
+ * Svelte 5 rune-based function to connect to an actor and retrieve its state.
+ * Using this function with the same options will return the same actor instance.
+ * This simplifies passing around the actor state in your components.
+ * It also provides a method to listen for events emitted by the actor.
+ * @param opts - Options for the actor, including its name, key, and parameters.
+ * @returns An object containing reactive state and event listener function.
+ */
+ function useActor<
+ ActorName extends keyof ExtractActorsFromRegistry,
+ >(
+ opts: ActorOptions,
+ ): {
+ current: Omit<
+ ActorStateReference>,
+ "handle" | "connection"
+ > & {
+ handle: ActorHandle<
+ ExtractActorsFromRegistry[ActorName]
+ > | null;
+ connection: ActorConn<
+ ExtractActorsFromRegistry[ActorName]
+ > | null;
+ };
+ useEvent: (eventName: string, handler: (...args: any[]) => void) => void;
+ } {
+ const { mount, setState, state } = getOrCreateActor(opts);
+
+ // Update options reactively
+ $effect.root(() => {
+ setState((prev) => {
+ prev.opts = {
+ ...opts,
+ enabled: opts.enabled ?? true,
+ } as any;
+ return prev;
+ });
+ });
+
+ // Mount and subscribe to state changes
+ $effect.root(() => {
+ mount();
+ });
+ const actorState = useStore(state);
+
+ function useEvent(
+ eventName: string,
+ // biome-ignore lint/suspicious/noExplicitAny: strong typing of handler is not supported yet
+ handler: (...args: any[]) => void,
+ ) {
+ let ref = $state(handler);
+ const actorState = useStore(state) || {};
+
+ $effect(() => {
+ ref = handler;
+ });
+ $effect(() => {
+ if (!actorState?.current?.connection) return;
+ function eventHandler(...args: any[]) {
+ ref(...args);
+ }
+ return actorState.current.connection.on(eventName, eventHandler);
+ });
+ }
+
+ const current = {
+ get connection() {
+ return actorState.current?.connection;
+ },
+ get handle() {
+ return actorState.current?.handle;
+ },
+ get isConnected() {
+ return actorState.current?.isConnected;
+ },
+ get isConnecting() {
+ return actorState.current?.isConnecting;
+ },
+ get isError() {
+ return actorState.current?.isError;
+ },
+ get error() {
+ return actorState.current?.error;
+ },
+ get opts() {
+ return actorState.current?.opts;
+ },
+ get hash() {
+ return actorState.current?.hash;
+ },
+ };
+ return {
+ current,
+ useEvent,
+ };
+ }
+
+ return {
+ useActor,
+ };
+}
diff --git a/packages/frameworks/svelte/src/rivet.svelte.ts b/packages/frameworks/svelte/src/rivet.svelte.ts
new file mode 100644
index 000000000..8c466f6ac
--- /dev/null
+++ b/packages/frameworks/svelte/src/rivet.svelte.ts
@@ -0,0 +1,154 @@
+import type { Client, ExtractActorsFromRegistry } from "@rivetkit/core/client";
+import {
+ type ActorOptions,
+ type AnyActorRegistry,
+ type CreateRivetKitOptions,
+ createRivetKit as createVanillaRivetKit,
+} from "@rivetkit/framework-base";
+import { BROWSER } from "esm-env";
+
+export { createClient } from "@rivetkit/core/client";
+
+export function createRivetKit(
+ client: Client,
+ opts: CreateRivetKitOptions = {},
+) {
+ const { getOrCreateActor } = createVanillaRivetKit<
+ Registry,
+ ExtractActorsFromRegistry,
+ keyof ExtractActorsFromRegistry
+ >(client, opts);
+
+ /**
+ * Svelte 5 rune-based function to connect to an actor and retrieve its state.
+ * Using this function with the same options will return the same actor instance.
+ * This simplifies passing around the actor state in your components.
+ * It also provides a method to listen for events emitted by the actor.
+ * @param opts - Options for the actor, including its name, key, and parameters.
+ * @returns An object containing reactive state and event listener function.
+ */
+ function useActor<
+ ActorName extends keyof ExtractActorsFromRegistry,
+ >(opts: ActorOptions) {
+ const { mount, setState, state } = getOrCreateActor(opts);
+
+ // Create reactive state using Svelte 5 runes with proper typing
+ type ActorConnection =
+ ExtractActorsFromRegistry[ActorName] extends {
+ connection: infer C;
+ }
+ ? C
+ : any;
+ type ActorHandle = ExtractActorsFromRegistry[ActorName] extends {
+ handle: infer H;
+ }
+ ? H
+ : any;
+
+ let connection = $state(null);
+ let handle = $state(null);
+ let isConnected = $state(false);
+ let isConnecting = $state(false);
+ let actorOpts = $state<{
+ name: keyof ExtractActorsFromRegistry;
+ key: string | string[];
+ params?: Record;
+ enabled?: boolean;
+ }>({} as any);
+ let isError = $state(undefined);
+ let error = $state(null);
+ let hash = $state("");
+
+ // Only run in browser to avoid SSR issues
+ if (BROWSER) {
+ // Subscribe to state changes from the base framework
+ state.subscribe((newData) => {
+ connection = newData.currentVal.connection;
+ handle = newData.currentVal.handle;
+ isConnected = newData.currentVal.isConnected;
+ isConnecting = newData.currentVal.isConnecting;
+ actorOpts = newData.currentVal.opts;
+ isError = newData.currentVal.isError;
+ error = newData.currentVal.error;
+ hash = newData.currentVal.hash;
+ });
+
+ // Update options reactively
+ $effect.root(() => {
+ setState((prev) => {
+ prev.opts = {
+ ...opts,
+ enabled: opts.enabled ?? true,
+ };
+ return prev;
+ });
+ });
+
+ // Mount and subscribe to state changes
+ $effect.root(() => {
+ mount();
+ });
+ }
+
+ /**
+ * Function to listen for events emitted by the actor.
+ * This function allows you to subscribe to specific events emitted by the actor
+ * and execute a handler function when the event occurs.
+ * It automatically manages the event listener lifecycle.
+ * @param eventName The name of the event to listen for.
+ * @param handler The function to call when the event is emitted.
+ */
+ function useEvent(
+ eventName: string,
+ // biome-ignore lint/suspicious/noExplicitAny: strong typing of handler is not supported yet
+ handler: (...args: any[]) => void,
+ ) {
+ // Get the current connection reactively
+ const connection = $derived(state.state.connection);
+ let connSubs: (() => void) | undefined;
+
+ $effect.root(() => {
+ // Set up event listener if connection exists
+ connSubs = connection?.on(eventName, handler);
+
+ // Cleanup function
+ return () => {
+ connSubs?.();
+ };
+ });
+ }
+
+ // Return reactive state with proper typing
+ return {
+ get connection(): ActorConnection | null {
+ return connection;
+ },
+ get handle(): ActorHandle | null {
+ return handle;
+ },
+ get isConnected() {
+ return isConnected;
+ },
+ get isConnecting() {
+ return isConnecting;
+ },
+ get actorOpts() {
+ return actorOpts;
+ },
+ get isError() {
+ return isError;
+ },
+ get error() {
+ return error;
+ },
+ get hash() {
+ return hash;
+ },
+ useEvent,
+ };
+ }
+
+ return {
+ useActor,
+ };
+}
diff --git a/packages/frameworks/svelte/src/routes/+page.svelte b/packages/frameworks/svelte/src/routes/+page.svelte
new file mode 100644
index 000000000..ac6f1db25
--- /dev/null
+++ b/packages/frameworks/svelte/src/routes/+page.svelte
@@ -0,0 +1,4 @@
+
+
Welcome to your library project
+
Create your package using @sveltejs/package and preview/showcase your work with SvelteKit