Build a Jokes app with Svelte
Build a jokes app with Svelte

Svelte
Super simple and powerful compiler for JavaScript which makes development a fun again. We’ll build a jokes app which uses an api to fetch random chuck norris jokes. We’ll have a input to fetch number of jokes we want to show it in outr application.
You can use Svelte instead of..
Popular Front-End frameworks and libraries out there.
Why Svelte?
Check out this awesome presentation by Rich harris. He justifies why we should use svelte.
Important note
Svelte is a JavaScript compiler. React is a library, Angular and Vue are frameworks.
After this blog, You’ll be comfortable with…
- Click and input event listeners in svelte. (That means you will get to know how to use all event listeners).
- Initializing and updating states.
- Bind in svelte.
- How to call external api in svelte.
- Catch input value and basics of svelte reactivity.
- How to use forEach in svelte.
- Bonus — conditionals in svelte.
Quick info: Svelte will remove unused CSS on the fly.
Create new Svelte project
As in documentation, We will use npx to create our new project.
Open terminal/cmd and run the below command
npx degit sveltejs/template my-svelte-projectIt will create a folder called my-svelte-project in the same directory where you ran the command.
Basically, It is the svelte application that will have the required configuration to get started with svelte.
Install dependencies and run the project.
Change directory to my-svelte-project and
npm installIt will install all the dependencies in package.json.
Run the application by
npm run devWe made it!. Go to port 5000 to see what we got.
Quick info: Svelte uses rollup plugin to compile svelte components.
Open the App in any code editor of your choice. You will see exactly like below.
Quick info: You might not see yarn.lock if you used npm.

Let me explain all the directories you see in the picture.
node_modules
You know that already!
public
Everything you see inside the public folder is self-explanatory. You can see global CSS and bundle of JavaScript you write and index.html will be there.
src
This is where we write our code
- main.js
- It Simply says it creates new app instance using App.svelte
import App from './App.svelte'const app = new App({
target: document.body,
props: {
name: 'world',
},
})export default app
We targeted entire body here. This says you can create multiple instances targeting multiple elements.
Quick info: It is important to name as .svelte so that rollup can understand.
- App.svelte
This is the main component where we start writing our logic. As you can see, It will have the code of what you see in browser.
Now you might see the script, style and all HTML elements are there. Just like Vue, we can use single-file components.
Quick info: We have to explicitly mention scoped styling in Vue. In svelte, the styles you write inside components is automatically scoped.
- This means the style you write inside a component will not affect other components.
Coming back to App.svelte
<script>
export let name
</script>
<style>
h1 {
color: purple;
}
</style>
<h1>Hello {name}!</h1>Here We’re exporting name and in main.js we have props name that’s why we get hello name
Quick info: Svelte understands JavaScript code inside {}
Our first code
In App.svelte add the below changes
<script>
export let name
const year = new Date().getFullYear()
</script>
<style>
h1 {
color: purple;
}
</style>
<h1>Hello {name}!</h1>
<p>Current year is {year}</p>Quick info: We have hot loading. Changes you make will reflect automatically in the browser (you should save the file 😆) without manual refresh.
Now if you see the browser, You can see the current year painted in the browser. That’s how the svelte template works.
Finally, We will move to build our app.
Since this is for the tutorial purpose we’ll add the bootstrap cdn inside index.html.
Inside public/index.html
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
/>Step 1
Create layouts folder inside src
Inside src/layouts create Navbar.svelte and copy the below code
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<h3 class="navbar-brand " href="/">SvelteJokes</h3>
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="http://www.icndb.com/">Url to Jokes api</a>
</li>
</ul>
</div>
</nav>This is nothing but navbar for our app. To be more clear and understand better we’re using navbar component as layouts. why? because layouts will be used everywhere.
I hope I don’t need to explain the above html.
Let’s move on
Step 2
Create folder called views inside src
Basically views is what we see as the output. You might have known about what’s the purpose of views directory.
Inside views create Jokes.svelte.
Now let’s add both layouts and views inside App.svelte.
Delete Everything we have in App.svelte and add the below.
<script>
import Navbar from './layouts/Navbar.svelte'
import Jokes from './views/Jokes.svelte'
</script><style></style><Navbar /><Jokes />
Now you can only see the navbar in our app.
What we did was, We imported Navbar and Jokes component from layouts, views and used it in our App.svelte.
You know import statements are available in JavaScript.
That’s all we need in App.svelte.
Last step
Now the last part, Logic of our app. We gonna write it in src/views/Jokes.svelte
Quick info: We’ll be using axios for api call. Use whatever you want, It is your call.
Copy the below html in Jokes.svelte
<div class="row mt-5">
<div class="container">
<div class="input-group mb-3">
<input
type="number"
class="form-control"
placeholder="Enter the number of jokes you want"
/>
</div>
<div class="row justify-content-center">
<div>
<button class="btn btn-primary">Get Jokes</button>
</div>
</div>
</div>
</div>
<div class="row mb-5 mt-3 justify-content-center">
<div class="card" style="width: 18rem;">
<div class="card-header">Jokes</div>
<ul class="list-group list-group-flush"></ul>
</div>
</div>Above is nothing but we created the html. Nothing fancy. It will have a input element, button with get jokes text and below the jokes container to fetch jokes.
You can see it in the browser.
Let’s take a quick pause and learn some svelte before moving on.
State in svelte
See the code in below image

