Skip to content

Commit 6a063a3

Browse files
adriandlampi0vercel[bot]
authored
docs: add vite getting started (#285)
* refactor: migrate to latest nitro v3 Signed-off-by: Pooya Parsa <pooya@pi0.io> * update workaround * fix(nitro): nitro builder using deprecated srcDir * fix: add back nitro config * fix: testing matrix dirs * fix(hono): externalize nitro workflow output dir * chore: format * fix(nitro): externalize .nitro/workflow folder * docs(hono): update getting started * update docs and workbench * improve plugin patch * test: fix hono dev config * fix: wrong api file path in hono dev config * fix(nitro): check all dirs for builder * chore: add comments * refactor: migrate to latest nitro v3 Signed-off-by: Pooya Parsa <pooya@pi0.io> * docs: update home page frameworks * update getting started stuff and add vite page * docs: update vite getting started page * Update docs/app/(home)/components/frameworks.tsx Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com> * Update docs/content/docs/getting-started/index.mdx Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com> * Apply suggestion from @adriandlam * Update docs/app/(home)/components/frameworks.tsx Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com> * lockfile * lockfile * docs: update vite getting started guide * format * format * format * reset packages/nitro/src/index.ts * docs: fix vite getting started * docs: fix vite getting started api route * revert --------- Signed-off-by: Pooya Parsa <pooya@pi0.io> Co-authored-by: Pooya Parsa <pooya@pi0.io> Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
1 parent 29892a0 commit 6a063a3

File tree

5 files changed

+454
-10
lines changed

5 files changed

+454
-10
lines changed

docs/app/(home)/components/frameworks.tsx

Lines changed: 188 additions & 5 deletions
Large diffs are not rendered by default.

docs/content/docs/getting-started/index.mdx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Getting Started
33
---
44

5-
import { Next, Nitro, SvelteKit, Nuxt, Hono, Bun } from '@/app/(home)/components/frameworks';
5+
import { Next, Nitro, SvelteKit, Nuxt, Hono, Bun, AstroDark, AstroLight, TanStack, Vite } from '@/app/(home)/components/frameworks';
66

77
# Getting Started
88

@@ -13,6 +13,10 @@ Start by choosing your framework. Each guide will walk you through the steps to
1313
<Next className="size-16" />
1414
<span className="font-medium">Next.js</span>
1515
</Card>
16+
<Card href="/docs/getting-started/vite" className="flex flex-col items-center justify-center text-center gap-2">
17+
<Vite className="size-16" />
18+
<span className="font-medium">Vite</span>
19+
</Card>
1620
<Card href="/docs/getting-started/hono" className="flex flex-col items-center justify-center text-center gap-2">
1721
<Hono className="size-16" />
1822
<span className="font-medium">Hono</span>
@@ -29,4 +33,15 @@ Start by choosing your framework. Each guide will walk you through the steps to
2933
<Nuxt className="size-16" />
3034
<span className="font-medium">Nuxt</span>
3135
</Card>
36+
<Card href="/docs/getting-started/astro" disabled className="flex flex-col items-center justify-center text-center gap-2">
37+
<AstroLight className="size-16 dark:hidden" />
38+
<AstroDark className="size-16 hidden dark:block" />
39+
<span className="font-medium">Astro</span>
40+
<Badge variant="secondary">Coming soon</Badge>
41+
</Card>
42+
<Card href="/docs/getting-started/tanstack" disabled className="flex flex-col items-center justify-center text-center gap-2">
43+
<TanStack className="size-16 invert" />
44+
<span className="font-medium">TanStack Start</span>
45+
<Badge variant="secondary">Coming soon</Badge>
46+
</Card>
3247
</Cards>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"title": "Getting Started",
3-
"pages": ["next", "..."],
3+
"pages": ["next", "vite", "..."],
44
"defaultOpen": true
55
}
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
---
2+
title: Vite
3+
---
4+
5+
# Vite
6+
7+
This guide will walk through setting up your first workflow in a Vite app. Along the way, you'll learn more about the concepts that are fundamental to using the development kit in your own projects.
8+
9+
---
10+
11+
<Steps>
12+
13+
<Step>
14+
## Create Your Vite Project
15+
16+
Start by creating a new Vite project. This command will create a new directory named `my-workflow-app` with a minimal setup and setup a Vite project inside it.
17+
18+
```bash
19+
npm create vite@latest my-workflow-app -- --template react-ts
20+
```
21+
22+
Enter the newly made directory:
23+
24+
```bash
25+
cd my-workflow-app
26+
```
27+
28+
### Install `workflow` and `nitro`
29+
30+
<Tabs items={['npm', 'pnpm', 'yarn']}>
31+
<Tab value="npm">
32+
<CodeBlock>
33+
npm i workflow nitro
34+
</CodeBlock>
35+
</Tab>
36+
<Tab value="pnpm">
37+
<CodeBlock>
38+
pnpm i workflow nitro
39+
</CodeBlock>
40+
</Tab>
41+
<Tab value="yarn">
42+
<CodeBlock>
43+
yarn add workflow nitro
44+
</CodeBlock>
45+
</Tab>
46+
</Tabs>
47+
48+
<Callout>
49+
While Vite provides the build tooling and development server, Nitro adds the server framework needed for API routes and deployment. Together they enable building full-stack applications with workflow support. Learn more about Nitro [here](https://v3.nitro.build).
50+
</Callout>
51+
52+
### Configure Vite
53+
54+
Add `workflow()` to your Vite config. This enables usage of the `"use workflow"` and `"use step"` directives.
55+
56+
```typescript title="vite.config.ts" lineNumbers
57+
import { nitro } from 'nitro/vite';
58+
import { defineConfig } from 'vite';
59+
import { workflow } from 'workflow/vite';
60+
61+
export default defineConfig({
62+
plugins: [nitro(), workflow()], // [!code highlight]
63+
nitro: { // [!code highlight]
64+
serverDir: './', // [!code highlight]
65+
}, // [!code highlight]
66+
});
67+
```
68+
69+
<Accordion type="single" collapsible>
70+
<AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
71+
<AccordionTrigger className="text-sm">
72+
### Setup IntelliSense for TypeScript (Optional)
73+
</AccordionTrigger>
74+
<AccordionContent className="[&_p]:my-2">
75+
76+
To enable helpful hints in your IDE, setup the workflow plugin in `tsconfig.json`:
77+
78+
```json title="tsconfig.json" lineNumbers
79+
{
80+
"compilerOptions": {
81+
// ... rest of your TypeScript config
82+
"plugins": [
83+
{
84+
"name": "workflow" // [!code highlight]
85+
}
86+
]
87+
}
88+
}
89+
```
90+
91+
</AccordionContent>
92+
</AccordionItem>
93+
</Accordion>
94+
95+
</Step>
96+
97+
<Step>
98+
99+
## Create Your First Workflow
100+
101+
Create a new file for our first workflow:
102+
103+
```typescript title="workflows/user-signup.ts" lineNumbers
104+
import { sleep } from "workflow";
105+
106+
export async function handleUserSignup(email: string) {
107+
"use workflow"; // [!code highlight]
108+
109+
const user = await createUser(email);
110+
await sendWelcomeEmail(user);
111+
112+
await sleep("5s"); // Pause for 5s - doesn't consume any resources
113+
await sendOnboardingEmail(user);
114+
115+
return { userId: user.id, status: "onboarded" };
116+
}
117+
118+
```
119+
120+
We'll fill in those functions next, but let's take a look at this code:
121+
122+
* We define a **workflow** function with the directive `"use workflow"`. Think of the workflow function as the _orchestrator_ of individual **steps**.
123+
* 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.
124+
125+
## Create Your Workflow Steps
126+
127+
Let's now define those missing functions.
128+
129+
```typescript title="workflows/user-signup.ts" lineNumbers
130+
import { FatalError } from "workflow"
131+
132+
// Our workflow function defined earlier
133+
134+
async function createUser(email: string) {
135+
"use step"; // [!code highlight]
136+
137+
console.log(`Creating user with email: ${email}`);
138+
139+
// Full Node.js access - database calls, APIs, etc.
140+
return { id: crypto.randomUUID(), email };
141+
}
142+
143+
async function sendWelcomeEmail(user: { id: string; email: string; }) {
144+
"use step"; // [!code highlight]
145+
146+
console.log(`Sending welcome email to user: ${user.id}`);
147+
148+
if (Math.random() < 0.3) {
149+
// By default, steps will be retried for unhandled errors
150+
throw new Error("Retryable!");
151+
}
152+
}
153+
154+
async function sendOnboardingEmail(user: { id: string; email: string}) {
155+
"use step"; // [!code highlight]
156+
157+
if (!user.email.includes("@")) {
158+
// To skip retrying, throw a FatalError instead
159+
throw new FatalError("Invalid Email");
160+
}
161+
162+
console.log(`Sending onboarding email to user: ${user.id}`);
163+
}
164+
```
165+
166+
Taking a look at this code:
167+
168+
* 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`.
169+
* 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).
170+
* Steps can throw a `FatalError` if an error is intentional and should not be retried.
171+
172+
<Callout>
173+
We'll dive deeper into workflows, steps, and other ways to suspend or handle events in [Foundations](/docs/foundations).
174+
</Callout>
175+
176+
</Step>
177+
178+
<Step>
179+
180+
## Create Your Route Handler
181+
182+
To invoke your new workflow, we'll have to add your workflow to a `POST` API route handler, `api/signup.post.ts` with the following code:
183+
184+
```typescript title="api/signup.post.ts"
185+
import { start } from 'workflow/api';
186+
import { defineEventHandler } from 'nitro/h3';
187+
import { handleUserSignup } from "../workflows/user-signup";
188+
189+
export default defineEventHandler(async ({ req }) => {
190+
const { email } = await req.json() as { email: string };
191+
// Executes asynchronously and doesn't block your app
192+
await start(handleUserSignup, [email]);
193+
return {
194+
message: "User signup workflow started",
195+
}
196+
});
197+
```
198+
199+
This route handler creates a `POST` request endpoint at `/api/signup` that will trigger your workflow.
200+
201+
<Callout>
202+
Workflows can be triggered from API routes or any server-side code.
203+
</Callout>
204+
205+
</Step>
206+
207+
</Steps>
208+
209+
## Run in development
210+
211+
To start your development server, run the following command in your terminal in the Vite root directory:
212+
213+
```bash
214+
npm run dev
215+
```
216+
217+
Once your development server is running, you can trigger your workflow by running this command in the terminal:
218+
219+
```bash
220+
curl -X POST --json '{"email":"hello@example.com"}' http://localhost:5173/api/signup
221+
```
222+
223+
Check the Vite development server logs to see your workflow execute as well as the steps that are being processed.
224+
225+
Additionally, you can use the [Workflow DevKit CLI or Web UI](/docs/observability) to inspect your workflow runs and steps in detail.
226+
227+
```bash
228+
npx workflow inspect runs
229+
# or add '--web' for an interactive Web based UI
230+
```
231+
232+
<img src="/o11y-ui.png" alt="Workflow DevKit Web UI" />
233+
234+
---
235+
236+
## Deploying to production
237+
238+
Workflow DevKit apps currently work best when deployed to [Vercel](https://vercel.com/home) and needs no special configuration.
239+
240+
Check the [Deploying](/docs/deploying) section to learn how your workflows can be deployed elsewhere.
241+
242+
## Next Steps
243+
244+
* Learn more about the [Foundations](/docs/foundations).
245+
* Check [Errors](/docs/errors) if you encounter issues.
246+
* Explore the [API Reference](/docs/api-reference).

pnpm-lock.yaml

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)