deno.com
On this page

Build a SvelteKit App

SvelteKit is a web framework built on top of Svelte, a modern front-end compiler that builds highly optimized vanilla JavaScript. SvelteKit provides features like file-based routing, server-side rendering, and full-stack capabilities.

In this tutorial we'll build a simple SvelteKit app with Deno. The app will display a list of dinosaurs. When you click on one, it'll take you to a dinosaur page with more details. You can see the finished app on GitHub.

You can see a live version of the app on Deno Deploy.

Deploy your own

You can deploy your own version of this svelte app to Deno Deploy immediately. Just click the button!

Deploy on Deno

Create a SvelteKit app with Deno Jump to heading

We'll use SvelteKit to create a new SvelteKit app. In your terminal, run the following command to create a new SvelteKit app:

deno run -A npm:create-svelte

When prompted, give your app a name and select the "Skeleton project" template. Choose "Yes, using TypeScript syntax" when asked about TypeScript.

Once created, cd into your new project and run the following command to install dependencies:

deno install

Then, run the following command to serve your new SvelteKit app:

deno task dev

Deno will run the dev task from the package.json file which will start the Vite development server. Click the output link to localhost to see your app in the browser.

Configure the formatter Jump to heading

deno fmt supports Svelte files with the --unstable-component flag. To use it, run this command:

deno fmt --unstable-component

To configure deno fmt to always format your Svelte files, add this at the top level of your deno.json file:

"unstable": ["fmt-component"]

Add a backend API Jump to heading

We'll build API routes using SvelteKit's built-in API capabilities. SvelteKit allows you to create API endpoints by creating +server.js or +server.ts files in your routes directory.

In the src/routes directory, create an api folder. In that folder, create a data.json, which will contain the hard coded dinosaur data.

Copy and paste this json file into the src/routes/api/data.json file. (If you were building a real app, you would probably fetch this data from a database or an external API.)

We're going to build out some API routes that return dinosaur information. SvelteKit provides a simple way to create API endpoints using server files.

Create src/routes/api/dinosaurs/+server.ts to handle the /api/dinosaurs endpoint. This will return all dinosaurs:

src/routes/api/dinosaurs/+server.ts
import { json } from "@sveltejs/kit";
import data from "../data.json" with { type: "json" };

export function GET() {
  return json(data);
}

Then create src/routes/api/dinosaurs/[id]/+server.ts to handle individual dinosaur requests at /api/dinosaurs/:id:

src/routes/api/dinosaurs/[id]/+server.ts
import { json } from "@sveltejs/kit";
import type { RequestHandler } from "./$types";
import data from "../../data.json" with { type: "json" };

export const GET: RequestHandler = ({ params }) => {
  const dinosaur = data.find((item) => {
    return item.name.toLowerCase() === params.id.toLowerCase();
  });

  if (dinosaur) {
    return json(dinosaur);
  }

  return json({ error: "Not found" }, { status: 404 });
};

SvelteKit automatically handles routing based on the file structure. The +server.ts files define API endpoints, and the [id] folder creates a dynamic route parameter.

Build the frontend Jump to heading

File-based routing and data loading Jump to heading

SvelteKit uses file-based routing, where the structure of your src/routes directory determines your app's routes. Unlike Vue Router, you don't need to configure routes manually - SvelteKit automatically creates routes based on your file structure.

In SvelteKit, +page.svelte files define page components, and +page.ts files define data loading functions that run before the page loads. This provides built-in server-side rendering and data fetching capabilities.

The pages and components Jump to heading

SvelteKit organizes the frontend into pages and components. Pages are defined by +page.svelte files in the routes directory, while components can be reusable pieces of code stored anywhere in your project.

Each Svelte component file contains three optional sections: <script>, <template> (the HTML), and <style>. The <script> tag contains the JavaScript/TypeScript logic, the template contains the HTML markup, and the <style> tag contains scoped CSS.

We'll create pages for the home page and individual dinosaur details, along with data loading functions to fetch dinosaur information from our API.

The home page Jump to heading

The home page will display a list of dinosaurs fetched from our API. First, create src/routes/+page.ts to load the dinosaur data:

src/routes/+page.ts
import type { PageLoad } from "./$types";