From the above picture svelte understands state by ”=” symbol.
let name = 'svelte'Whatever you have in equals will be considered as state value.
Updating the state
Keep watching the result for 5 seconds.

By the above picture, It is clear that the state can be changed using the ”=” sign.
The above JavaScript code is self-explanatory. We have name variable set as “Karthick” and in setTimeout we’re changing the state to “name is changed”
Quick info: Svelte only understands the change of state only by equals sign.
For example
let fruits = []
fruits.push('apple', 'orange')The above code won’t work.
What you should do is
let fruits = []
fruits = [...fruits, 'mango', 'apple']Event listeners and Reactivity

By above picture, Event listeners can be done with on:“type of the event”
Reactivity
It is quite simple. We used ”$:” which is a feature in JavaScript we rarely use but svelte make use of it well.
Basically we’re changing the state which should be changed if the name state is changed. So we have to give it with dollar sign and colon. It simply means it should change whenever the name state change.
Quick info: $: basically change the state when the assigned value state changes. Powerful reactivity behaviour of svelte.
Another Example with Input
Info: I accidentally named the variable as PreviousCount instead of nextCount. Sorry about that.

In this example, We used on:input event and we changed the value of the name through input using vanilla JS function. On the other hand, When we increment count, We wanted to change nextCount as well so we gave it with $:
Now we know some basics of svelte. Let’s get back to our app
Quick Recap
We created the Jokes.svelte component and created the HTML template.
Input element Reactivity
As we know we can catch the value we type inside the input element by on:input={functionname}
<script>
let number = 0
function changeNumber(e) {
number = e.target.value
}
</script>
<div class="row mt-5">
<div class="container">
<div class="input-group mb-3">
<input
type="number"
class="form-control"
on:input="{changeNumber}"
placeholder="Enter the number of jokes you want"
/>
</div>
<div class="row justify-content-center">
<div>
<button class="btn btn-primary">Get Jokes</button>
</div>
</div>
</div>
</div>
<div class="row mb-5 mt-3 justify-content-center">
<div class="card" style="width: 18rem;">
<div class="card-header">Jokes</div>
<ul class="list-group list-group-flush"></ul>
</div>
</div>The above code will get the number we type inside the input and put in number state.
However, We have very short syntax for doing this
bind is available in svelte which helps to bind what we want with the state.
Look at the syntax here
<input
type="number"
class="form-control"
bind:value="{number}"
placeholder="Enter the number of jokes you want"
/>From the above code, We binded the value of input with number state. value in bind:value is html property of input elements.
<input type="number" class="form-control" value="1" />Now our Jokes.svelte will look like this
<script>
let number = 0
</script><div class="row mt-5">
<div class="container">
<div class="input-group mb-3">
<input
type="number"
class="form-control"
bind:value="{number}"
placeholder="Enter the number of jokes you want"
/>
</div>
<div class="row justify-content-center">
<div>
<button class="btn btn-primary">Get Jokes</button>
</div>
</div>
</div>
</div>
<div class="row mb-5 mt-3 justify-content-center">
<div class="card" style="width: 18rem;">
<div class="card-header">Jokes</div>
<ul class="list-group list-group-flush"></ul>
</div>
</div>
Now let’s make the button work
<script>
function getJokes() {}
</script>
<div>
<button on:click="{getJokes}" class="btn btn-primary">Get Jokes</button>
</div>The above code is self-explanatory right?. We added on click listener to the button which calls the getJokes function.
We’re going to fetch random jokes from chuck Norris api. Check out the api.
For API call we gonna use axios. Run the following command in terminal to install axios.
npm install axiosLet’s make our getJokes function into async function. Why?
Axios returns a promise, To resolve and to get the results, We’re doing that way. Sure enough, you can do that by .then without async function but I personally like async, await pattern.
First, We will import the axios on top.
Now we have
import axios from 'axios'
let number = 0
async function getJokes() {}In api you cannot 0 jokes. so we have to send a through an alert message when the number is ) or undefined. Let’s add them.
import axios from 'axios'
let number = 0
async function getJokes() {
if (number === 0 || number === undefined) {
alert('please enter a number')
}
}Your own Task: Please add the logic for negative numbers as well.
Now let’s create the variable called Jokes as an array and call the api.
<script>
import axios from "axios"; let jokes = [];
let number = 0;
async function getJokes() {
if (number === 0 || number === undefined) {
alert("please enter a number");
} else {
const data = await axios.get(
`http://api.icndb.com/jokes/random/${number}`
);
jokes = data.data.value;
}
}
</script>
Whenever we type the number input it will be stored in number state. When we click the button it will call api using axios and return the results.
data.data.value is purely coming from axios api call results. It will return an array of jokes based on the number we have provided and set it to the jokes state during every api call.
Your own task: Optimize the code to catch errors if api call failed.
That’s it!. We’re done.
each in svelte
To show the results what we have to do is, e can use each loop inside the template
Inside ul tag
<ul class="list-group list-group-flush">
{#each jokes as joke, index}
<li class="list-group-item">
<b>{index + 1}</b>
{joke.joke}
</li>
{/each}
</ul>#each should be closed by /each. Don’t forget.
The index will simply return the index of the array. we showed the index number in our html.
Since the index starts from zero, We added +1 for the index to start from number 1.
joke.joke is simply the jokes we get from the array.
Full Jokes.svelte code will look like this
<script>
import axios from 'axios' let jokes = []
let number = 0
async function getJokes() {
if (number === 0 || number === undefined) {
alert('please enter a number')
} else {
const data = await axios.get(
`http://api.icndb.com/jokes/random/${number}`
)
jokes = data.data.value
}
}
</script><div class="row mt-5">
<div class="container">
<div class="input-group mb-3">
<input
type="number"
class="form-control"
bind:value="{number}"
placeholder="Enter the number of jokes you want"
/>
</div>
<div class="row justify-content-center">
<div>
<button on:click="{getJokes}" class="btn btn-primary">Get Jokes</button>
</div>
</div>
</div>
</div>
<div class="row mb-5 mt-3 justify-content-center">
<div class="card" style="width: 18rem;">
<div class="card-header">Jokes</div>
<ul class="list-group list-group-flush">
{#each jokes as joke, index}
<li class="list-group-item">
<b>{index + 1}</b>
{joke.joke}
</li>
{/each}
</ul>
</div>
</div>
Bonus: If else statements

The above code is self-explanatory. You can write conditions in svelte like above.
I think that’s it for this tutorial.
I’ll come up with something advanced next time.
Thank you 🙏
Happy coding 😆
