A
Ali Aslam
Guest
So youβre convinced that Svelte is worth your time (if not, go back and re-read previous article in the series
). Now itβs time to actually spin up a Svelte app and see it in action.
By the end of this article, youβll have:
Letβs dive in.
Gone are the days of mysterious webpack configs and 50-line setup guides. SvelteKit makes it almost too easy.
Youβll need Node.js v18+ installed. It includes npm, which weβll use to install and run packages like Svelte. Svelte (and SvelteKit) are distributed as npm packages you add to a project.
With that ready, open your terminal and run:
This uses the official Svelte CLI (
Youβll be asked which language you want to use: JavaScript or TypeScript.
Youβll see a checklist like:
Recommended for this tutorial:
Choose npm and the CLI will auto-install dependencies for you. If you chose None, install manually:
The CLI prints the next steps:
This starts the dev server and opens your browser. Your app runs at http://localhost:5173. Press Ctrl + C to stop.
Before you start coding, letβs make sure your editor understands Svelte.
Use VS Code β Itβs free, popular, and has the best Svelte support.
Now your editor will understand Svelte syntax and give you autocomplete. Restart VS Code if things donβt kick in right away.
Now you can step into project folder i.e.
To execute the
Before we start wildly coding, letβs peek under the hood. Hereβs what a fresh SvelteKit minimal project looks like today:
Looks neat, right? Letβs break it down:
Any files in here (images, icons,
Notice whatβs missing compared to older tutorials:
Thatβs the high-level view. Next, weβll poke around inside
In most frameworks, you have to set up a router, configure paths, and map components manually.
In SvelteKit? You just make files.
SvelteKit uses file-based routing: the structure of the
Hereβs what you get in a fresh project:
That
Donβt worry if some of these sound confusing right now.
For the moment, you only need to focus on +page.svelte (pages) and +layout.svelte (layouts). Weβll explore the others (server data, error handling) later in the series.
So:
β¦creates a new page at:
And if you add:
β¦youβll get:
Letβs try it out:
Inside
Drop in some code:
Don't worry about the code itself for now. This would be covered in detail later. For now you can copy and paste, or best, type in the code. In my experience, building muscle memory by typing is the best way to learn a new language. But it's your call.
Now visit http://localhost:5173/about.
Boom β you have a new page. No router config. No imports. Just the file.
Thatβs file-based routing: the folder structure = your URL structure.
Most apps have common stuff on every page β navbars, footers, sidebars. In SvelteKit, thatβs what
When you created the project, SvelteKit already gave you a layout file:
In other words: wherever you put
Older versions of svelte use
They mean the same thing:
When you move between
Visualized:
Letβs add a navbar so itβs shared across all pages:
Now you would see a navigation bar at top of the page, and when you navigate between
If earlier section about layout/navigation confused you, you can read it again and it would make total sense now.
No need for 
Layouts can nest inside each other, which is super useful for organizing sections of your app.
For example, say you have a dashboard with multiple pages under
Create a new layout just for that section:
Now when you visit:
Visualized:
Notice how the dashboard layout is nested inside the root layout. Thatβs why your section nav appears under the main navbar by default β unless you style it differently with CSS.
Step 6: The
The
Think of it as your toolbox. Inside
If youβve worked with plain JavaScript, Vite, or Rollup before, you might be used to seeing
SvelteKit flips that convention on its head:
Mental shift:
Letβs build a simple counter as your very first reusable component.
Create a new file:
Now letβs try it out. Open your home page (
When you click the button, the number goes up.
Quick note on
You might notice we wrote
Both still work today, but
Pro tip: Want to keep your homepage clean? Create a new route (src/routes/counter/+page.svelte) and put the there instead. That way your counter demo lives on its own page.
As your app grows,
With this structure, your imports stay clean thanks to the
Key takeaway:
Keeping it well-organized from the start makes your project easier to scale, maintain, and even share as a package later.
Step 7:
Peek into
This is the raw HTML file that wraps your whole app. Youβll rarely need to touch it, but itβs useful for:
Example: add a Google Font:
Boom, now your whole app uses Roboto.
Step 8: Static Assets β Where to Put Your Images
Want to add an image to your site? Drop it in
Example: place
Now in a Svelte file:
No import needed β itβs served directly from
Step 9: Your First Tweak
Youβve now got the key building blocks:
Time to put it into practice.
Challenge:
Need ideas?
Thereβs no βrightβ answer here β the goal is just to practice using layouts + lib components together.
Letβs recap what we covered today:
Thatβs a lot of ground covered β you now understand how a SvelteKit project is structured and how pages/layouts flow together.
Note: All the coding youβve done so farβbuilding pages, layouts, and library componentsβis designed as a warm-up, not your final implementation. Youβre getting hands-on familiarity with the structure and flow of a SvelteKit app. Weβll revisit and refine these concepts as we go deeper in later articles.
In the next article (βReactivity 101 β The \$ Magic in Svelteβ), weβll dive into what makes Svelte really shine: its reactivity model. Thatβs where the fun begins.
Continue reading...

By the end of this article, youβll have:
- A working SvelteKit project running locally.
- A solid understanding of the project structure.
- The confidence to poke around without fear of breaking stuff.
Letβs dive in.

Table of Contents
Step 1: Installing SvelteKit
- 1) Choose a template
- 2) Choose a language
- 3) Pick extras (integrations)
- 4) Package manager
- 5) Run the app
Step 2: The Project Structure
src/
β Your main playgroundstatic/
Config & meta files
Step 3: Routes & Pages β The Magic of File-Based Routing
Naming rules you should know
Step 4: Layouts β Reusing UI Across Pages
Whatβs going on here?
Optional clarification: Old vs. new SvelteKit
What happens when you navigate?
Letβs customize it
Step 5: Nested Layouts (Optional but Powerful)
- Add some child pages
- How it works
Step 6: Thelib/
Folder β Your Personal Toolbox
But waitβ¦ isnβt
lib/
usually output?- Example: a Counter component
- Use it in the home page
Best practices for
lib/
organization
Step 8: Static Assets β Where to Put Your Images
Step 9: Your First Tweak (Practice Challenge)
Wrapping Up
Step 1: Installing SvelteKit
Gone are the days of mysterious webpack configs and 50-line setup guides. SvelteKit makes it almost too easy.

