A modern, type-safe boilerplate for building full-stack applications with SvelteKit and Directus. This starter template features automatic type generation, remote functions pattern, async Svelte 5 components, and Tailwind CSS v4.
$derived and await syntaxsrc/
āāā lib/
ā āāā directus/
ā ā āāā directus.ts # Directus client configuration
ā ā āāā generateDirectusTypes.ts # Type generation script
ā āāā remotes/
ā ā āāā directus.remote.ts # Remote functions for data fetching
ā āāā types/
ā āāā directus-schema.ts # Auto-generated Directus types
āāā routes/
āāā +page.svelte # Example page with async data
āāā +layout.svelte # Root layout
Using degit (recommended for starter templates):
npx degit https://github.com/alexvdvalk/sveltekit-directus-starter my-project
cd my-project
npm install
Create a .env file in the root directory:
PUBLIC_DIRECTUS_SERVER=https://your-directus-instance.com
DIRECTUS_TOKEN=your-static-token
Note: You can generate a static token in your Directus admin panel under Settings ā Access Tokens.
npm run generate:types
This will create/update src/lib/types/directus-schema.ts with types matching your Directus schema.
npm run dev
Visit http://localhost:5173 to see your app running!
This starter uses a "remote functions" pattern for server-side data fetching. Remote functions are defined using SvelteKit's query helper and can be directly awaited in components.
Define a remote function (src/lib/remotes/directus.remote.ts):
import { query } from "$app/server";
import getDirectus from "$lib/directus/directus";
import { readUsers } from "@directus/sdk";
export const getUsers = query(async () => {
const directus = getDirectus();
return await directus.request(readUsers());
});
Use in a component (src/routes/+page.svelte):
<script lang="ts">
import { getUsers } from "$lib/remotes/directus.remote";
// Async data with Svelte 5's $derived
const data = $derived(await getUsers());
</script>
{#each data as user}
<p>{user.first_name}</p>
{/each}
The Directus client is configured to:
fetch for optimal performanceExample: Fetching items
import { query } from "$app/server";
import getDirectus from "$lib/directus/directus";
import { readItems } from "@directus/sdk";
export const getPosts = query(async () => {
const directus = getDirectus();
return await directus.request(
readItems('posts', {
fields: ['id', 'title', 'content'],
filter: { status: { _eq: 'published' } }
})
);
});
Whenever you update your Directus schema, regenerate types:
npm run generate:types
This ensures your TypeScript types stay in sync with your CMS structure.
This project uses Tailwind CSS v4 with additional plugins:
@tailwindcss/typography - Beautiful typographic defaults@tailwindcss/forms - Form stylingExample usage in components:
<div class="container mx-auto px-4">
<h1 class="text-4xl font-bold text-gray-900">
Welcome to SvelteKit + Directus
</h1>
</div>
| Command | Description |
|---|---|
npm run dev |
Start development server |
npm run build |
Build for production |
npm run preview |
Preview production build |
npm run check |
Run type checking |
npm run lint |
Lint code with ESLint |
npm run format |
Format code with Prettier |
npm run generate:types |
Generate TypeScript types from Directus |
The Directus client is configured in src/lib/directus/directus.ts. It uses:
Required environment variables:
PUBLIC_DIRECTUS_SERVER - Your Directus instance URLDIRECTUS_TOKEN - Static token for authenticationBuild the application:
npm run build
The build output will be in the build/ directory. Deploy using your preferred adapter:
See SvelteKit adapters documentation for more options.
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - feel free to use this starter for your projects!
Happy coding! š