Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
39c6294
add workbench sveltekit
adriandlam Oct 29, 2025
8955e2b
add sveltekit package
adriandlam Oct 29, 2025
4b6a19a
fix: use js for generated server routes in svelte
adriandlam Oct 29, 2025
dfa6f6e
add test routes for sveltekit workbench
adriandlam Oct 29, 2025
2ae3503
updates from debugging
ijjk Oct 29, 2025
252339f
feat: add sveltekit build target
adriandlam Oct 30, 2025
09e49db
update user sign up workflow workbench sveltekit
adriandlam Oct 30, 2025
91fb404
fix: base builder missing GET route handler for sveltekit
adriandlam Oct 30, 2025
9502bf5
feat: add vercel builder and check for vercel env
adriandlam Oct 30, 2025
a52d521
refactor: workflowPlugin for sveltekit
adriandlam Oct 30, 2025
38d5410
ci: add tests to workbench sveltekit
adriandlam Oct 30, 2025
004e042
fix: no start command and vercel builder outputs
adriandlam Oct 30, 2025
f7b9115
fix: base builder conditions
adriandlam Oct 30, 2025
7b0268b
.
adriandlam Oct 30, 2025
f62bbdb
add auto adapter sveltekit
adriandlam Oct 30, 2025
86e59fc
fix: disable checking origin for cross site ci stuff
adriandlam Oct 30, 2025
eff0730
allow all trusted origins in svelte config
adriandlam Oct 30, 2025
e500bfb
fix: add catch for error thrown when waiting for ops
adriandlam Oct 30, 2025
84d4f70
fix: sveltekit workbench adapter
adriandlam Oct 30, 2025
450a2f1
test
adriandlam Oct 30, 2025
91db702
test
adriandlam Oct 30, 2025
2a29c72
refactor: move vercel builder on config resolved
adriandlam Oct 30, 2025
881d0d6
update package json
adriandlam Oct 30, 2025
2693d7b
add demo workflow trigger
adriandlam Oct 30, 2025
9a920d0
test letting sveltekit handle route generation
adriandlam Oct 30, 2025
b91f8ed
fix: exclude git ignore for local builder outputs
adriandlam Oct 30, 2025
5a9417e
update config
ijjk Oct 30, 2025
90acfdd
add debug logs
ijjk Oct 30, 2025
c109c21
update debug
ijjk Oct 30, 2025
5eddb04
update turbo.json
ijjk Oct 30, 2025
23ef645
fix env check
ijjk Oct 30, 2025
203e03a
another output
ijjk Oct 30, 2025
518712e
use top-level await
ijjk Oct 30, 2025
971ac50
ensure vercel functions are patched
ijjk Oct 30, 2025
c2b8192
change hook
ijjk Oct 30, 2025
bac5a5e
update
ijjk Oct 30, 2025
8e63f00
fix spread
ijjk Oct 30, 2025
da1e842
debug
ijjk Oct 30, 2025
870cdb6
update
ijjk Oct 31, 2025
4b8297d
chore: remove vercel builder
adriandlam Oct 31, 2025
6577c06
chore: update comments in sveltekit workflow package
adriandlam Oct 31, 2025
52d60e3
chore: remove console comment
adriandlam Oct 31, 2025
f80dab1
refactor: workflow svelte plugin
adriandlam Oct 31, 2025
c10d87b
refactor: simplify local builder config
adriandlam Oct 31, 2025
5852ffb
chore: remove unused deps
adriandlam Oct 31, 2025
4e2749f
chore: add comment for workbench svelte app
adriandlam Oct 31, 2025
f754595
chore: add sveltekit export to workflow
adriandlam Oct 31, 2025
9b4a561
export sveltekit from workflow
adriandlam Oct 31, 2025
91597e1
lockfile
adriandlam Oct 31, 2025
741093a
chore: remove unused deps svelte workbench
adriandlam Oct 31, 2025
4751a2a
update styling
adriandlam Oct 31, 2025
fc84338
add sveltekit getting started docs
adriandlam Oct 31, 2025
50704e9
update sveltekit docs getting started
adriandlam Oct 31, 2025
724e095
changeset
adriandlam Oct 31, 2025
f005eba
Apply suggestion from @vercel[bot]
adriandlam Oct 31, 2025
cd73314
use proper env var
adriandlam Oct 31, 2025
9b838e6
Update packages/sveltekit/src/index.ts
adriandlam Oct 31, 2025
45b5cc6
Update docs/content/docs/getting-started/sveltekit.mdx
adriandlam Oct 31, 2025
3ea99d1
Document CSRF protection bypass in SvelteKit workbench config (#157)
Copilot Oct 31, 2025
1dc1439
refactor: deduplicate SvelteKit request conversion logic (#156)
Copilot Oct 31, 2025
dba3fb7
docs: fix getting staretd sveltekit missing folder
adriandlam Nov 3, 2025
96f21ef
chore: cleanup sveltekit builder after rebase
adriandlam Nov 3, 2025
c1cd6a5
lockfile
adriandlam Nov 3, 2025
e0a4e0d
fix: sveltekit building logic in base builder
adriandlam Nov 3, 2025
b91e97f
refactor: move sveltekit builder logic to its own package
adriandlam Nov 3, 2025
a9f08ae
fix: console log base builder
adriandlam Nov 4, 2025
a3aaf42
changeset
adriandlam Nov 4, 2025
1581bac
test
adriandlam Nov 4, 2025
74d367b
feat: create hmr plugin
adriandlam Nov 4, 2025
b81f1a0
fix: add initial build on load
adriandlam Nov 4, 2025
831f648
fix: check all files for workflows and steps
adriandlam Nov 4, 2025
d9523c6
add comments for plugin todo
adriandlam Nov 4, 2025
2105c0c
remove catching error
adriandlam Nov 4, 2025
79712e4
fix: missing context for nodejs envs causing waitUntil to fail
adriandlam Nov 4, 2025
3ca91e3
fix: setting global request conext in vercel environments
adriandlam Nov 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@workflow/example-nitro-v3",
"@workflow/example-nitro-v2",
"@workflow/example-nuxt",
"@workflow/example-vite"
"@workflow/example-vite",
"@workflow/example-sveltekit"
]
}
10 changes: 10 additions & 0 deletions .changeset/forty-crabs-wonder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@workflow/world-local": patch
"@workflow/sveltekit": patch
"@workflow/builders": patch
"workflow": patch
"@workflow/core": patch
"@workflow/cli": patch
---

