These integration guides are not official documentation and the Strapi Support Team will not provide assistance with them.
VitePress is a static site generator built on Vite optimized for speed and performance. It offers a seamless developer experience with features like hot module replacement (HMR) and automatic page preloading. VitePress is well-suited for documentation sites, with simple configuration and easy Vue.js integration.
Thanks to Vite's fast build system, VitePress provides quick build times and efficient rendering. Its minimalist design ensures easy customization, making it ideal for developers who need fast, SEO-friendly documentation and static websites.
Integrating VitePress with Strapi combines the strengths of both platforms. This combination offers developers a powerful solution for fast, dynamic, content-driven websites.
This modular approach provides a solid foundation for modern, content-driven websites, from blogs to comprehensive documentation sites.
Integrating VitePress with Strapi creates a powerful stack, combining dynamic content management with fast static site generation. Here’s how to set up and deploy these technologies for production.
Create separate directories for the VitePress frontend and Strapi backend:
1
2
3
4
5
6
7
8
9
10
project-root/
├── frontend/ # VitePress application
│ ├── docs/
│ ├── .vitepress/
│ └── package.json
├── backend/ # Strapi application
│ ├── src/
│ ├── config/
│ └── package.json
└── README.md
Initialize VitePress in the frontend directory:
1
npm init vitepress
Set up Strapi in the backend directory:
1
npx create-strapi-app@latest .
Create necessary content types and API endpoints through the Strapi admin panel.
Then set up an API client in your VitePress project:
1
2
3
4
5
6
7
8
9
10
11
12
13
// .vitepress/api/strapi.js
import axios from 'axios'
const apiURL = import.meta.env.VITE_API_URL || 'http://localhost:1337/api'
const api = axios.create({
baseURL: apiURL,
headers: {
'Content-Type': 'application/json'
}
})
export default api
Create modular fetch functions for different content types:
1
2
3
4
5
6
7
8
9
10
11
12
// .vitepress/api/articles.js
import api from './strapi'
export const getArticles = async (params = {}) => {
try {
const response = await api.get('/articles', { params })
return response.data
} catch (error) {
console.error('Error fetching articles:', error)
return { data: [] }
}
}
Generate routes based on your Strapi content:
1
2
3
// .vitepress/config.js
import { defineConfig } from 'vitepress'
import { getArticles } from './api/articles'
Use environment variables for API URLs, but do not expose sensitive tokens in client-accessible variables like VITE_API_TOKEN. Store and use tokens securely on the server side.
Implement proper caching strategies:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// .vitepress/api/cache.js
const cache = new Map()
export const getCachedData = async (key, fetchFn, ttl = 60000) => {
const cachedItem = cache.get(key)
if (cachedItem && Date.now() - cachedItem.timestamp < ttl) {
return cachedItem.data
}
const data = await fetchFn()
cache.set(key, {
data,
timestamp: Date.now()
})
return data
}
Configure CORS in Strapi for production by exporting an array with the 'strapi::cors' middleware in 'config/middlewares.js', like this:
1
2
3
4
5
6
7
8
9
10
11
module.exports = [
// ...other middlewares
{
name: 'strapi::cors',
config: {
origin: ['https://your-vitepress-site.com'],
headers: ['Content-Type', 'Authorization', 'Origin'],
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
},
},
];
Set up a webhook in Strapi to trigger VitePress rebuilds:
1
2
3
4
5
6
7
8
9
10
11
12
13
// Strapi webhook configuration
{
"name": "Trigger VitePress rebuild",
"url": "https://api.netlify.com/build_hooks/your-build-hook-id",
"headers": {
"Content-Type": "application/json"
},
"events": [
"entry.create",
"entry.update",
"entry.delete"
]
}
The configuration of webhooks in Strapi lets you automate your static site generation process. This approach is similar to static site generation with Strapi, where changes in content trigger site rebuilds.
Optimize Strapi queries for performance:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const getOptimizedArticles = async () => {
const response = await api.get('/articles', {
params: {
fields: ['title', 'slug', 'publishedAt'],
populate: {
featuredImage: {
fields: ['url', 'alternativeText']
}
},
pagination: {
page: 1,
pageSize: 10
},
sort: ['publishedAt:desc']
}
})
return response.data
}
These steps will help you create a robust integration between VitePress and Strapi that is ready for production. This setup gives you dynamic content management with the speed benefits of static sites.
We recommend updating both platforms, implementing proper error handling, and monitoring your deployment. This will give you a flexible, scalable solution for content-driven websites that can grow with your needs.
Let's walk through a real-world example of how integrating VitePress with Strapi works.
The architecture follows a clean separation of concerns:
This setup allows content editors to work within Strapi while developers focus on frontend development with VitePress.
There are three core elements that drive the integration:
Let's examine key code snippets from a sample GitHub project showing Strapi integration (note: this example uses React, but the concepts apply to VitePress):
For API configuration:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// api.js
import axios from 'axios';
const api = axios.create({
baseURL: 'http://localhost:1337/api',
});
export const fetchArticles = async () => {
try {
const response = await api.get('/articles');
return response.data;
} catch (error) {
console.error('Error fetching articles:', error);
return [];
}
};
This creates a reusable API client for fetching Strapi data. You can use this during the build process in VitePress.
For dynamic route generation, VitePress relies on its file-based routing system and does not support an asynchronous 'buildEnd' hook for injecting routes. Instead, generate route files or use available plugins and build-time scripts to create content dynamically.
For content rendering, create a Vue component:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- ArticleContent.vue -->
<script setup>
import { ref, onMounted } from 'vue'
import { fetchArticles } from '../api'
const articles = ref([])
onMounted(async () => {
const response = await fetchArticles()
articles.value = response.data
})
</script>
<template>
<div>
<article v-for="article in articles" :key="article.id">
<h2>{{ article.attributes.title }}</h2>
<div v-html="article.attributes.content"></div>
</article>
</div>
</template>
You can use this component within VitePress Markdown files:
1
2
3
4
5
# Our Blog
Here are our latest articles:
<ArticleContent />
This setup combines the best of both worlds—content management through Strapi and static site generation through VitePress. Content editors manage content in Strapi's interface, while developers benefit from VitePress for high-performance, static site generation.
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 Vitepress documentation.