Follow along with the code on GitHub: https://github.com/PythoniCode/svelte-dapp-part1
If you’re deciding on a front-end framework, then I can’t recommend SvelteKit enough. Development workflow in SvelteKit is the most simple and straightforward of any framework.
In this post, I will walk through how to start a new dApp project in SvelteKit and why I prefer it to Next.js or Nuxt.
First, I recommend installing Visual Studio Code. I’m not a huge IDE enthusiast, but VS Code is amazing. Furthermore, it has special features that help develop a SvelteKit project.
Next, we will set up our default SvelteKit project. To get started with Svelte in VS Code, press CTRL+SHIFT+X to open the extensions panel. Then, search for Svelte and install the Svelte for VS Code extension.

Then, open up a terminal (either in a new window or with CTRL+SHIFT+ ` ). In the terminal, navigate to a new directory and type npm init svelte@next
to initialize a new SvelteKit project.
If you have not worked with Svelte before I recommend checking out the Tutorial on their website. Otherwise, you can initialize a project with the settings below or feel free to use your own settings.

Congrats! Now we have a default SvelteKit project that we can play around with.
There are two more things to do before moving on…
1 (REQUIRED) Install svelte-web3
2 (OPTIONAL) Install Tailwind CSS
You can find detailed instructions on how to install svelte-web3 here.
Install svelte-web3
First, in terminal type npm i svelte-web3
Then, goto app.html in your project folder and paste the following code anywhere in the <head>
tag.
<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>
And that’s it! You’re ready to use web3 with svelte.
(Optional) Install TailwindCSS
If you want to use the Tailwind CSS library all you have to do is type npx svelte-add@latest tailwindcss
in the terminal. Then type npm install
to finish installing the necessary packages.
Basic Functionality
OK!!! Now our project is finally all setup and we’re ready to start coding our application.
To open our dev environment make sure all packages are installed then type npm run dev
In your project folder, goto index.svelte
in the /routes
subdirectory. Here is where the homepage of your app will be (aka the root directory). If there is not a <script>
tag then add one at the top of the file.
Depending on how you initialized the SvelteKit project, it may already be populated with a ton of starter code. We are going to ignore this for now!
At the top of the <script>
tag in index.svelte
we need to import a few things to make use of the svelte-web3 library.
<script>
// IMPORT THESE
import { browser } from '$app/env';
import { defaultEvmStores, web3, selectedAccount, connected, chainId, chainData } from 'svelte-web3';
</script>
More information on the svelte-web3 imports can be found on their GitHub page.
You may see the following error:
exports is not defined
ReferenceError: exports is not defined
This is a known issue, refresh the page and it should be fine. Otherwise, check the svelte-web3 page for updates.
The first thing we need to do is set a provider. You can read more about web3 providers here. We will use a browser provider like Metamask, so if you don’t have one installed I recommend installing it now.
To set Metamsk as a provider, simply include the following code in the <script> tag.
// This will only render client-side if the browser is available.
if(browser) {
defaultEvmStores.setBrowserProvider();
}
The reason we have the if(browser)
check is because SvelteKit does something called server-side rendering. If this code is running on the server, then we don’t have access to the browser object, thus this code will only be run on the client-end and thus we have access to the browser so we can load a browser provider like Metamask.
Any code that accesses elements that are part of the browser (like window
and document
) needs to be kept client-side by using if(browser)
checks or onMount
functions.
Ok. Now let’s make our web application display blockchain information.
Somewhere below the <script>
tags, add a <div>
element that exposes the chain ID that our current provider is connected to. (I replaced the <Counter/>
component in the Svelte starter project).
<!-- <Counter /> -->
<div>{$chainId}</div>

Yay! Now your SvelteKit project should show the chain ID of your current network somewhere on the page. In the above screenshot you can see the chain ID is 1 since I was connected to Ethereum main net.
The chain ID will dynamically update based on the network you are connected to.

Well that’s pretty simple. What else can we do? Go back to the <div>
that includes the chain ID and add a field to display chain data like so.
<div>{$chainId} {JSON.stringify($chainData)}</div>

Now we have more information about the chain that we can use in our application.
For example, I will include the following information about the chain:
<!-- NOTE: this codeblock includes Tailwind CSS classes -->
<div class="flex flex-col justify-center items-center">
<h1 class="font-bold">{$chainData?.name}</h1>
<p>Native Currency: {$chainData?.nativeCurrency?.name} ({$chainData?.nativeCurrency?.symbol})</p>
</div>
After adding some Tailwind CSS styling and deleting the rest of the body in the example project we get the following result:

Looks nice, but it doesn’t really do anything. So let’s add some features to our new application.
More features
Let’s figure out how to find the balance of an address on the blockchain.
First add a simple form element to our html body in index.svelte
<form class="m-2 p-2">
<input type="text"/>
<button type="submit">Get Balance</button>
<p id="result"></p>
</form>
Now, to make this form usable in Svelte we have to add some code into our <script>
tag.
let address;
let result;
const query_balance = () => {
// Not implemented
}
And then update our HTML like so.
<form on:submit|preventDefault={query_balance} class="m-2 p-2">
<input bind:value={address} type="text"/>
<button type="submit">Get Balance</button>
<div bind:textContent={result} contenteditable="true"></div>
</form>
Our “Get Balance” button still doesn’t do anything, because when it is pressed the query_balance()
function is executed and it is currently empty.
Try adding the following code in the query_balance() function and see what happens when you press “Get Balance”
const query_balance = () => { result = address; }
Yay! Now our “result” is being updated with whatever we input into “address”.
Let’s change the function to return the balance of an address.
const query_balance = async () => {
if($web3.utils.isAddress(address)) result = $web3.utils.fromWei(await $web3.eth.getBalance(address)).toString() + " " + $chainData?.nativeCurrency?.symbol;
else result = "Not a valid address.";
}
Yep! Just two lines of code. To test the function here is a list of the richest Ethereum wallets on the main net: https://www.coincarp.com/currencies/ethereum/richlist/
(Make sure you are connected to Ethereum Mainnet when testing)

BOOM! We can now query the balance of any user on the blockchain we are connected to.
I’m going to wrap up this post here and do a part 2 soon, so hopefully you were able to follow along and enjoyed making a simple dapp in SvelteKit!
Good post Anthony! We recently published our SvelteKit based algorithmic trading website for Web3 and now wrote a post-mortem on the first-year experience on SvelteKit, comparison to other frontend web frameworks and what challenges we faced: https://tradingstrategy.ai/blog/building-cryptocurrency-website