back arrowBack to Blog


Next.js vs React.js vs SvelteKit: Understand the Differences

Next vs React vs Svelte thumbnail

The Svelte framework has gained a lot of momentum and adoption over the past few years. For folks who primarily use React and Next.js, learning a new JS framework can be a daunting task. 

But fear not! In this blog, we’re going to learn the basics of Svelte through comparisons with Next.js and React.js. All frameworks share a lot in common but diverge at critical moments as well.

Here are the topics that will be discussed in this blog:

  1. The basics

  2. SvelteKit vs. Next.js vs. React.js

  3. Pages and API routes

  4. Data fetching

Let’s get started.

The basics

Svelte is a component framework. SvelteKit is built on top of Svelte to provide additional features such as routing, data fetching, and SSR, allowing developers to build multi-page applications. 

In Svelte, components end in .svelte rather than .js/.ts. 

Svelte is also syntactically different from something like React.js. Below, we have two code blocks that do the same thing.


	let count = 0;
	function handleClick() {
		count += 1;

<button on:click={handleClick}>
	clicks: {count}


Svelte is broken down into three parts. similar to how a traditional HTML page works:

  1. The JavaScript is now contained within script tags

  2. HTML

  3. Styles


import { useState } from 'react'
import './global.css'

export default function App() {
	const [count, setCount] = useState(0)

	return (
			onClick={() => setCount(count + 1)}
		> clicks: {count}</button>

File structure

Let’s explore the file structure and draw parallels between Next.js, React.js, and Svelte to understand what's going on. To better understand with a practical example, clone the Svelte sample app repo here.

folder structure
Fig: Folder structure example


Next.js / React.js

/src folder stores the files of our app.

Next.js: /app folder stores the files of our app.

/routes this is where all our routes and pages go.

Next.js: /app folder is where all our routes and pages go.

/lib folder stores components, functions, and images of your app. For example you can have a Header.svelte component and a Box.svelte component. 

Next.js: Next.js does not come with a default lib folder or equivalent. You can create a component folder inside your app folder starting with an underscore to tell Next.js that it’s not a route (_component). 

src/app.d.ts is a type declaration file to store global types. 

Next.js: Next.js does not have an equivalent by default. 

src/app.html is the main HTML page where all Svelte components / page HTML will be rendered. 

React.js: public/index.html is the equivalent in React.js. 

/static is the folder to store any shared static assets such as images or favicons. As an example, you create a new folder in the static folder: static/image. Within a Svelte page, you can reference the image without importing it like this: src=”images/static/myimage.png”

React.js: It’s like storing assets in the public folder in React. 

src/hooks.server.ts is a server hook that processes the request before it hits the server. It’s like middleware. 

Next.js: Equivalent of middleware.ts file.

Here are some other important files that are not in the Svelte sample app but that you will come across in Svelte:


Next.js / React.js 

+page.svelte is the main page file for the route. The plus in front of the file is just the syntax. By default, a page is server-side rendered. 

Next.js: page.tsx is the main page file for the route.

+page.js / +page.ts is something you might see in a page route with a +page.svelte. The +page.js is SSR on the initial page request. If you’re on the page and you click reload, it will handle it all on the server. However, for subsequent requests, navigating between pages will be handled using CSR. 

Next.js: The closest equivalent is getStaticProps but getStaticProps only runs server-side. 

+page.server.js / +page.server.ts is used if you're accessing sensitive data that requires environment variables or if you’re fetching data from a database. This runs only on the server. 

Next.js: Server components are the equivalent. 

+server.js/+server.ts: This is where you store API routes. Like Next.js, the API functions can be HTTP methods like GET, POST, PUT, PATCH, and DELETE.

Next.js: This is like the route.ts file. You have an /api folder with a directory, and a route.ts file with the route function.

Pages and API routes

Svelte and Next.js API and page routes follow identical structures. 

In Next.js, a new page can be created by creating a new directory in the app directory and creating a new file called page.tsx inside of it. In Svelte, you create a new directory within the routes directory and add a +page.svelte inside of it.

Example route



Profile page: /profile



Dashboard page: /dashboard



Here’s a comparison for API routes: 

Example API route



Update database API route



Let’s see this in action in the next section. 

Data fetching 

Let’s say you want to fetch data for a page in Svelte. 

  1. Create a route by creating a directory named “dashboard” in the routes folder.

  2. Within the route, create a +page.svelte.

  3. Lastly, create a +page.js/+page.ts file in the same directory. This is where we fetch the data.

  	export let data

<div class="">


Code block: src/routes/dashboard/+page.svelte

As an example above, we have an imaginary dashboard route with the page. To write any JS in Svelte, we surround our JavaScript in script tags. Then we have our HTML, and lastly our styles. We get the data from out +page.js file and output the data.pageInfo. 

Within the script tags, we export data that we get from our +page.js file below.

export async function load({ fetch }) {
	const fetchData = await fetch("FETCH_URL")
	const res = await fetchData.json()
  return {
    	pageInfo: fetchData

Code block: src/routes/dashboard/+page.js

In our +page.js file, we have a load function which is a special function. The fetch in the load parameters is the Svelte version of the native fetch web API (read more about that here). 

Behind the scenes, Svelte is passing the pageInfo data into our page (+page.svelte), from where we export that data to our page and print it. 

Let’s now see how to create API requests by continuing on with the dashboard page but with a clean slate.

	let response = ""
	async function getSecretMsg () {
		const res = await fetch('/secret')
		const json = await res.json()
		response = JSON.stringify(json)

<button on:click={getSecretMsg}>Get Secret Message:</button>


Code block: src/routes/dashboard/+page.svelte

We have the dashboard route with our page. In our HTML, we have a button with an on:click to call the getSecretMsg function. The async function fetches from our /secret route.

import { json } from '@sveltejs/kit';

export function GET() {
	const secretMsg = "This is the secret msg" 
	return json(secretMsg);

Code block: src/routes/dashboard/secret/+server.js

Within our route, we then create a directory called “secret” that'll be the API route; this is why we fetch the secret in the +page.svelte. It’s a GET request and we return the secrets as a JSON.  

We hope you found these basics helpful! Feel free to refer back to this blog whenever you need a refresher. 


So after going through this entire blog, do you think Svelte is the future? Would you use this framework over React? For me, given how easy the syntax is, I am most likely going to be using this more often than React.js. 

To see an example with Descope and SvelteKit Auth, be sure to star and check out the repository.  If reading this tutorial made you curious to try Descope, sign up for a Free Forever account and join AuthTown, our open user community for developers looking to learn about authentication.