A Practical Introduction to Svelte

Hey, and welcome to this tutorial! If you’re here, you’ve probably heard of Svelte surpassing and wanna know what all the fuzz is about. Luckily I’m here to walk you through the vital concepts of Svelte, by towers a real-world project that I think you’ll really like! So without remoter ado, let’s get started with a primer on what Svelte plane is:

What is Svelte?

Svelte is a “radical new tideway to towers user interfaces”, equal to the official documentation. In practice, Svelte is quite similar to JavaScript frameworks like React, Vue and Angular – it’s a way to create websites and web applications using primarily JavaScript. Like these frameworks, Svelte is moreover based virtually the idea of components: small “chunks” of lawmaking that encapsulates template and logic, to create reusable “building blocks”.

A archetype example of a component could be a navigation menu, which is usually present on every page on the website. Having it as a component makes sense, to encapsulate all the related lawmaking in one place for easy modification in the future. To succeed this, Svelte borrows the idea of SFC’s (Single File Components) from Vue. The idea is to write all your logic in a <component-name>.svelte file, which combines all the necessary HTML, CSS and JS for that component.

While all the major frameworks use components as their key abstraction, Svelte differs from them in a few key areas:
1. Svelte is unquestionably a compiler rather than a framework. Meaning that while you develop you lawmaking in a similar malleate to other frameworks, Svelte will compile it into vanilla JavaScript for the browser to use.
2. Svelte tries to stay tropical to the native platform of the web. It does this by leveraging “standard” HTML, CSS and JS as much as possible.

These two points are what makes Svelte heady to me. It’s a vapor of fresh air, and considering Svelte is a compiler, it can include a lot increasingly features “out-of-the-box” since it doesn’t have to worry well-nigh shipping everything to the browser. That’s why Svelte comes with seated animations, a global store and many other unconfined features.

Let’s explore Svelte by towers a real-world project: A Cryptocurrency tracker!

What we’ll be building

We’re gonna build an overview page of the most popular cryptocurrencies, by fetching some data from an external API, and displaying it using variegated Svelte features. This will indulge us to get familiar with:

  • Svelte components (using .svelte files)
  • Iterating over an variety to exhibit some data
  • If/else statements in Svelte
  • Handling sawed-off clicks from the user
  • Styling Svelte components
  • Dynamically tightness classes based on data

Our finished project will end up looking like this:


I’ll moreover include a list of uneaten full-length ideas for you to play virtually with and implement yourself, to get plane increasingly familiar with Svelte.

Installation and setup

So, surpassing we get started, there’s a few requirements: You must have NodeJS installed, and wangle to a terminal/shell. You’ll moreover need a lawmaking editor. I recommend VS Code, as it comes with a seated terminal, but you can use whatever you like.

With those in place, unshut up a terminal and create a new project using the official Svelte starter template:

1npx degit sveltejs/template svelte-crypto-tracker

npx comes seated with NodeJS, degit is a project scaffolding tool, sveltejs/template is the official template, and svelte-crypto-tracker is the name of our project (feel self-ruling to rename it). When that’s done, you want to cd into the project:

1cd svelte-crypto-tracker

Then, install the dependencies and start the project in minutiae mode:

1npm install

2npm run dev

Open up localhost:5000 in your browser to see the official welcome page:

When you see this, you’re up and running! Now unshut the lawmaking folder in your editor, and let’s get started on our app.

Getting started

In the src folder, there’s an App.svelte component. This is our main component that the template has generated for us, and where we’ll be writing most of our logic. Every .svelte file consists of 3 parts (not necessarily in this order):

  • A script block, containing all the JavaScript logic
  • A style block, where we can write CSS that will be scoped to this component
  • And finally, the rest of the file becomes our template, where we write HTML and use special Svelte features to manipulate it

By default, we’re showing Hello {name}, where name is a property passed to our component from somewhere else – in this case, the main.js file responsible for bootstrapping our app. We can see that name is supposed as a variable in the script tag, with export let name.

In Svelte, any variable specified in the script woodcut is misogynist to use in the template. And if we put export in front of it, that allows other components to pass a property lanugo into this variable. Start by removing the export and setting the variable to “Crypto Tracker” instead, and then simply exhibit that in the template:

1// src/App.svelte


3 let name = "Crypto Tracker";




7 <h1>{name}</h1>


Great! There’s really not much else to variables in Svelte, and this simplicity is one of the reasons I enjoy working with it.

Let’s add a sawed-off too, that we’ll use to fetch the forge data from an API in a moment. We’ll do that by subtracting a special on:click directive that Svelte gives us, and tell it to undeniability a function when that happens:

1// src/App.svelte


3 let name = "Crypto Tracker";


5 function fetchCoins() {

6 console.log("Hello world!");

7 }




11 <h1>{name}</h1>

12 <button on:click={fetchCoins}>Fetch Forge Data!</button>


Click the sawed-off and trammels your panel to verify that it works – you should see “Hello world!“. Now let’s get to the meat, and unquestionably fetch some data and show it on the screen.

Fetching and displaying data

