Directus is an open-source headless CMS and backend-as-a-service that wraps any SQL database with instant REST and GraphQL APIs, plus a no-code Data Studio for content management. It's built with Node.js and Vue.js, supports PostgreSQL, MySQL, SQLite, MariaDB, MS-SQL, OracleDB, and CockroachDB, and is fully extensible.
This skill is organized into focused reference files. Read the relevant reference before answering:
TopicReference FileWhen to ReadSDK & API Basicsreferences/sdk-and-api.mdAny question about the JS/TS SDK, REST API, GraphQL, authentication, CRUD operations, filtering, or real-time subscriptionsAstro Integrationreferences/astro-integration.mdIntegrating Directus with Astro — fetching data, dynamic routes, SSG/SSR, live preview, authentication, visual editingTypeScript Patternsreferences/typescript-patterns.mdSchema typing, type generation, advanced generics, type-safe SDK usageFlows & Automationreferences/flows-and-automation.mdDirectus Flows, triggers, operations, scheduled tasks, AI content generation, webhook integrationsExtensionsreferences/extensions.mdCustom endpoints, hooks, interfaces, layouts, displays, modules, operations, panels, themesData Modeling & Adminreferences/data-modeling.mdCollections, fields, relations (M2O, O2M, M2M, M2A), singletons, permissions, roles, file management, environment configTroubleshootingreferences/troubleshooting.mdCommon errors, debugging, CORS issues, Docker problems, migration headaches, performance tips
Always read the relevant reference file before generating code or instructions. For complex questions spanning multiple topics, read multiple references.
These are the most common patterns you'll need. For anything beyond these basics, consult the reference files.
bash
npm install @directus/sdk
typescript
import { createDirectus, rest, staticToken } from '@directus/sdk';
// Define your schema for type safety
interface MySchema {
posts: Post[];
categories: Category[];
global: GlobalSettings; // singleton (not an array)
}
interface Post {
id: number;
title: string;
content: string;
status: string;
category: number | Category;
}
interface Category {
id: number;
name: string;
}
interface GlobalSettings {
site_title: string;
description: string;
}
const client = createDirectus<MySchema>('https://your-directus-url.com')
.with(staticToken('your-token'))
.with(rest());
typescript
import { readItems, readItem, readSingleton } from '@directus/sdk';
// Get all posts
const posts = await client.request(readItems('posts'));
// Get one post with relational data
const post = await client.request(readItem('posts', 1, {
fields: ['*', { category: ['name'] }],
}));
// Get singleton
const global = await client.request(readSingleton('global'));
typescript
// src/lib/directus.ts
import { createDirectus, rest } from '@directus/sdk';
const directus = createDirectus(import.meta.env.DIRECTUS_URL).with(rest());
export default directus;
yaml
# docker-compose.yml
services:
directus:
image: directus/directus:latest
ports:
- 8055:8055
volumes:
- ./database:/directus/database
- ./uploads:/directus/uploads
- ./extensions:/directus/extensions
environment:
SECRET: 'your-random-secret'
ADMIN_EMAIL: 'admin@example.com'
ADMIN_PASSWORD: 'your-password'
DB_CLIENT: 'sqlite3'
DB_FILENAME: '/directus/database/data.db'
WEBSOCKETS_ENABLED: 'true'
.with(rest()), .with(authentication()), .with(realtime()), .with(staticToken()).{DIRECTUS_URL}/assets/{file-id} with optional transformation query params like ?width=500&format=webp.DB_CLIENT, SECRET, CORS_ENABLED, AUTH_PROVIDERS, etc.