export const load: PageLoad = async ({ fetch }) => {
  const res = await fetch(`/api/dinosaurs`);
  const dinosaurs = await res.json();

  return { dinosaurs };
};

This load function runs on both the server and client, and the data is passed to the page component. The fetch function is provided by SvelteKit and works in both server and client environments.

Next, update src/routes/+page.svelte to display the dinosaur list:

src/routes/+page.svelte
<script lang="ts">
  import type { PageProps } from "./$types";

  let { data }: PageProps = $props();
  let dinosaurs = data.dinosaurs;
</script>

<main>
  <h1>🦕 Dinosaur app</h1>
  <p>Click on a dinosaur below to learn more.</p>
  {#each dinosaurs as dinosaur (dinosaur.name)}
  <a href="/{dinosaur.name.toLowerCase()}" class="dinosaur">
    {dinosaur.name}
  </a>
  {/each}
</main>

This code uses Svelte's each block to iterate over the dinosaurs array and render each dinosaur as a link. The {#each} block is Svelte's way of rendering lists, and the (dinosaur.name) provides a unique key for each item.

The Dinosaur detail page Jump to heading

The dinosaur detail page will display information about a specific dinosaur. SvelteKit uses folder names in square brackets to create dynamic routes. The [dinosaur] folder creates a route that captures the dinosaur name from the URL.

First, create src/routes/[dinosaur]/+page.ts to load individual dinosaur data:

src/routes/[dinosaur]/+page.ts
import type { PageLoad } from "./$types";
import { error } from "@sveltejs/kit";

export const load: PageLoad = async ({ fetch, params }) => {
  const res = await fetch(`/api/dinosaurs/${params.dinosaur}`);
  const dinosaur = await res.json() as { name: string; description: string };

  if (res.status === 404) {
    return error(404, "No dinosaur found");
  }

  return { dinosaur };
};

This load function uses the params object to access the dinosaur parameter from the URL. If the API returns a 404, we use SvelteKit's error function to throw a 404 error.

Next, create src/routes/[dinosaur]/+page.svelte to display the dinosaur details:

src/routes/[dinosaur]/+page.svelte
<script lang="ts">
  import type { PageProps } from "./$types";

  let { data }: PageProps = $props();
  let dinosaur = data.dinosaur;
</script>

<div>
  <h1>{dinosaur.name}</h1>
  <p>{dinosaur.description}</p>
  <a href="/">🠠 Back to all dinosaurs</a>
</div>

This page displays the dinosaur's name and description, along with a link back to the home page. The data comes from the load function and is automatically available in the component.

Run the app Jump to heading

Now that we've set up the frontend and backend API routes, we can run the app. In your terminal, run the following command:

deno task dev

This will start the SvelteKit development server with Vite. SvelteKit automatically handles both the frontend pages and the API routes we created, so you don't need to run separate servers.

Visit http://localhost:5173 in your browser to see the app. Click on a dinosaur to see more details!

You can see a live version of the app on Deno Deploy.

Build and deploy Jump to heading

SvelteKit comes with built-in build capabilities. We configured it to use the Deno adapter, which optimizes the build for deployment on Deno-compatible platforms. Run the following command to build the app in production mode:

deno task build

This will:

  1. Build the SvelteKit app using Vite
  2. Generate optimized production assets
  3. Create server-side code compatible with Deno

The built app will be ready for deployment on platforms that support Deno, such as Deno Deploy.

You can deploy this app to your favorite cloud provider. We recommend using Deno Deploy for a simple and easy deployment experience. You can deploy your app directly from GitHub, simply create a GitHub repository and push your code there, then connect it to Deno Deploy.

Create a GitHub repository Jump to heading

Create a new GitHub repository, then initialize and push your app to GitHub:

git init -b main
git remote add origin https://github.com/<your_github_username>/<your_repo_name>.git
git add .
git commit -am 'my svelte app'
git push -u origin main

Deploy to Deno Deploy Jump to heading

Once your app is on GitHub, you can deploy it on the Deno DeployEA dashboard. Deploy my app

For a walkthrough of deploying your app, check out the Deno Deploy tutorial.

🦕 Now that you can run a SvelteKit app in Deno with the Deno adapter you're ready to build real world applications!

Did you find what you needed?

Privacy policy