SvelteKit Beginner Tutorial: Your First Web App
Start your web development journey with SvelteKit! This SvelteKit beginner tutorial guides you through setting up your first project, understanding core concepts, and building a simple app.

SvelteKit Beginner Tutorial: Build Your First Web App
SvelteKit is a powerful, modern framework for building web applications of all sizes, powered by the innovative Svelte compiler. If you're looking for a fast, efficient, and enjoyable way to build web projects, starting with SvelteKit is an excellent choice. This SvelteKit beginner tutorial will guide you through the essential steps to get your first application up and running, covering core concepts and practical examples.
We'll demystify the setup process, explore key features like routing and data loading, and empower you to confidently begin your SvelteKit development journey.
Why Choose SvelteKit for Your Next Project?
Before we dive into the code, let's briefly understand why SvelteKit stands out in the crowded web development landscape. Unlike traditional frameworks that run much of their logic in the browser, Svelte compiles your code into tiny, highly optimized JavaScript at build time. This approach leads to several significant advantages:
- Blazing Fast Performance: Less client-side JavaScript means faster load times and smoother user experiences.
- Exceptional Developer Experience: Svelte's syntax is intuitive and close to plain JavaScript, HTML, and CSS, making it easy to learn and write.
- Built-in SSR, SSG, and SPA: SvelteKit provides server-side rendering (SSR), static site generation (SSG), and single-page application (SPA) capabilities out of the box, offering flexibility for various project needs.
- Small Bundle Sizes: The compiler produces minimal code, resulting in smaller application sizes and faster downloads.
- Full-Stack Capabilities: With its adapter system, SvelteKit can be deployed to a wide range of platforms, from Node.js servers to serverless functions and static hosts.
These benefits make SvelteKit an incredibly compelling choice for both new and experienced developers.
Prerequisites for Your SvelteKit Journey
To follow this SvelteKit beginner tutorial, you'll need a few things set up on your machine:
- Node.js (LTS version): SvelteKit projects require Node.js for dependency management and running development servers. Download the latest LTS version from nodejs.org.
- npm or Yarn (or pnpm): These are package managers that come with Node.js. We'll primarily use
npmin our examples. - A Code Editor: Visual Studio Code (VS Code) is highly recommended due to excellent Svelte extensions like "Svelte for VS Code."
Once you have these installed, you're ready to create your first SvelteKit application!
Step 1: Setting Up Your First SvelteKit Project
Let's get hands-on. Open your terminal or command prompt and follow these steps:
Initialize the Project
Navigate to the directory where you want to create your project and run the following command:
npm create svelte@latest my-first-sveltekit-app
Replace my-first-sveltekit-app with your desired project name. The create svelte command is the official way to scaffold a new SvelteKit project.
Follow the Prompts
After running the command, you'll be presented with a series of prompts. Here's what they mean and our recommended choices for a beginner:
Which Svelte app template?:Skeleton project: A minimal SvelteKit project. Recommended for beginners.SvelteKit demo app: A more feature-rich demo.Library project: For building Svelte component libraries.- Select
Skeleton project.
Add type checking with TypeScript?:Yes, using TypeScript syntax: Best for robust projects.Yes, using JSDoc comments: Good for gradually adding types.No: Pure JavaScript.- Recommended for beginners:
Yes, using TypeScript syntaxto get used to typed JavaScript, which improves code quality and maintainability.
Add ESLint for code linting?:Yes: ESLint helps enforce code style and catch errors. Recommended.
Add Prettier for code formatting?:Yes: Prettier automatically formats your code, ensuring consistency. Recommended.
Add Playwright for browser testing?:Yes: For end-to-end testing.No: Can be added later. Recommended for beginners:Noto keep things simple for now.
Add Vitest for unit testing?:Yes: For unit testing components and functions.No: Can be added later. Recommended for beginners:Noto keep things simple for now.
Once you've made your selections, SvelteKit will create the project structure.
Install Dependencies and Run the Development Server
Navigate into your newly created project directory:
cd my-first-sveltekit-app
Install the project dependencies:
npm install
Finally, start the development server:
npm run dev -- --open
The --open flag will automatically open your default web browser to http://localhost:5173 (or a similar port). You should see a page displaying "Welcome to SvelteKit!" This confirms your setup is successful.
Step 2: Understanding the Project Structure
Let's take a quick tour of the essential files and folders in your new SvelteKit project:
my-first-sveltekit-app/
├── .svelte-kit/ # Generated files (don't touch)
├── src/
│ ├── app.html # Main HTML template for SvelteKit
│ ├── app.d.ts # Global type definitions
│ └── routes/ # Where your application pages and API endpoints live
│ ├── +page.svelte # The main homepage for your application
│ └── +layout.svelte # Global layout for all pages
├── static/ # Static assets (images, fonts, etc.)
├── package.json # Project metadata and scripts
├── svelte.config.js # SvelteKit configuration
├── tsconfig.json # TypeScript configuration (if you chose TypeScript)
└── vite.config.ts # Vite configuration (SvelteKit uses Vite)
The most important directory for development is src/routes/. This is where you'll define your application's pages and API endpoints.
Step 3: Core SvelteKit Concepts
Let's delve into the fundamental building blocks of a SvelteKit application.
Svelte Components (.svelte files)
Svelte components are single files ending with .svelte that encapsulate HTML, CSS, and JavaScript.
Example: src/routes/+page.svelte
<!-- src/routes/+page.svelte -->
<script lang="ts">
let name = 'SvelteKit Developer';
function greet() {
alert(`Hello, ${name}!`);
}
</script>
<style>
h1 {
color: #ff3e00;
}
button {
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
}
</style>
<h1>Welcome, {name}!</h1>
<p>This is your first SvelteKit app.</p>
<button on:click={greet}>Say Hello</button>
Key takeaways:
<script>block: Contains your JavaScript logic. Variables declared here are reactive, meaning changes to them automatically update the DOM.<style>block: Contains your CSS. Styles are scoped to this component by default, preventing conflicts with other components.- HTML markup: Uses standard HTML, with Svelte extensions for reactivity (
{name}) and event handling (on:click).
Routing in SvelteKit
SvelteKit uses a file-system-based router. This means that the structure of your src/routes directory directly dictates your application's URL structure.
src/routes/+page.svelte: This becomes the root route (/).src/routes/about/+page.svelte: This becomes the/aboutroute.src/routes/blog/[slug]/+page.svelte: This creates dynamic routes like/blog/my-first-postwhere[slug]is a parameter.
Let's create a new page.
- Create a new folder
src/routes/about. - Inside
src/routes/about, create a file named+page.svelte.
src/routes/about/+page.svelte
<!-- src/routes/about/+page.svelte -->
<h1>About Us</h1>
<p>We are learning SvelteKit!</p>
<p>Visit our <a href="/">homepage</a>.</p>
Now, save this file and visit http://localhost:5173/about in your browser. You should see your new "About Us" page.
Layouts (+layout.svelte)
Layouts allow you to share UI elements (like headers, footers, navigation) across multiple pages.
src/routes/+layout.svelte: Applies to all pages in your application.src/routes/admin/+layout.svelte: Applies to all pages within the/adminroute and its sub-routes.
Let's create a global layout.
- Open
src/routes/+layout.svelte. (It should already exist from the skeleton project).
src/routes/+layout.svelte
<!-- src/routes/+layout.svelte -->
<script lang="ts">
import '../app.css'; // Import global styles if needed
</script>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/products">Products</a> {# For a page we'll create next #}
</nav>
<main>
<slot></slot> <!-- This is where your page content will be rendered -->
</main>
<footer>
<p>© {new Date().getFullYear()} My SvelteKit App</p>
</footer>
<style>
nav {
display: flex;
gap: 1em;
padding: 1em;
background-color: #f0f0f0;
border-bottom: 1px solid #ddd;
}
nav a {
text-decoration: none;
color: #333;
font-weight: bold;
}
nav a:hover {
color: #ff3e00;
}
main {
padding: 2em;
}
footer {
text-align: center;
padding: 1em;
margin-top: 2em;
border-top: 1px solid #eee;
color: #777;
}
</style>
Now, both your homepage (/) and your about page (/about) will display the navigation and footer. The <slot> element is crucial; it's a placeholder where the content of the current page (+page.svelte) will be injected.
Data Loading (+page.server.ts or +page.ts)
SvelteKit makes data loading incredibly efficient and flexible. You can load data on the server, in the browser, or both.
+page.server.ts: For data that only needs to run on the server (e.g., fetching from a database, accessing API keys). This data is passed to the page as props.+page.ts: For data that can run on both the server and the browser (e.g., fetching public APIs, browser-specific data).
Let's create a simple "Products" page that loads data from a mock API.
- Create a new folder
src/routes/products. - Inside
src/routes/products, create+page.server.ts. - Inside
src/routes/products, create+page.svelte.
src/routes/products/+page.server.ts
// src/routes/products/+page.server.ts
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ fetch }) => {
// In a real app, this would fetch from a database or external API
const mockProducts = [
{ id: 1, name: 'SvelteKit T-Shirt', price: 25.00, description: 'Comfortable and stylish!' },
{ id: 2, name: 'SvelteKit Mug', price: 12.50, description: 'Perfect for your morning coffee.' },
{ id: 3, name: 'SvelteKit Sticker Pack', price: 5.00, description: 'Decorate your gear!' },
];
// We can simulate an API call here
// const res = await fetch('https://api.example.com/products');
// const products = await res.json();
return {
products: mockProducts
};
};
The load function in +page.server.ts runs on the server and returns an object. This object's properties become available as props to the corresponding +page.svelte component.
src/routes/products/+page.svelte
<!-- src/routes/products/+page.svelte -->
<script lang="ts">
import type { PageData } from './$types';
// Access the data loaded from +page.server.ts
export let data: PageData;
</script>
<style>
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5em;
}
.product-card {
border: 1px solid #ddd;
padding: 1em;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.product-card h3 {
color: #ff3e00;
margin-top: 0;
}
.product-card p {
font-size: 0.9em;
color: #555;
}
.product-card .price {
font-weight: bold;
color: #28a745;
}
</style>
<h1>Our Products</h1>
{#if data.products && data.products.length > 0}
<div class="product-grid">
{#each data.products as product (product.id)}
<div class="product-card">
<h3>{product.name}</h3>
<p>{product.description}</p>
<p class="price">${product.price.toFixed(2)}</p>
</div>
{/each}
</div>
{:else}
<p>No products available at the moment.</p>
{/if}
Now, navigate to http://localhost:5173/products. You'll see the product list rendered on the page, with data loaded directly from your +page.server.ts file. Notice how we use export let data: PageData; to receive the data from the load function.
Form Actions (+page.server.ts or +server.ts)
SvelteKit also simplifies handling form submissions and other server-side mutations using "form actions." These allow you to define server-side logic that runs when a form is submitted, without needing to create separate API endpoints for every form.
Let's add a simple contact form to our /about page.
Update src/routes/about/+page.server.ts (create if it doesn't exist)
// src/routes/about/+page.server.ts
import type { Actions } from './$types';
export const actions: Actions = {
default: async ({ request }) => {
const data = await request.formData();
const name = data.get('name');
const email = data.get('email');
const message = data.get('message');
// In a real application, you would save this data to a database,
// send an email, etc.
console.log('Form submission received:', { name, email, message });
// Simulate a delay for server processing
await new Promise(resolve => setTimeout(resolve, 1000));
return {
success: true,
message: 'Thank you for your message! We will get back to you soon.'
};
}
};
The actions object exports functions that handle different form submissions. The default action is used if no specific action attribute is provided on the form. It receives the request object, from which you can extract formData.
Update src/routes/about/+page.svelte
<!-- src/routes/about/+page.svelte -->
<script lang="ts">
import type { ActionData } from './$types';
export let form: ActionData; // SvelteKit automatically passes action data
</script>
<style>
form {
display: grid;
gap: 1em;
max-width: 500px;
margin-top: 2em;
padding: 1.5em;
border: 1px solid #eee;
border-radius: 8px;
background-color: #f9f9f9;
}
label {
font-weight: bold;
margin-bottom: 0.3em;
display: block;
}
input[type="text"],
input[type="email"],
textarea {
width: 100%;
padding: 0.8em;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box; /* Include padding in width */
}
textarea {
resize: vertical;
min-height: 100px;
}
button[type="submit"] {
background-color: #ff3e00;
color: white;
padding: 1em 1.5em;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 1em;
font-weight: bold;
transition: background-color 0.2s ease;
}
button[type="submit"]:hover {
background-color: #e03200;
}
.success-message {
color: #28a745;
font-weight: bold;
margin-top: 1em;
}
</style>
<h1>About Us</h1>
<p>We are learning SvelteKit!</p>
<p>Visit our <a href="/">homepage</a>.</p>
<h2>Contact Us</h2>
<form method="POST">
<label for="name">Name:</label>
<input type="text" id="name" name="name" required>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<label for="message">Message:</label>
<textarea id="message" name="message" rows="5" required></textarea>
<button type="submit">Send Message</button>
</form>
{#if form?.success}
<p class="success-message">{form.message}</p>
{/if}
Now, if you go to http://localhost:5173/about, fill out the form, and submit it, you'll see a success message appear. Check your terminal where the development server is running; you'll see the console.log output from +page.server.ts. This demonstrates a full-stack interaction with SvelteKit.
Step 4: Building and Deploying Your SvelteKit App
When you're ready to deploy your SvelteKit application, you'll use an adapter. Adapters configure SvelteKit to output your app in a format suitable for various deployment targets (e.g., Vercel, Netlify, Node.js server, static files).
Install an Adapter
For a simple static site, the adapter-static is a good choice.
npm install -D @sveltejs/adapter-static
Configure SvelteKit
Open svelte.config.js and update it to use the new adapter:
// svelte.config.js
import adapter from '@sveltejs/adapter-static'; // Import the adapter
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
// adapter-auto is recommended for most platforms (Vercel, Netlify, etc.)
// For static sites, use adapter-static
adapter: adapter({
// default options are sufficient for most static sites
pages: 'build',
assets: 'build',
fallback: undefined, // Or '404.html' for a custom 404 page
precompress: false,
strict: true
}),
paths: {
// If your site is not deployed to the root of a domain,
// e.g. 'https://example.com/my-app', set this.
// Otherwise, leave it commented out or set to ''
// base: process.argv.includes('dev') ? '' : '/my-app',
}
}
};
export default config;
Note: For full-stack applications (using server-side rendering or API routes), adapter-auto is generally the best default, as it intelligently detects your deployment environment.
Build Your Application
Run the build command:
npm run build
This command will:
- Compile your Svelte components.
- Generate the necessary JavaScript, CSS, and HTML files.
- Place the output in the
builddirectory (or whatever your adapter specifies).
For adapter-static, the build folder will contain your entirely static, deployable website. You can then serve this build folder using any static web server (like Nginx, Apache, or a simple npx serve build command).
Conclusion: Your SvelteKit Journey Begins!
Congratulations! You've successfully set up your first SvelteKit application, understood its core concepts like components, routing, layouts, data loading, and form actions, and even learned how to prepare it for deployment. This SvelteKit beginner tutorial has provided a solid foundation for you to start building more complex and interactive web applications.
SvelteKit's blend of performance, developer experience, and versatility makes it a fantastic tool for modern web development. Keep exploring the official SvelteKit documentation and don't hesitate to experiment. Happy coding!
FAQ
Q1: What is the main difference between Svelte and SvelteKit?
A1: Svelte is a component compiler that turns your Svelte code into highly optimized JavaScript at build time. SvelteKit is a framework built on top of Svelte that provides features like routing, server-side rendering (SSR), static site generation (SSG), data loading, and API endpoints, making it a full-fledged solution for building web applications. Think of Svelte as the engine and SvelteKit as the complete car.
Q2: Is SvelteKit suitable for large-scale applications?
A2: Yes, absolutely. SvelteKit is designed to be highly performant and scalable. Its compilation approach, efficient reactivity system, and built-in features for data loading and routing make it well-suited for both small projects and complex, large-scale applications requiring fast performance and good maintainability. Many companies are now using SvelteKit in production.
Q3: How do I handle global state management in SvelteKit?
A3: Svelte offers its own built-in reactive stores for state management, which are simple, efficient, and well-integrated. For more complex global state, you can use Svelte's context API or external libraries like Pinia (often used with Vue but has Svelte compatibility) or Zustand, though Svelte's stores often suffice.
Q4: Can I use SvelteKit to build a mobile app?
A4: SvelteKit itself is for web applications. However, Svelte components can be used with frameworks like NativeScript-Vue (which also supports Svelte components) or Capacitor/Cordova to wrap your web app into a native mobile container. For truly native mobile experiences, dedicated frameworks like React Native or Flutter might be more appropriate.
Q5: What is an adapter in SvelteKit?
A5: An adapter is a package that determines how your SvelteKit application is built and deployed. It transforms your compiled SvelteKit code into a format compatible with different hosting environments. For example, adapter-node builds a Node.js server, adapter-static creates static HTML/CSS/JS files, and adapter-vercel optimizes for deployment on Vercel.
Q6: How do I debug SvelteKit applications?
A6: You can debug SvelteKit applications using your browser's developer tools, similar to any other web application. For Svelte-specific debugging, the Svelte DevTools browser extension (available for Chrome and Firefox) is invaluable. It allows you to inspect component states, props, and reactivity in real-time. For server-side code (like +page.server.ts or +server.ts), you can use Node.js debugging tools or simply console.log statements in your terminal.