A Udemy course with 3 complete project ready to Deploy
With Svelte 5, SvelteKit is auto-imported.
$state (no more import store needed), $derived, $effect, $props (better than export let)$bindable and $on runesadapter-auto no more settings are required (auto-deplouy for Netlify, Vercel, Cloudflare, Node, ...)hook.server and hook.client)bun and pnpm Create new app svelte:
npx sv create my-app # create app svelte in classic mode (npm)
npm run dev # run npm app
bunx sv create my-app # create app svelte with a speed up (bun)
bun run dev # run bun app
N.B.
To get max compatibility use a local folder to create app (this avoid errors of FileSystem compatibility)
Chose the initial settings like this:
Then open project folder
cd my-app
bun install # to install needed packages
The first file we check is in src/routes/+page.svelte
Content in this file is directly rendered inside the browser like a simple html page.
<script lang='ts'>
</script>
<button onclick={() => console.log("You clicked this button")}>
Click me!
</button>
<p>Hello</p>
<style>
</style>
As you can see this simple script include a button and a title , but I can organize code better usgin tags script like this
<script lang='ts'>
function onclick() {
console.log("event clicked inside script tag");
}
</script>
<button onclick={onclick} >
Click me!
</button>
<p>Hello</p>
Svelte give the feature of shorthand implementation, this work only if event has the same name of function called
<button onclick={onclick} > // simple function assignment
<button {onclick} > // shorthand assignment
<button onclick={onclick2} > // this doesn't support shorthand call
Another feature of Svelte is the ability to render a parameter values inside the HTML tag
<script lang='ts'>
let numberOne = 1;
</script>
<h2>{numberOne}</h2>
<p>Hello</p>
<style>
h2 {
color: blue;
}
</style>
this simple code render inside html page
1 <!--h2 tag in color blue-->
Hello <!--as simple paragraph text-->
Each style inside the page has a modular value, this means that the styles has visible only in the current page.
So I can write a simple indentation like this...
<div class="container">
<p>This is the left side</p>
<p>This is the right side</p>
</div>
<style>
.container {
display: flex;
justify-content: space-between;
border: 2px solid black;
padding: 10px;
margin-top: 10px;
background-color: #f0f0f0;
border-radius: 5px;
font-family: Arial, sans-serif;
font-size: 16px;
color: #333;
}
</style>
In this case separate the paragraphs in 2 columns, giving the font and colors defined inside <style> tag
As a framework js Svelte give some solution for reactivity programming.
This is possible implementing the runes. There are several types of rune inside Svelte and SvelteKit.
One of this is $state rune:
<script>
let number = $state(0); // define a reactive variable as number = 0
function onclick () {
number++; // simple update number as integer (like in C++)
}
</script>
<h2>{number}</h2> // this render the "number" variable
<button {onclick}>Increment number</button> // this call incremental function
Come avviene in JSX in svelte posso modulare il contenuto di un tag semplicemente aggiungendo un contenuto condizionale come segue:
<p>{number === 0 ?
"Click the button to start" :
`number of clicks = {number}`}</p>
This is a case of modal content where
As $state manage reactivity of the variables, there is a rune that is useful for modular content called $derived.
So I can Organize previous code like this:
<script>
let userInfo = $derived(
number === 0 ?
"Click the button to start" :
`number of clicks = {number}`
);
</script>
<p>{userInfo}</p>
With $derived rune I can replicate the content several times just adding inside the HTML tag the name of block I declare in the <script> tag, in this case userInfo
I can also bind a funciton to the rune giving a fine grained condition that is organize a little better:
<script>
let number = $state(0);
let userInfo = $derived.by(() => calculateUserInfo(numer));
function onclick() {
number++;
}
function calculateUserInfo(number: number) {
switch(number) {
case 0:
return "Click button to start counter";
case 1:
return "You've clicked 1 time";
default:
`You've clicked ${number} times`;
}
}
</script>
<button {onclick}>Click me</button>
<p>{getMessage()}</p>
In this example I use the rune $derived.by that means I first run function calculateUserInfo before get response.
Under the hoods, Svelte manage the status change as Signal (already presents in modern version of Angular and Vue.js).
Another useful rune in svelte is $effect rune.
Consider a sample textfield for userName value
<script>
let userName = $state("");
</script>
<h3>Your username</h3>
<input type="text" bind:value={userName}/>
<p>{userName}</p>
Maybe this input field can be used to send a search query to the DB. In this case I can implement a $effect rune that run just after any change of variable state for userName
<script>
let userName = $state("");
$effect(() => {
// execute first time and at each $effect call
console.log("effect rune is running");
if (userName) { // execute at each state change of userName
console.log(`Sending username to run query on the DB, current username is: ${userName} `);
}
})
</script>
<h3>Your username</h3>
<input type="text" bind:value={userName}/>
<!-- This bind the input field to the username value -->
<p>{userName}</p>
As I can note the <input> tag has an attribute bind:value that just connect the content of the field to the variable userName.
If I would track my state change (mainly for debugging purpose) it's useful implement an importa rune called $inspect.
Taking this example:
<script>
let userName = $state("");
$inspect(userName);
</script>
<h3>Your username</h3>
<input type="text" bind:value={userName}/>
<p>{userName}</p>
I can now check the console log is nore clean and value focused on every state change of the variable userName
Like many JS frameWork I maybe neet to create a modular component ready to use as needed.
Considering now to split previous code in a separate component saved in the folder src/lib/components/UserInput.svelte
<script lang="ts">
/* generic data inspect */
// let data = $props();
// $inspect(data);
/* can simply assign value to internal variable */
// let userName = $state(data.userName);
/* optionally I can spread props passed inside variables directly */
// let { userName, children, ...props } = $props<{ userName: string }>();
/*or define an interface that is used as props model*/
import type { Snippet } from "svelte";
interface UserInputInterface {
userName: string;
children: Snippet;
}
let { userName, children, ...props }: UserInputInterface = $props();
</script>
<h2>Your username</h2>
<input type="text" bind:value={userName} />
<!-- This is needed to render children tags for the element 'UserName' -->
{@render children()}
<p>{userName}</p>
<style>
h2 {
color: blue;
font-family: "Gill sans", "Gill Sans MT", Calibri, "Trebuchet MS", sans-serif;
}
</style>
And in the main page in src/routes/+page.svelte
<script>
import UserInput from "$lib/components/UserInput.svelte";
</script>
<UserInput userName={"Pikachu"}>
<h3>Stuff passed inside the input tag</h3>
</UserInput>
As you can see I use :
UserInputInterface to define type of content I pass inside the componentSnippet as Svelte type to define contents Passed inside Component as as HTML element (saved as children){@render children()} to visualize children passed inside propsUserInput is tha name of the file component also the Tag used inside te page to instantiate itAs before we now implement Snippet component to show different usecases
Edite directly the file +page.svelte to make this test
<script lang="ts">
let userName = $state("Niklas");
let isEditMode = $state(false);
</script>
{#snippet userInput(exampleString: string)}
<h3>Your username</h3>
{#if isEditMode}
<input type="text" bind:value={userName} />
{:else}
<p>{userName}</p>
{/if}
{/snippet}
{@render userInput("Example 1")}
<br />
<button onclick={() => isEditMode = !isEditMode}>
{isEditMode ? "Save Changes" : "Edit Fields"}
</button>
We see a classic conditional snippet to show and hide a text input field.
But I can implement also a list of element with Snippet component:
<script lang='ts'>
let peopleWaiting = $state(['1760974261222', '1760974261229']);
</script>
<h1>Waiting queue</h1>
{#snippet userInput(personId: string)}
<li>ID for person: {personId}</li>
{/snippet}
<ul>
{#each peopleWaiting as person}
{@render userInput(person)}
{/each}
</ul>
<button onclick={() => peopleWaiting.push(new Date().getTime().toString())}>I'm waiting too!</button>
In this case Snippet component instantiate a row to the list wich is
userInput callThe the list is populated by calling an each loop wich check element one by one
#each peopleWaiting as person@render userInput(person)Then the button append in the main array id value wich is the time converted to string
peopleWaiting.push(new Date().getTime().toString())Populating the main array peopleWaiting declared in the top of the page
let peopleWaiting = $state(['1760974261222', '1760974261229'])As part of Svelte 5 installation SvelteKit doesn't need a separate initial setup.
This is a main feature of Svelte 5 wich allow to get feature of WvelteKit "out of the box".
Get this example of blog project:
<a href="/blog">Click to go to blog</a>
A second one in src/routes/blog/+page.svelte with this content
<h3>Welcome to out blog!</h3>
This is a sample wich include a connection between 2 pages.
Now, in the latest version of Svelte 5 and SvelteKit layout are included based on position of the routing page like +layout.svelte and the new settings using $props.
<script lang="ts">
import favicon from '$lib/assets/favicon.svg';
let { children } = $props();
</script>
<svelte:head>
<link rel="icon" href={favicon} />
</svelte:head>
{@render children?.()}
This template is default setup to create a common style of the website.
I can for example
render childrenCreate a file in src/ app.css like
html + {
font family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
Then include inside +layout.svelte file to bind the css style like this
<script lang="ts">
import './../app.css'
let data = $props();
</script>
<header>Welcome! Landing Page</header>
{@render data.children()}
This will iclude css stule created inside app.css file applying the font-family on whole content.
For each pages that has dynamic path, Svelte allow to include a sulug to routing folders (articleId for example)
take for example this path routes/blog/[articleId]
inside I can add a dynamic blog article +page.svelte
this will get parameters to populate each field of the content like title, description, image, body of article.
So I can for example add this content to +page.svelte
<h1>Blog article</h1>
And get this by write this path to the browser
There are 3 layer of data fetching
import { error } from "@sveltejs/kit";
import type { PageServerLoad } from "./$types";
export const load: PageServerLoad = async ({ params }) => {
const blogArticles = [
{
id: '1',
title: 'First Article',
content: 'This is the content of the first article.'
},
{
id: '2',
title: 'Second Article',
content: 'This is the content of the second article.'
},
{
id: '3',
title: 'Third Article',
content: 'This is the content of the third article.'
},
];
const foundArticle = blogArticles.find(
(article) => article.id === params.articleId
);
if (foundArticle) {
return {
id: foundArticle.id,
blogPost: foundArticle.title,
postContent : foundArticle.content,
};
}
throw error(404, 'Article not found');
};
then In the same folder I can create the file +page.svelte like this:
<script lang="ts">
let { data } = $props();
let { id, blogPost, postContent } = data;
</script>
<h2>Blog Article !</h2>
<h3>Article ID: {id}</h3>
<h5>Article Title: {blogPost}</h5>
<p>Article Content: {postContent}</p>
<style>
h2 {
color: green;
}
</style>
now this is an example of how a dynamic content can be fetched by a single blog page.
To remove load from the server is sufficent to remove the +page.server.ts and create another file called +page.tscopying the full content of the previous page to the new one.
the only update to the code is the function called to load the page then modify main function from PageServerLoad to PageLoad
N.B.
If doesn't charge function or there are missing installs run from terminal the command bun install to add missing packages.
Now to get more accessibility to various article of the blog, add in the +page.svelte file.
<h3>Welcome to our blog!</h3>
<a href="/blog/1">Read Article 1</a><br>
<a href="/blog/2">Read Article 2</a><br>
<a href="/blog/3">Read Article 3</a><br>
N.B.
Notice that also the layout page run in the same manner of the pages, so
The III° point is the same as previous explains for +page.svelte
In SvelteKit you can create some endpoint to implement API Requests. The right manner is to add a file called +server.ts that will follow a specific endpoint for the URI path.
For example if I want to call a REST API that delete my account I can simply add :
So to implement create the folder structure inside src/routes path.
so the next step is to implement the function to create a business logic of the endpoint.
import { json } from "@sveltejs/kit";
export async function POST({ request }) {
const purchaseData = await request.json();
console.log('Purchase confirmed:', purchaseData);
return json({ status: 'success', data: purchaseData });
}
now to test endpoint on Postman you need to create a new request in POST mode and add an endpoint like
Then set the header of the request
{
"id": 123,
"item": "Pokedex 2025",
"quantity": 2
}
This continue to the Section 4 of udemy course