Skip to content

Commit 7750e03

Browse files
Svelte demo (#1909)
1 parent eed852e commit 7750e03

File tree

2 files changed

+328
-0
lines changed

2 files changed

+328
-0
lines changed

examples/_data.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,11 @@ export const sidebar = [
219219
href: "https://fresh.deno.dev/docs/getting-started/create-a-project/",
220220
type: "tutorial",
221221
},
222+
{
223+
title: "Build a Svelte app",
224+
href: "/examples/svelte_tutorial/",
225+
type: "tutorial",
226+
},
222227
{
223228
title: "Build a Vue app",
224229
href: "/examples/vue_tutorial/",

examples/tutorials/svelte.md

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
---
2+
title: "Build a SvelteKit App"
3+
description: "A tutorial on building SvelteKit applications with Deno. Learn how to set up a SvelteKit project, implement file-based routing, manage state with load functions, and create a full-stack TypeScript application."
4+
url: /examples/svelte_tutorial/
5+
oldUrl:
6+
- /runtime/manual/examples/how_to_with_npm/svelte/
7+
- /runtime/tutorials/how_to_with_npm/svelte/
8+
---
9+
10+
[SvelteKit](https://kit.svelte.dev/) is a web framework built on top of
11+
[Svelte](https://svelte.dev/), a modern front-end compiler that builds highly
12+
optimized vanilla JavaScript. SvelteKit provides features like file-based
13+
routing, server-side rendering, and full-stack capabilities.
14+
15+
In this tutorial we'll build a simple SvelteKit app with Deno. The app will
16+
display a list of dinosaurs. When you click on one, it'll take you to a dinosaur
17+
page with more details. You can see the
18+
[finished app on GitHub](https://github.com/denoland/tutorial-with-svelte).
19+
20+
You can see a live version of the app on
21+
[Deno Deploy](https://tutorial-with-svelte.deno.deno.net/).
22+
23+
:::info Deploy your own
24+
25+
You can deploy your own version of this svelte app to Deno Deploy immediately.
26+
Just click the button!
27+
28+
[![Deploy on Deno](https://deno.com/button)](https://app.deno.com/new?clone=https://github.com/denoland/tutorial-with-svelte)
29+
30+
:::
31+
32+
## Create a SvelteKit app with Deno
33+
34+
We'll use [SvelteKit](https://kit.svelte.dev/) to create a new SvelteKit app. In
35+
your terminal, run the following command to create a new SvelteKit app:
36+
37+
```shell
38+
deno run -A npm:create-svelte
39+
```
40+
41+
When prompted, give your app a name and select the "Skeleton project" template.
42+
Choose "Yes, using TypeScript syntax" when asked about TypeScript.
43+
44+
Once created, `cd` into your new project and run the following command to
45+
install dependencies:
46+
47+
```shell
48+
deno install
49+
```
50+
51+
Then, run the following command to serve your new SvelteKit app:
52+
53+
```shell
54+
deno task dev
55+
```
56+
57+
Deno will run the `dev` task from the `package.json` file which will start the
58+
Vite development server. Click the output link to localhost to see your app in
59+
the browser.
60+
61+
## Configure the formatter
62+
63+
`deno fmt` supports Svelte files with the
64+
[`--unstable-component`](https://docs.deno.com/runtime/reference/cli/fmt/#formatting-options-unstable-component)
65+
flag. To use it, run this command:
66+
67+
```sh
68+
deno fmt --unstable-component
69+
```
70+
71+
To configure `deno fmt` to always format your Svelte files, add this at the top
72+
level of your `deno.json` file:
73+
74+
```json
75+
"unstable": ["fmt-component"]
76+
```
77+
78+
## Add a backend API
79+
80+
We'll build API routes using SvelteKit's built-in API capabilities. SvelteKit
81+
allows you to create API endpoints by creating `+server.js` or `+server.ts`
82+
files in your routes directory.
83+
84+
In the `src/routes` directory, create an `api` folder. In that folder, create a
85+
`data.json`, which will contain the hard coded dinosaur data.
86+
87+
Copy and paste
88+
[this json file](https://github.com/denoland/tutorial-with-svelte/blob/main/src/routes/api/data.json)
89+
into the `src/routes/api/data.json` file. (If you were building a real app, you
90+
would probably fetch this data from a database or an external API.)
91+
92+
We're going to build out some API routes that return dinosaur information.
93+
SvelteKit provides a simple way to create API endpoints using server files.
94+
95+
Create `src/routes/api/dinosaurs/+server.ts` to handle the `/api/dinosaurs`
96+
endpoint. This will return all dinosaurs:
97+
98+
```js title="src/routes/api/dinosaurs/+server.ts"
99+
import { json } from "@sveltejs/kit";
100+
import data from "../data.json" with { type: "json" };
101+
102+
export function GET() {
103+
return json(data);
104+
}
105+
```
106+
107+
Then create `src/routes/api/dinosaurs/[id]/+server.ts` to handle individual
108+
dinosaur requests at `/api/dinosaurs/:id`:
109+
110+
```ts title="src/routes/api/dinosaurs/[id]/+server.ts"
111+
import { json } from "@sveltejs/kit";
112+
import type { RequestHandler } from "./$types";
113+
import data from "../../data.json" with { type: "json" };
114+
115+
export const GET: RequestHandler = ({ params }) => {
116+
const dinosaur = data.find((item) => {
117+
return item.name.toLowerCase() === params.id.toLowerCase();
118+
});
119+
120+
if (dinosaur) {
121+
return json(dinosaur);
122+
}
123+
124+
return json({ error: "Not found" }, { status: 404 });
125+
};
126+
```
127+
128+
SvelteKit automatically handles routing based on the file structure. The
129+
`+server.ts` files define API endpoints, and the `[id]` folder creates a dynamic
130+
route parameter.
131+
132+
## Build the frontend
133+
134+
### File-based routing and data loading
135+
136+
SvelteKit uses file-based routing, where the structure of your `src/routes`
137+
directory determines your app's routes. Unlike Vue Router, you don't need to
138+
configure routes manually - SvelteKit automatically creates routes based on your
139+
file structure.
140+
141+
In SvelteKit, `+page.svelte` files define page components, and `+page.ts` files
142+
define data loading functions that run before the page loads. This provides
143+
built-in server-side rendering and data fetching capabilities.
144+
145+
### The pages and components
146+
147+
SvelteKit organizes the frontend into pages and components. Pages are defined by
148+
`+page.svelte` files in the routes directory, while components can be reusable
149+
pieces of code stored anywhere in your project.
150+
151+
Each Svelte component file contains three optional sections: `<script>`,
152+
`<template>` (the HTML), and `<style>`. The `<script>` tag contains the
153+
JavaScript/TypeScript logic, the template contains the HTML markup, and the
154+
`<style>` tag contains scoped CSS.
155+
156+
We'll create pages for the home page and individual dinosaur details, along with
157+
data loading functions to fetch dinosaur information from our API.
158+
159+
#### The home page
160+
161+
The home page will display a list of dinosaurs fetched from our API. First,
162+
create `src/routes/+page.ts` to load the dinosaur data:
163+
164+
```ts title="src/routes/+page.ts"
165+
import type { PageLoad } from "./$types";
166+
167+
export const load: PageLoad = async ({ fetch }) => {
168+
const res = await fetch(`/api/dinosaurs`);
169+
const dinosaurs = await res.json();
170+
171+
return { dinosaurs };
172+
};
173+
```
174+
175+
This load function runs on both the server and client, and the data is passed to
176+
the page component. The `fetch` function is provided by SvelteKit and works in
177+
both server and client environments.
178+
179+
Next, update `src/routes/+page.svelte` to display the dinosaur list:
180+
181+
```html title="src/routes/+page.svelte"
182+
<script lang="ts">
183+
import type { PageProps } from "./$types";
184+
185+
let { data }: PageProps = $props();
186+
let dinosaurs = data.dinosaurs;
187+
</script>
188+
189+
<main>
190+
<h1>🦕 Dinosaur app</h1>
191+
<p>Click on a dinosaur below to learn more.</p>
192+
{#each dinosaurs as dinosaur (dinosaur.name)}
193+
<a href="/{dinosaur.name.toLowerCase()}" class="dinosaur">
194+
{dinosaur.name}
195+
</a>
196+
{/each}
197+
</main>
198+
```
199+
200+
This code uses Svelte's [each block](https://svelte.dev/docs/logic-blocks#each)
201+
to iterate over the `dinosaurs` array and render each dinosaur as a link. The
202+
`{#each}` block is Svelte's way of rendering lists, and the `(dinosaur.name)`
203+
provides a unique key for each item.
204+
205+
#### The Dinosaur detail page
206+
207+
The dinosaur detail page will display information about a specific dinosaur.
208+
SvelteKit uses folder names in square brackets to create dynamic routes. The
209+
`[dinosaur]` folder creates a route that captures the dinosaur name from the
210+
URL.
211+
212+
First, create `src/routes/[dinosaur]/+page.ts` to load individual dinosaur data:
213+
214+
```ts title="src/routes/[dinosaur]/+page.ts"
215+
import type { PageLoad } from "./$types";
216+
import { error } from "@sveltejs/kit";
217+
218+
export const load: PageLoad = async ({ fetch, params }) => {
219+
const res = await fetch(`/api/dinosaurs/${params.dinosaur}`);
220+
const dinosaur = await res.json() as { name: string; description: string };
221+
222+
if (res.status === 404) {
223+
return error(404, "No dinosaur found");
224+
}
225+
226+
return { dinosaur };
227+
};
228+
```
229+
230+
This load function uses the `params` object to access the `dinosaur` parameter
231+
from the URL. If the API returns a 404, we use SvelteKit's `error` function to
232+
throw a 404 error.
233+
234+
Next, create `src/routes/[dinosaur]/+page.svelte` to display the dinosaur
235+
details:
236+
237+
```html title="src/routes/[dinosaur]/+page.svelte"
238+
<script lang="ts">
239+
import type { PageProps } from "./$types";
240+
241+
let { data }: PageProps = $props();
242+
let dinosaur = data.dinosaur;
243+
</script>
244+
245+
<div>
246+
<h1>{dinosaur.name}</h1>
247+
<p>{dinosaur.description}</p>
248+
<a href="/">🠠 Back to all dinosaurs</a>
249+
</div>
250+
```
251+
252+
This page displays the dinosaur's name and description, along with a link back
253+
to the home page. The data comes from the load function and is automatically
254+
available in the component.
255+
256+
## Run the app
257+
258+
Now that we've set up the frontend and backend API routes, we can run the app.
259+
In your terminal, run the following command:
260+
261+
```shell
262+
deno task dev
263+
```
264+
265+
This will start the SvelteKit development server with Vite. SvelteKit
266+
automatically handles both the frontend pages and the API routes we created, so
267+
you don't need to run separate servers.
268+
269+
Visit `http://localhost:5173` in your browser to see the app. Click on a
270+
dinosaur to see more details!
271+
272+
You can see a live version of the app on
273+
[Deno Deploy](https://tutorial-with-svelte.deno.deno.net/).
274+
275+
## Build and deploy
276+
277+
SvelteKit comes with built-in build capabilities. We configured it to use the
278+
Deno adapter, which optimizes the build for deployment on Deno-compatible
279+
platforms. Run the following command to build the app in production mode:
280+
281+
```sh
282+
deno task build
283+
```
284+
285+
This will:
286+
287+
1. Build the SvelteKit app using Vite
288+
2. Generate optimized production assets
289+
3. Create server-side code compatible with Deno
290+
291+
The built app will be ready for deployment on platforms that support Deno, such
292+
as Deno Deploy.
293+
294+
You can deploy this app to your favorite cloud provider. We recommend using
295+
[Deno Deploy](https://deno.com/deploy) for a simple and easy deployment
296+
experience. You can deploy your app directly from GitHub, simply create a GitHub
297+
repository and push your code there, then connect it to Deno Deploy.
298+
299+
### Create a GitHub repository
300+
301+
[Create a new GitHub repository](https://github.com/new), then initialize and
302+
push your app to GitHub:
303+
304+
```sh
305+
git init -b main
306+
git remote add origin https://github.com/<your_github_username>/<your_repo_name>.git
307+
git add .
308+
git commit -am 'my svelte app'
309+
git push -u origin main
310+
```
311+
312+
### Deploy to Deno Deploy
313+
314+
Once your app is on GitHub, you can deploy it on the Deno Deploy<sup>EA</sup>
315+
dashboard.
316+
<a href="https://app.deno.com/" class="docs-cta deploy-cta deploy-button">Deploy
317+
my app</a>
318+
319+
For a walkthrough of deploying your app, check out the
320+
[Deno Deploy tutorial](/examples/deno_deploy_tutorial/).
321+
322+
🦕 Now that you can run a SvelteKit app in Deno with the Deno adapter you're
323+
ready to build real world applications!

0 commit comments

Comments
 (0)