Udemy-Course-SvelteKit Svelte Themes

Udemy Course Sveltekit

a full course with 3 complete projects in Svelte 5 and SvelteKit

Udemy Svelte Kit Full Course

A Udemy course with 3 complete project ready to Deploy

Intro:

With Svelte 5, SvelteKit is auto-imported.

Some Svelte 5 upgrade

  • runes "out of the box" in the initial settings (in version 4 aren't default present)
    • classics runes like $state (no more import store needed), $derived, $effect, $props (better than export let)
    • added new $bindable and $on runes
  • new engine "fine-grained reactivity": only changes are updated
  • 3x performance boost from previous Svelte 4 (compiler full rewitten in TS, also improving typing)
  • better Vite 5 integration
  • updated devtools and stacktrace with clearer logging

Some Svelte Kit upgrade

  • full compatibility with Svelte 5
  • all framework is rune ready
  • flexyble and less configurations: with adapter-auto no more settings are required (auto-deplouy for Netlify, Vercel, Cloudflare, Node, ...)
  • clear and predictable routing + hooks (new API hook.server and hook.client)
  • vite 5 integration
  • speed up build with bun and pnpm
  • easy config of CSP (Content Security Policy), against XSS attack
  • Edge First, Streaming SSR (good for CMS like AEM)

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:

  • minimal
  • TypeScript
  • Prettier (SPACEBAR for options select)
  • bun (or npm , depens on your favourite package manager)

Then open project folder

cd my-app
bun install    # to install needed packages

Page Layout

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


Reactivity in Svelte

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.

– ᚠ – $state rune

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

  • I can see the first string only if button has never clicked
  • and the second one as I click the button with a number of times

– ᚾ – $derived rune

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).

– ᛃ – $effect rune

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.

– ᛗ – $inspect rune

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

– ᛟ – $props rune & components

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 component
  • Snippet as Svelte type to define contents Passed inside Component as as HTML element (saved as children)
  • {@render children()} to visualize children passed inside props
  • UserInput is tha name of the file component also the Tag used inside te page to instantiate it

The Snippet component

As 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

  • a string "ID for person: "
  • and a value 'personId' get from userInput call

The the list is populated by calling an each loop wich check element one by one

  • #each peopleWaiting as person
    and pass the id value to the function
  • @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'])

SvelteKit

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".

Routing

Get this example of blog project:

  • one page in src/routes/+page.svelte with this content
    <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

  • add an header before render children
  • add also a footer
  • create a common style for a menu and share with other pages

Add a style CSS

Create 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.

Dynamic routing

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

http://localhost:5173/blog/3


Passing data in Svelte

There are 3 layer of data fetching

  1. server only : +page.server.ts, implements Server Load Function
  2. back & front : +page.ts, Load function wich runs twice; once for backend & once for frontend
  3. frontend : +page.svelte wich can access to data being returned form +layout.ts file
  4. data from REST API: +server.ts, is the file created in the folder that is the same of endpoint

I° case, fetching from server

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.

II° case, fetching server & client side

  • Go to the folder of the slug [articleId]

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 navigate to parent folder in src/routes/blog

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

  • if i want to load layout from server just create a file +layout.server.ts
  • to load instead form client side create the file +layout.ts

III° case simple client page

The III° point is the same as previous explains for +page.svelte

IV° case, data to endpoint API

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 :

  • api/delete-account/+server.ts

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

  • Content-Type -> application/json
  • body > raw > JSON, adding this sample content
    {
      "id": 123,
      "item": "Pokedex 2025",
      "quantity": 2
    }
    

This continue to the Section 4 of udemy course

https://www.udemy.com/course/practical-sveltekit-guide-build-and-deploy-real-world-apps/learn/lecture/46325285#overview

Top categories

Loading Svelte Themes