We’re gonna get our data from the Coinstats API, so let’s update our lawmaking by subtracting a new variable, coins, and setting it to an empty variety – and then transpiration our fetchCoins function to fetch some data (all in the script tag):

1// src/App.svelte


3 let coins = [];


5 async function fetchCoins() {

6 const response = rely fetch(

7 "https://api.coinstats.app/public/v1/coins?skip=0&limit=20"

8 );

9 const data = rely response.json();

10 coins = data.coins;

11 console.log("coins:", coins);

12 }


There’s a couple of things going on in our function, so lets walk through it. Firstly, we reverted our function to be async, and then undeniability the native browser fetch function, passing an URL to the API endpoint we get from the API documentation. This particular endpoint will fetch the first 20 coins. Try to unshut the link in your browser to see what kind of data we’re getting back.

We then save this in a response variable, and undeniability the .json() function on it, to get the data in a format we can work with. Finally, we update our coins variety with the fetched forge data, and log it to the console. It should squint something like this:


Awesome! We got some data, now let’s show it on the page. We can do this using the svelte {#each} block. This takes an variety (our coins array), and iterates over it, giving us wangle to each individual forge object inside the array. Use it like this:

1// src/App.svelte


3 <h1>{name}</h1>

4 <button on:click={fetchCoins}>Fetch Forge Data!</button>

5 {#each coins as coin}

6 <p>{coin.name}</p>

7 {/each}


That’ll show 20 forge names on our page – neat! But just showing the name isn’t that exciting, we moreover want to see stuff like the current price and recent percentage changes in the price. So for each coin, we’re gonna make a new component tabbed CoinCard.

In the src folder, create a new file tabbed CoinCard.svelte. Put the pursuit lawmaking in the file:

1// src/CoinCard.svelte


3 export let coin




7 {coin.name} - {coin.symbol}


The export let coin tells Svelte that we expect a forge prop to be passed to this component. Let’s switch when to App.svelte and use our new component by importing it at the top of our file, right unelevated the opening script tag:

1// src/App.svelte

2import CoinCard from "./CoinCard.svelte"

And then we’ll use it inside our loop, by replacing

1// src/App.svelte

2{#each coins as coin}

3 <p>{coin.name}</p>



1// src/App.svelte

2{#each coins as coin}

3 <CoinCard {coin} />


Sweet! Now we’re still iterating our coins array, and for each coin, we’re rendering our CoinCard component, passing lanugo the data for a particular forge as a prop. The {coin} part of the whilom lawmaking is unquestionably a shorthand for writing coin={coin}, with the first coin stuff the name of the variable in the CoinCard component (that we supposed using export let coin), and the second coin stuff the very value from the array. If we wanted to, we could pass other data by subtracting something like hello={42}, and if the CoinCard exported a variable tabbed hello, it would receive the value 42.

Showing increasingly data and styling

Let’s show some increasingly data than just the forge name and symbol. Replace the HTML with:

1// src/CoinCard.svelte

2<div class="coin-card">

3 <img class="coin-image" src={coin.icon} alt="" />

4 <p class="coin-name">{coin.name}</p>

5 <div class="coin-details">

6 <div

7 class="detail-field price-change"

8 >

9 {coin.priceChange1w}%

10 </div>

11 <div class="detail-field">{coin.price.toFixed(2)}$</div>

12 <a class="detail-field" href={coin.websiteUrl}>Website &#8594;</a>

13 </div>


This will show the forge icon, name, price transpiration over the last week, the current price (fixed to 2 decimal points using the JS function toFixed()), and a link to the coins website. This is unconfined information, but it doesn’t squint good.


Let’s fix that. Another tomfool thing well-nigh Svelte is that we can write CSS directly in our component using the style tags, and this CSS will only wield to elements inside this component. I’ve written a tuft of CSS for us here to make the CoinCards squint a lot better. Paste the unelevated lawmaking in your CoinCard.svelte file, on the bottom:

1// src/CoinCard.svelte


3 .coin-card {

4 background-color: white;

5 border-radius: 20px;

6 --tw-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1),

7 0 10px 10px -5px rgba(0, 0, 0, 0.04);

8 box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),

9 var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);

10 }


12 .coin-image {

13 max-width: 4rem;

14 margin-top: 10px;

15 }


17 .coin-name {

18 font-size: 24px;

19 font-weight: bold;

20 margin-top: 15px;

21 }


23 .coin-details {

24 display: grid;

25 grid-template-columns: 1fr 1fr 1fr;

26 border-top: 1px solid #d1d5db;

27 background-color: #f3f4f6;

28 }


30 .detail-field {

31 font-size: 15px;

32 font-weight: bold;

33 padding: 15px 0;

34 }


36 .detail-field:not(:last-child) {

37 border-right: 1px solid #d1d5db;

38 }


40 .price-change {

41 color: #dc2626;

42 }


44 .positive {

45 color: #16a34a;

46 }


48 @media (min-width: 1024px) {

49 .detail-field {

50 font-size: 18px;

51 padding: 15px;

52 }

53 }


I won’t walk through what all the styles do, but it’s mostly organizing the content in a grid and waffly font sizes/colors/margins. We’ll moreover need to retread some things in App.svelte, so go when to that file and add these styles:

1// src/App.svelte


3 main {

4 text-align: center;

5 padding: 40px 0;

6 margin: 0 auto;

7 }

8 h1 {

9 color: #ff3e00;

10 text-transform: uppercase;

11 font-size: 4em;

12 font-weight: 100;

13 }


15 .grid {

16 display: grid;

17 grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));