With that ready, open your terminal and run:
Code:
npx sv create hello-svelte
This uses the official Svelte CLI (
sv
) to scaffold your project. It replaces the old npm create svelte@latest
flow.1) Choose a template
- SvelteKit minimal β clean, barebones setup (use this for the tutorial)
- SvelteKit demo β comes with example code
- Svelte library β for publishing reusable components (not needed here)
2) Choose a language
Youβll be asked which language you want to use: JavaScript or TypeScript.
- For this series, select JavaScript (weβll keep things plain and simple).
- If you prefer TypeScript, pick it hereβthe CLI sets it up for you. You can always consult Svelteβs TS docs later if you switch.
3) Pick extras (integrations)
Youβll see a checklist like:
Code:
[β’] prettier
[ ] eslint
[ ] vitest
[ ] playwright
[ ] tailwindcss
[ ] sveltekit-adapter
[ ] devtools-json
[ ] drizzle
[ ] lucia
[ ] mdsvex
[ ] paraglide
[ ] storybook
Recommended for this tutorial:
- Prettier β
keep checked (auto-formats your code)
- Everything else β skip for now (weβre starting lean; you can add tools later)
4) Package manager
- npm β
recommended (comes with Node.js)
- yarn / pnpm / bun / deno β fine if you already use them
- None β skips installing dependencies
Choose npm and the CLI will auto-install dependencies for you. If you chose None, install manually:
Code:
cd hello-svelte
npm install
5) Run the app
The CLI prints the next steps:
Code:
π Project steps
1: cd hello-svelte
2: npm run dev -- --open
You can do it now, or from within the editor (VSCode terminal) after reading the next part.
This starts the dev server and opens your browser. Your app runs at http://localhost:5173. Press Ctrl + C to stop.
π Editor Setup (Recommended)
Before you start coding, letβs make sure your editor understands Svelte.
Use VS Code β Itβs free, popular, and has the best Svelte support.
- Install Visual Studio Code.
- In VS Code, go to the Extensions Marketplace and add:
- Svelte for VS Code (official extension β gives you autocomplete, IntelliSense, error checking).
- Prettier (if you selected Prettier in the setup wizard, this ensures consistent formatting).
- ESLint (optional, if you enabled ESLint in the wizard).
Now your editor will understand Svelte syntax and give you autocomplete. Restart VS Code if things donβt kick in right away.
Now you can step into project folder i.e.
cd hello-svelte
and issue command code .
to bring up visual studio code open in context of your project folder. (Don't forget the '.' which stands for current folder). You can also open the folder from file menu.To execute the
npm run dev
command from within visual studio code, use the Terminal->New terminal menu option. And then issue the command from there.Step 2: The Project Structure
Before we start wildly coding, letβs peek under the hood. Hereβs what a fresh SvelteKit minimal project looks like today:
Code:
hello-svelte/
βββ src/
β βββ routes/
β β βββ +page.svelte
β βββ lib/
βββ static/
βββ .gitignore
βββ .npmrc
βββ jsconfig.json
βββ package.json
βββ package-lock.json
βββ svelte.config.js
βββ vite.config.js
βββ README.md
Looks neat, right? Letβs break it down:
src/
β Your main playground
routes/ β File-based routing. Each+page.svelte
is a page.
+page.svelte
β A page component (the+
is part of the convention).+layout.svelte
β (optional) shared layout for nested routes (headers, footers, navbars, etc.).
lib/ β For reusable code: components, stores, utilities.
static/
Any files in here (images, icons,
robots.txt
, etc.) are served as-is at the root of your site.
Config & meta files
- svelte.config.js β SvelteKitβs main config (adapters, preprocessors, etc.). Youβll touch this later when deploying or adding integrations.
- vite.config.js β Vite bundler config. Usually fine as-is, but you can tweak it for advanced use cases.
- jsconfig.json β Helps your editor with IntelliSense and path aliases (
$lib
points tosrc/lib
). - .npmrc β Locks npm-specific settings (e.g. ensuring consistent installs across machines).
- .gitignore β Tells Git which files/folders to skip (like
node_modules/
or.svelte-kit/
). - package.json / package-lock.json β Dependency list and scripts (start, dev, build, etc.), like any Node.js project.
- README.md β Quick notes about your project.

app.html
β this used to be editable, but in modern SvelteKit itβs handled internally. You rarely, if ever, need to touch the HTML shell anymore.
Thatβs the high-level view. Next, weβll poke around inside
src/routes/
and see how pages and layouts actually work.Step 3: Routes & Pages β The Magic of File-Based Routing
In most frameworks, you have to set up a router, configure paths, and map components manually.
In SvelteKit? You just make files.

SvelteKit uses file-based routing: the structure of the
src/routes/
folder defines the URLs in your app.Hereβs what you get in a fresh project:
Code:
src/
βββ routes/
βββ +page.svelte β http://localhost:5173/
That
+page.svelte
is your home page.Why the plus sign?
Files that start with+
are special SvelteKit route files (+page.svelte
,+layout.svelte
, etc.).
The+
makes them easy to spot and prevents conflicts with your own files.
Anything without+
is just normal code you can write freely.
Naming rules you should know
+page.svelte
β a Svelte component that renders when you visit that route.+layout.svelte
β optional wrapper for shared UI (like navbars/footers). We'll explore it further in next step.+page.server.js
/+page.server.ts
β server-side data loading for that page.+layout.server.js
β server-side data loading for layouts.+error.svelte
β error boundary for that route.- Folders β create subroutes. A folder becomes part of the URL path.

For the moment, you only need to focus on +page.svelte (pages) and +layout.svelte (layouts). Weβll explore the others (server data, error handling) later in the series.
So:
Code:
src/routes/about/+page.svelte
β¦creates a new page at:
Code:
http://localhost:5173/about
And if you add:
Code:
src/routes/blog/+page.svelte
β¦youβll get:
Code:
http://localhost:5173/blog
Letβs try it out:
Inside
src/routes/
, create a file called:
Code:
about/+page.svelte
Drop in some code:
Code:
<script>
let team = $state(["Ali", "Bob", "Caleb"]);
</script>
<h1>About Us</h1>
<ul>
{#each team as person}
<li>{person}</li>
{/each}
</ul>
Don't worry about the code itself for now. This would be covered in detail later. For now you can copy and paste, or best, type in the code. In my experience, building muscle memory by typing is the best way to learn a new language. But it's your call.
Now visit http://localhost:5173/about.

Thatβs file-based routing: the folder structure = your URL structure.
Step 4: Layouts β Reusing UI Across Pages
Most apps have common stuff on every page β navbars, footers, sidebars. In SvelteKit, thatβs what
+layout.svelte
is for.When you created the project, SvelteKit already gave you a layout file:
src/routes/+layout.svelte
Code:
<script>
import favicon from '$lib/assets/favicon.svg';
let { children } = $props();
</script>
<svelte:head>
<link rel="icon" href={favicon} />
</svelte:head>
{@render children?.()}
Whatβs going on here?
$props()
β gives you the props that SvelteKit automatically passes into this layout.let { children } = $props();
β extracts the specialchildren
prop.children
β represents the current page being displayed.{@render children?.()}
β actually renders that page at this spot inside the layout.

{@render children?.()}
, thatβs where the current page goes.
Optional clarification: Old vs. new SvelteKit (Optional: for people familiar with old svelte syntax)
Older versions of svelte use
<slot />
. In modern SvelteKit (v2+), thatβs been replaced with the children
prop.They mean the same thing:
<slot />
(old) β βinsert the page here.β{@render children?.()}
(new) β βinsert the page here.β
What happens when you navigate?
When you move between
/
and /about
, the layout stays the same.- The
<nav>
and anything else in+layout.svelte
is persistent. - Only the children (the current page) changes.
Visualized:
Code:
+layout.svelte
βββ <nav> ... </nav> β stays put
βββ {@render children?.()} β replaced with the current page
ββ / β renders src/routes/+page.svelte
ββ /about β renders src/routes/about/+page.svelte
Letβs customize it
Letβs add a navbar so itβs shared across all pages:
Code:
<script>
import favicon from '$lib/assets/favicon.svg';
let { children } = $props();
</script>
<svelte:head>
<link rel="icon" href={favicon} />
</svelte:head>
<nav>
<a href="/">Home</a> |
<a href="/about">About</a>
</nav>
{@render children?.()}
Now you would see a navigation bar at top of the page, and when you navigate between
/
and /about
, the navbar stays put, while the children (page content) swaps out.If earlier section about layout/navigation confused you, you can read it again and it would make total sense now.

<Router>
wrappers or Outlet
components β layouts are built in. Simple, clean, elegant. 
Step 5: Nested Layouts (Optional but Powerful)
Layouts can nest inside each other, which is super useful for organizing sections of your app.
For example, say you have a dashboard with multiple pages under
/dashboard
.Create a new layout just for that section:
Code:
src/routes/dashboard/+layout.svelte
Code:
<script>
let { children } = $props();
</script>
<section>
<h2>Dashboard</h2>
<nav>
<a href="/dashboard">Overview</a> |
<a href="/dashboard/settings">Settings</a>
</nav>
{@render children?.()}
</section>
Tip: In Visual Studio Code, you can select 'routes' folder and create new file asdashboard/+layout.svelte
, and it would automatically place +layout.svelte under dashboard folder (and create dashboard folder if it didn't exist already)
Add some child pages
src/routes/dashboard/+page.svelte
Code:
<h3>Dashboard Overview</h3>
<p>Welcome to your dashboard.</p>
src/routes/dashboard/settings/+page.svelte
Code:
<h3>Dashboard Settings</h3>
<p>Here you can update your preferences.</p>
How it works
Now when you visit:
/dashboard
β youβll see the global navbar (from root layout), then the Dashboard heading + section nav, and finally the Overview page./dashboard/settings
β the global navbar and the dashboard layout stay put, only the page content (Settings
) swaps out.
Visualized:
Code:
+layout.svelte (root)
βββ Global navbar (always visible)
βββ {@render children?.()}
βββ +layout.svelte (dashboard)
βββ Dashboard title + nav (always visible inside dashboard)
βββ {@render children?.()}
βββ +page.svelte β /dashboard
βββ settings/+page.svelte β /dashboard/settings

Step 6: The lib/
Folder β Your Personal Toolbox
The
src/lib/
folder in SvelteKit is special: itβs where you put reusable code that multiple pages will need.Think of it as your toolbox. Inside
lib
, youβll usually keep:- Components β buttons, modals, navbars
- Stores β shared state (like logged-in user info)
- Utils β helper functions
But waitβ¦ isnβt lib/
usually output?
If youβve worked with plain JavaScript, Vite, or Rollup before, you might be used to seeing
lib/
(or dist/
, build/
) as an output folder where compiled bundles go.SvelteKit flips that convention on its head:
- In SvelteKit,
src/lib/
is source code you write, not build output. - Why? Because SvelteKit is designed to feel like an app and a package at the same time. By keeping reusable code in
lib
, you could later publish parts of it (e.g. components or utilities) as an npm package if you wanted.

src/lib/
is input, not output. Treat it like your personal library of building blocks.Example: a Counter component
Letβs build a simple counter as your very first reusable component.
Create a new file:
Code:
src/lib/Counter.svelte
Code:
<script>
// This is a normal JavaScript variable
// but marked with $state so Svelte knows:
// βwhen this changes, update the UI.β
let count = $state(0);
</script>
<!-- Here we *use* that variable in the UI -->
<button onclick={() => count++}>
Count: {count}
</button>
Use it in the home page
Now letβs try it out. Open your home page (
src/routes/+page.svelte
) and add the counter:
Code:
<script>
import Counter from '$lib/Counter.svelte';
</script>
<h1>Welcome to SvelteKit</h1>
<p>Hereβs your first component in action:</p>
<Counter />
When you click the button, the number goes up.

Whatβs going on here?
- In the
<script>
section ofCounter.svelte
, you declared a variable (count
) and told Svelte it should update the UI when it changes. - In the markup, you used
{count}
inside the button β so every timecount
changes, the text updates automatically.
In+page.svelte
, you imported theCounter
component and wrote<Counter />
.
- Thatβs just a custom HTML element provided by your component.
- Think of it like
<button>
or<h1>
, except you created it yourself. - This is how you reuse components in Svelte β build once, drop them anywhere.

$state
:You might notice we wrote
let count = $state(0)
instead of let count = 0
.Both still work today, but
$state
is the recommended way because it makes it clear which variables should update the UI. At the moment it's a suggested nudge, but in later versions the support might be dropped altogether.
Best practices for lib/
organization
As your app grows,
lib/
can get messy if you throw everything in the root. Common practice is to add subfolders:
Code:
src/lib/
βββ components/
β βββ Counter.svelte
β βββ Button.svelte
β βββ Navbar.svelte
βββ stores/
β βββ user.js
βββ utils/
β βββ formatDate.js
βββ assets/
βββ favicon.svg
- components/ β all your Svelte components
- stores/ β global state (using Svelte stores)
- utils/ β helper JS functions
- assets/ β icons, images, static files you want to import in code (different from
/static
, which is for files served as-is)

$lib
alias:
Code:
import Counter from '$lib/components/Counter.svelte';
import { user } from '$lib/stores/user.js';
import formatDate from '$lib/utils/formatDate.js';

src/lib/
is not an output folder. Itβs your reusable code folder.Keeping it well-organized from the start makes your project easier to scale, maintain, and even share as a package later.
Step 7: app.html
β The Root Template
Peek into
src/app.html
.This is the raw HTML file that wraps your whole app. Youβll rarely need to touch it, but itβs useful for:
- Adding meta tags (
<meta name="description" ...>
). - Linking external fonts or stylesheets.
- Setting a global favicon.
Example: add a Google Font:
Code:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap">
Boom, now your whole app uses Roboto.

Step 8: Static Assets β Where to Put Your Images
Want to add an image to your site? Drop it in
static/
.Example: place
logo.png
in static/
.Now in a Svelte file:
Code:
<img src="/logo.png" alt="App Logo" />
No import needed β itβs served directly from
/
. Super handy for logos, icons, or other non-dynamic assets.Step 9: Your First Tweak
(Practice Challenge)
Youβve now got the key building blocks:
- Layouts (
+layout.svelte
) for shared UI src/lib/
for reusable components

Challenge:
- Create a new component in
src/lib/
(maybe aHeader
,Footer
, orNavbar
). - Import it into your root layout (
src/routes/+layout.svelte
). - Style it a little to make it your own.

- A
Header
with a logo and tagline. - A
Footer
with your name and the year. - Move your
<nav>
into its ownNavbar.svelte
.
Thereβs no βrightβ answer here β the goal is just to practice using layouts + lib components together.
Wrapping Up
Letβs recap what we covered today:
Spun up a SvelteKit project.
Explored routes & file-based routing.
Learned about layouts (global + nested).
Discovered the
lib/
folder,app.html
, andstatic/
.Built our first reusable component.
Thatβs a lot of ground covered β you now understand how a SvelteKit project is structured and how pages/layouts flow together.
Note: All the coding youβve done so farβbuilding pages, layouts, and library componentsβis designed as a warm-up, not your final implementation. Youβre getting hands-on familiarity with the structure and flow of a SvelteKit app. Weβll revisit and refine these concepts as we go deeper in later articles.
In the next article (βReactivity 101 β The \$ Magic in Svelteβ), weβll dive into what makes Svelte really shine: its reactivity model. Thatβs where the fun begins.

Continue reading...