These integration guides are not official documentation and the Strapi Support Team will not provide assistance with them.
Svelte is a modern JavaScript framework that compiles components into efficient JavaScript at build time, unlike React or Vue, which handle heavy lifting in the browser. It uses a reactive programming model where state changes directly update the DOM without the need for a virtual DOM. This results in smaller bundles and faster performance.
Svelte’s assignment-based reactivity updates the DOM automatically when variables change, using the $:
syntax. The framework also supports reactive statements, allowing developers to run code when dependencies change. With scoped styling and minimal code, Svelte enables fast, responsive user experiences.
Integrating Svelte with Strapi creates a powerful stack for modern web development, which combines a flexible back-end with a lightning-fast front-end. Strapi, a leading headless CMS, manages your content through a user-friendly admin interface that is ideal for non-technical users. It delivers content via REST and GraphQL APIs, providing flexibility for your Svelte app.
Svelte’s modular, maintainable components allow you to build reactive user interfaces, while Strapi handles content modeling. Customize your data structure in Strapi, then easily consume it in Svelte for versatile applications. You can start with REST APIs and switch to GraphQL as your app grows, all without altering your back-end setup.
You can use Strapi’s headless CMS to avoid the limitations of traditional CMS architectures and benefit from more control and scalability. Svelte’s efficiency, combined with Strapi’s flexibility, creates a stack that is both developer-friendly and user-oriented. The open-source nature of both tools provides transparency, community support, and extensive customization.
Deployment is straightforward with Strapi Cloud, or you can choose from various deployment options. Strapi’s v5 updates enhance performance and development tools, making it easier to integrate with Svelte.
Choosing to integrate Svelte with Strapi can help you create a clean separation of concerns—Strapi manages your content while Svelte delivers fast, reactive interfaces for a wide range of web applications.
Ready to build something amazing with Svelte and Strapi? Let's walk through how to integrate these powerful tools to create responsive, content-rich applications.
Before we start, make sure you have:
Visual Studio Code with the Svelte extension will make your coding experience much smoother.
Start by creating a fresh SvelteKit project. If you're evaluating different frameworks, this SvelteKit comparison provides insights into how SvelteKit stacks up against alternatives like Next.js.
1
npm create svelte@latest my-svelte-app
1
2
cd my-svelte-app
npm install
1
npm run dev
You're now running SvelteKit! The project structure includes src/routes/
for your pages and src/lib/
for your components and utilities.
Next, let's create your Strapi back-end:
1
npx create-strapi-app@latest my-strapi-api --quickstart
http://localhost:1337/admin
. Let's integrate Svelte with Strapi's API:
src/routes/articles/+page.svelte
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
/** @type {import('./$types').PageLoad} */
export async function load({ fetch }) {
const res = await fetch('http://localhost:1337/api/articles');
const data = await res.json();
return { articles: data.data };
}
</script>
<h1>Articles</h1>
{#each articles as article}
<h2>{article.attributes.title}</h2>
<p>{article.attributes.content}</p>
{/each}
This code fetches articles from Strapi and displays them in your Svelte app. If you're unsure whether to use REST or GraphQL, consider reading about the REST vs GraphQL decision to make an informed choice that suits your project's needs.
For more complex data needs, GraphQL offers precise control:
1
npm install @urql/svelte
src/lib/graphql-client.js
:1
2
3
4
5
import { createClient } from '@urql/svelte';
export const client = createClient({
url: 'http://localhost:1337/graphql',
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<script>
import { client } from '$lib/graphql-client';
import { gql } from '@urql/svelte';
import { onMount } from 'svelte';
let articles = [];
const ARTICLES_QUERY = gql`
query GetArticles {
articles {
data {
id
attributes {
title
content
}
}
}
}
`;
onMount(async () => {
const response = await client.query(ARTICLES_QUERY).toPromise();
articles = response.data.articles.data;
});
</script>
<h1>Articles</h1>
{#each articles as article}
<h2>{article.attributes.title}</h2>
<p>{article.attributes.content}</p>
{/each}
This approach gives you precise control over what data you fetch.
config/middlewares.js
:1
2
3
4
5
6
7
8
module.exports = {
settings: {
cors: {
enabled: true,
origin: ['http://localhost:5173'], // Your SvelteKit dev server
},
},
};
/auth/local
endpoint to log in. .env
files:1
2
# In your SvelteKit project
VITE_STRAPI_URL=http://localhost:1337
import.meta.env.VITE_STRAPI_URL
.Reviewing Strapi Cron best practices can help ensure efficient and reliable background operations if your application requires scheduled tasks.
Follow these steps, and you will have a solid foundation for integrating Svelte with Strapi. As your app grows, remember to optimize queries, implement caching, and follow security best practices.
Let's dive into a real-world example—a blog platform built by integrating Svelte with Strapi. This project shows you practical implementation details and solutions to common challenges.
Our example is a modern blog that uses SvelteKit for the front-end and Strapi as the headless CMS. You can review the complete code on GitHub.
This blog platform features:
Here are some crucial aspects of how integrating Svelte with Strapi works:
load
function to grab blog posts:1
2
3
4
5
export async function load({ fetch }) {
const res = await fetch('http://localhost:1337/api/articles');
const { data } = await res.json();
return { articles: data };
}
1
2
3
4
5
6
export async function load({ params, fetch }) {
const { slug } = params;
const res = await fetch(`http://localhost:1337/api/articles?filters[slug][$eq]=${slug}`);
const { data } = await res.json();
return { article: data[0] };
}
1
2
3
4
5
6
7
8
9
<script>
export let data;
const { article } = data;
</script>
<article>
<h1>{article.attributes.title}</h1>
<div>{@html article.attributes.content}</div>
</article>
The project uses several techniques to maintain performance:
1
$: formattedDate = new Date(article.attributes.publishedAt).toLocaleDateString();
1
const res = await fetch('http://localhost:1337/api/articles?populate=author');
1
2
export const csr = false;
export const prerender = true;
The project addresses several typical integration issues:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// config/middlewares.js
module.exports = [
'strapi::errors',
{
name: 'strapi::security',
config: {
contentSecurityPolicy: {
useDefaults: true,
directives: {
'connect-src': ["'self'", 'http:', 'https:'],
'img-src': ["'self'", 'data:', 'blob:', 'http:', 'https:'],
'media-src': ["'self'", 'data:', 'blob:', 'http:', 'https:'],
},
},
},
},
// ... other middlewares
];
1
2
3
4
5
6
7
8
9
10
11
12
13
async function login(email, password) {
const response = await fetch('http://localhost:1337/api/auth/local', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ identifier: email, password }),
});
const data = await response.json();
if (data.jwt) {
localStorage.setItem('token', data.jwt);
return true;
}
return false;
}
1
2
3
4
5
# .env
PUBLIC_STRAPI_URL=http://localhost:1337
# src/lib/api.js
const BASE_URL = import.meta.env.PUBLIC_STRAPI_URL;
If you have any questions about Strapi 5 or just would like to stop by and say hi, you can join us at Strapi's Discord Open Office Hours, Monday through Friday, from 12:30 pm to 1:30 pm CST: Strapi Discord Open Office Hours.
For more details, visit the Strapi documentation and the Svelte documentation.