18 gap: 30px;

19 }


21 @media (min-width: 640px) {

22 main {

23 max-width: 1600px;

24 padding: 40px 20px;

25 }

26 }


And also, let’s wrap our iterating loop in a grid class:

1// src/App.svelte

2<div class="grid">

3 {#each coins as coin}

4 <CoinCard {coin} />

5 {/each}


Head when to the app, and it should squint something like this:


Much better, right? Now we’re unquestionably showing useful information in a nice grid overview. There’s still a few things to do, so let’s tackle those next.

Adding some details

As you might have noticed, all the price changes (shown in percentage) are currently colored red. But wouldn’t it be nice if they were colored untried to indicate a positive increase, and only red if the price has decreased? This is unquestionably quite easy using Svelte’s class directive.

Back in CoinCard.svelte, let’s add a function to determine if the price transpiration is positive or negative. Paste the lawmaking right unelevated the previous export let coin in the script tag:

1function changeIsPositive(priceChange) {

2 return priceChange >= 0;


This function will take a number (the priceChange) and trammels if it’s greater than or equal to 0. If it is, our function will return true (and false if the number is negative).

Now that we have a way to icon out if the priceChange is positive, we can add a dynamic matriculation binding. Find the div element with a matriculation of detail-field price-change, and add the pursuit symbol to the element:


This special Svelte directive will add the positive matriculation if the changeIsPositive function returns true when passed the coin’s weekly price change, and false otherwise. The positive matriculation is specified in the style tag, and simply makes the text green:

1.positive {

2 color: #16a34a;


Your price-change element should now squint like this:

1// src/CoinCard.svelte


3 class="detail-field price-change"

4 class:positive={changeIsPositive(coin.priceChange1w)}


6 {coin.priceChange1w}%


Aaaand now our app will show a untried number for positive increases:


Almost there! Let’s add one final detail surpassing wrapping up. I’d prefer if we only show the “Fetch Forge Data!” sawed-off when no coins have been loaded. And luckily, we can hands succeed this using Sveltes {#if} block. Head when to App.svelte and update the template to squint like this:

1// src/App.svelte


3 <h1>{name}</h1>

4 {#if coins.length === 0}

5 <button on:click={fetchCoins}>Fetch Forge Data!</button>

6 {:else}

7 <div class="grid">

8 {#each coins as coin}

9 <CoinCard {coin} />

10 {/each}

11 </div>

12 {/if}


Here we’re saying, IF the coins variety has length 0 (meaning we don’t have any forge data yet), show the sawed-off to fetch coins. Otherwise, we have once fetched the forge data, so we show the grid and iterate over the coins instead. To make sure this works, visit the app and printing the button. It should disappear as the coins get loaded 👍

Awesome! I think we got a pretty sleek looking app here. However, there’s a lot of other features that would be unconfined to add as well.

Observability for Production Apps

Debugging your JavaScript apps in production may be challenging and time-consuming. Asayer is a frontend monitoring tool that replays everything your users do and shows how your app behaves and renders for every issue. It’s like having your browser’s inspector unshut while looking over your user’s shoulder.

Asayer Frontend Monitoring

Asayer helps to quickly get to the root rationalization by reproducing issues as if they happened in your own browser. It moreover monitors your frontend performance by capturing key metrics such as page load time, memory consumption and slow network requests.

Happy debugging, for modern frontend teams – Start monitoring your web app for free.

Features to add

Now that you know the nuts of Svelte and have a working app, I encourage you to try subtracting some increasingly features on your own. Unelevated is a list for inspiration, but finger self-ruling to add whatever you can think of – try to make it your own!

  • Add an input field where the user can write a forge name to filter the results
  • Allow the user to fetch increasingly coins with a “Load More” button
  • Make each forge clickable to show increasingly data on that coin
  • Show a graph of price changes for a explicit coin
  • Allow the user to sort the coins by percentage growth or current price
  • Deploy the project to Netlify


Thanks for reading! I hope this gave you a nice introduction to Svelte, and that you had as much fun with the project as I did. I really encourage you to add a few uneaten features and deploy the project to Netlify. You can plane add it as a portfolio project on your website if you’d like!

To learn increasingly well-nigh Svelte, trammels out the official tutorial which has lots of great, interactive examples. And alimony your vision out for SvelteKit, which is an upcoming meta-framework on top of Svelte (kind of like NextJS for React) that’s currently in beta.

Finally, I’d love to know your thoughts on Svelte and this article, so hit me up on Twitter at @madsbrodt. Thank you!

Comments are closed.