Add sveltekit workflow integration
3 changes: 2 additions & 1 deletion .changeset/pre.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"@workflow/example-nitro-v3": "0.0.0",
"@workflow/example-nitro-v2": "0.0.0",
"@workflow/example-nuxt": "0.0.0",
"@workflow/example-vite": "0.0.0"
"@workflow/example-vite": "0.0.0",
"@workflow/example-sveltekit": "0.0.0"
},
"changesets": [
"angry-owls-beg",
Expand Down
10 changes: 9 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ jobs:
project-id: "prj_e7DZirYdLrQKXNrlxg7KmA6ABx8r"
- name: "vite"
project-id: "prj_uLIcNZNDmETulAvj5h0IcDHi5432"
- name: "sveltekit"
project-id: "prj_MqnBLm71ceXGSnm3Fs8i8gBnI23G"
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
Expand Down Expand Up @@ -172,7 +174,7 @@ jobs:
run: cd workbench/${{ matrix.app.name }} && ./resolve-symlinks.sh

- name: Run E2E Tests (Next.js)
if: matrix.app.name != 'nitro' && matrix.app.name != 'vite'
if: matrix.app.name != 'nitro' && matrix.app.name != 'vite' && matrix.app.name != 'sveltekit'
run: cd workbench/${{ matrix.app.name }} && pnpm dev & echo "starting tests in 10 seconds" && sleep 10 && pnpm vitest run packages/core/e2e/next-dev.test.ts && pnpm run test:e2e
env:
APP_NAME: ${{ matrix.app.name }}
Expand All @@ -190,6 +192,12 @@ jobs:
env:
APP_NAME: ${{ matrix.app.name }}
DEPLOYMENT_URL: "http://localhost:3000"
- name: Run E2E Tests (SvelteKit)
if: matrix.app.name == 'sveltekit'
run: cd workbench/${{ matrix.app.name }} && pnpm dev & echo "starting tests in 10 seconds" && sleep 10 && pnpm vitest run packages/core/e2e/e2e.test.ts
env:
APP_NAME: ${{ matrix.app.name }}
DEPLOYMENT_URL: "http://localhost:3000"

e2e-local-prod:
name: E2E Local Prod Tests (${{ matrix.app.name }} - ${{ matrix.app.canary && 'canary' || 'stable' }})
Expand Down
20 changes: 10 additions & 10 deletions docs/app/(home)/components/frameworks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -517,11 +517,18 @@ export const Frameworks = () => {
</Badge>
</div>

<Link href="/docs/getting-started/next">
<Next className="size-[56px]" />
<Link href="/docs/getting-started/next" className="relative">
<Next className="size-[56px] relative" />
<Next className="size-[64px] absolute top-0 opacity-15 blur-lg -z-10" />
</Link>
<Link href="/docs/getting-started/nitro">
<Link href="/docs/getting-started/nitro" className="relative">
<Nitro className="size-[56px]" />
<Nitro className="size-[64px] absolute top-0 opacity-15 blur-lg -z-10" />
</Link>

<Link href="/docs/getting-started/sveltekit" className="relative">
<SvelteKit className="size-[56px]" />
<SvelteKit className="size-[64px] absolute top-0 opacity-15 blur-lg -z-10" />
</Link>

<div className="col-span-4 w-full pt-6">
Expand All @@ -547,13 +554,6 @@ export const Frameworks = () => {
<NestGray className="size-[48px] opacity-70 transition-all duration-200 group-hover:opacity-0 group-hover:scale-95" />
<Nest className="size-[48px] absolute inset-0 opacity-0 scale-95 transition-all duration-200 group-hover:opacity-100 group-hover:scale-100" />
</div>
<div
className="group relative cursor-pointer size-[48px]"
onClick={() => handleRequest('SvelteKit')}
>
<SvelteKitGray className="size-[48px] opacity-70 transition-all duration-200 group-hover:opacity-0 group-hover:scale-95" />
<SvelteKit className="size-[48px] absolute inset-0 opacity-0 scale-95 transition-all duration-200 group-hover:opacity-100 group-hover:scale-100" />
</div>
<div
className="group relative cursor-pointer size-[60px]"
onClick={() => handleRequest('Nuxt')}
Expand Down
2 changes: 1 addition & 1 deletion docs/app/docs/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function Card({ title, href, className, children, disabled }: CardProps) {
<a
href={href}
className={cn(
'block rounded-lg border border-border p-6 transition hover:border-primary/25 hover:bg-accent no-underline duration-200',
'block rounded-lg border border-border p-6 transition hover:border-primary/25 hover:bg-accent no-underline duration-150 ease-out',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👨‍🍳

className
)}
>
Expand Down
3 changes: 1 addition & 2 deletions docs/content/docs/getting-started/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ Start by choosing your framework. Each guide will walk you through the steps to
<Nitro className="size-16" />
<span className="font-medium">Nitro</span>
</Card>
<Card href="/docs/getting-started/sveltekit" disabled className="flex flex-col items-center justify-center text-center gap-2">
<Card href="/docs/getting-started/sveltekit" className="flex flex-col items-center justify-center text-center gap-2">
<SvelteKit className="size-16" />
<span className="font-medium">SvelteKit</span>
<Badge variant="secondary">Coming soon</Badge>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

</Card>
<Card href="/docs/getting-started/nuxt" disabled className="flex flex-col items-center justify-center text-center gap-2">
<Nuxt className="size-16" />
Expand Down
258 changes: 258 additions & 0 deletions docs/content/docs/getting-started/sveltekit.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
---
title: SvelteKit
---

# SvelteKit

This guide will walk through setting up your first workflow in a SvelteKit app. Along the way, you'll learn more about the concepts that are fundamental to using the development kit in your own projects.

---

<Steps>

<Step>
## Create Your SvelteKit Project

Start by creating a new SvelteKit project. This command will create a new directory named `my-workflow-app` with a minimal setup and setup a SvelteKit project inside it.

```bash
npx sv create my-workflow-app --template=minimal --types=ts --no-add-ons
```

Enter the newly made directory:

```bash
cd my-workflow-app
```

### Install `workflow`

<Tabs items={['npm', 'pnpm', 'yarn']}>
<Tab value="npm">
<CodeBlock>
npm i workflow
</CodeBlock>
</Tab>
<Tab value="pnpm">
<CodeBlock>
pnpm i workflow
</CodeBlock>
</Tab>
<Tab value="yarn">
<CodeBlock>
yarn add workflow
</CodeBlock>
</Tab>
</Tabs>

### Configure Vite

Add `workflowPlugin()` to your Vite config. This enables usage of the `"use workflow"` and `"use step"` directives.

```typescript title="vite.config.ts" lineNumbers
import { sveltekit } from "@sveltejs/kit/vite";
import { defineConfig } from "vite";
import { workflowPlugin } from "workflow/sveltekit"; // [!code highlight]

export default defineConfig({
plugins: [sveltekit(), workflowPlugin()], // [!code highlight]
});
```

### Update `package.json`

Update your `package.json` to include port `3000` for the development server:

```json title="package.json" lineNumbers
{
// ...
"scripts": {
"dev": "vite dev --port 3000"
// ...
},
}
```

<Accordion type="single" collapsible>
<AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
<AccordionTrigger className="text-sm">
### Setup IntelliSense for TypeScript (Optional)
</AccordionTrigger>
<AccordionContent className="[&_p]:my-2">

To enable helpful hints in your IDE, setup the workflow plugin in `tsconfig.json`:

```json title="tsconfig.json" lineNumbers
{
"compilerOptions": {
// ... rest of your TypeScript config
"plugins": [
{
"name": "workflow" // [!code highlight]
}
]
}
}
```

</AccordionContent>
</AccordionItem>
</Accordion>

</Step>

<Step>

## Create Your First Workflow

Create a new file for our first workflow:

```typescript title="workflows/user-signup.ts" lineNumbers
import { sleep } from "workflow";

export async function handleUserSignup(email: string) {
"use workflow"; // [!code highlight]

const user = await createUser(email);
await sendWelcomeEmail(user);

await sleep("5s"); // Pause for 5s - doesn't consume any resources
await sendOnboardingEmail(user);

return { userId: user.id, status: "onboarded" };
}

```

We'll fill in those functions next, but let's take a look at this code:

* We define a **workflow** function with the directive `"use workflow"`. Think of the workflow function as the _orchestrator_ of individual **steps**.
* The Workflow DevKit's `sleep` function allows us to suspend execution of the workflow without using up any resources. A sleep can be a few seconds, hours, days, or even months long.

## Create Your Workflow Steps

Let's now define those missing functions.

```typescript title="workflows/user-signup.ts" lineNumbers
import { FatalError } from "workflow"

// Our workflow function defined earlier

async function createUser(email: string) {
"use step"; // [!code highlight]

console.log(`Creating user with email: ${email}`);

// Full Node.js access - database calls, APIs, etc.
return { id: crypto.randomUUID(), email };
}

async function sendWelcomeEmail(user: { id: string; email: string; }) {
"use step"; // [!code highlight]

console.log(`Sending welcome email to user: ${user.id}`);

if (Math.random() < 0.3) {
// By default, steps will be retried for unhandled errors
throw new Error("Retryable!");
}
}

async function sendOnboardingEmail(user: { id: string; email: string}) {
"use step"; // [!code highlight]

if (!user.email.includes("@")) {
// To skip retrying, throw a FatalError instead
throw new FatalError("Invalid Email");
}

console.log(`Sending onboarding email to user: ${user.id}`);
}
```

Taking a look at this code:

* Business logic lives inside **steps**. When a step is invoked inside a **workflow**, it gets enqueued to run on a separate request while the workflow is suspended, just like `sleep`.
* If a step throws an error, like in `sendWelcomeEmail`, the step will automatically be retried until it succeeds (or hits the step's max retry count).
* Steps can throw a `FatalError` if an error is intentional and should not be retried.

<Callout>
We'll dive deeper into workflows, steps, and other ways to suspend or handle events in [Foundations](/docs/foundations).
</Callout>

</Step>

<Step>

## Create Your Route Handler

To invoke your new workflow, we'll have to add your workflow to a `POST` API route handler, `src/routes/api/signup/+server.ts` with the following code:

```typescript title="src/routes/api/signup/+server.ts"
import { start } from "workflow/api";
import { handleUserSignup } from "../../../../workflows/user-signup";
import { json, type RequestHandler } from "@sveltejs/kit";

export const POST: RequestHandler = async ({
request,
}: {
request: Request;
}) => {
const { email } = await request.json();

// Executes asynchronously and doesn't block your app
await start(handleUserSignup, [email]);

return json({ message: "User signup workflow started" });
};

```

This route handler creates a `POST` request endpoint at `/api/signup` that will trigger your workflow.

<Callout>
Workflows can be triggered from API routes or any server-side code.
</Callout>

</Step>

</Steps>

## Run in development

To start your development server, run the following command in your terminal in the SvelteKit root directory:

```bash
npm run dev
```

Once your development server is running, you can trigger your workflow by running this command in the terminal:

```bash
curl -X POST --json '{"email":"[email protected]"}' http://localhost:3000/api/signup
```

Check the SvelteKit development server logs to see your workflow execute as well as the steps that are being processed.

Additionally, you can use the [Workflow DevKit CLI or Web UI](/docs/observability) to inspect your workflow runs and steps in detail.

```bash
npx workflow inspect runs
# or add '--web' for an interactive Web based UI
```

<img src="/o11y-ui.png" alt="Workflow DevKit Web UI" />

---

## Deploying to production

Workflow DevKit apps currently work best when deployed to [Vercel](https://vercel.com/home) and needs no special configuration.

Check the [Deploying](/docs/deploying) section to learn how your workflows can be deployed elsewhere.

## Next Steps

* Learn more about the [Foundations](/docs/foundations).
* Check [Errors](/docs/errors) if you encounter issues.
* Explore the [API Reference](/docs/api-reference).
Loading