Salta ai contenuti

Directus Cheat Sheet

Overview

Directus is an open-source data platform that layers on top of any SQL database to provide a REST and GraphQL API, a no-code admin app, and granular role-based access control. Unlike traditional CMS platforms that create their own database schema, Directus mirrors your existing database structure and lets you manage it through an intuitive interface without altering the underlying tables.

Directus supports PostgreSQL, MySQL, MariaDB, SQLite, MS SQL, OracleDB, and CockroachDB. It provides realtime updates via WebSockets, a flows automation engine for building custom logic without code, file storage with image transformation, and an extensible architecture through custom hooks, endpoints, and modules.

Installation

npm

# Create a new Directus project
npm init directus-project@latest my-project

# Start the server
cd my-project
npx directus start

# Admin app: http://localhost:8055

Docker

# Quick start with Docker
docker run -d \
  --name directus \
  -p 8055:8055 \
  -e SECRET="your-secret-key" \
  -e ADMIN_EMAIL="admin@example.com" \
  -e ADMIN_PASSWORD="password" \
  -e DB_CLIENT="sqlite3" \
  -e DB_FILENAME="/directus/database/data.db" \
  -v directus_data:/directus/database \
  -v directus_uploads:/directus/uploads \
  directus/directus:latest

Docker Compose

version: "3"
services:
  directus:
    image: directus/directus:latest
    ports:
      - "8055:8055"
    volumes:
      - directus_uploads:/directus/uploads
      - directus_extensions:/directus/extensions
    environment:
      SECRET: "your-random-secret"
      ADMIN_EMAIL: "admin@example.com"
      ADMIN_PASSWORD: "password"
      DB_CLIENT: "pg"
      DB_HOST: "db"
      DB_PORT: "5432"
      DB_DATABASE: "directus"
      DB_USER: "directus"
      DB_PASSWORD: "directus"
    depends_on:
      - db
  db:
    image: postgres:16
    environment:
      POSTGRES_DB: directus
      POSTGRES_USER: directus
      POSTGRES_PASSWORD: directus
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:
  directus_uploads:
  directus_extensions:

REST API

CRUD Operations

# List items
curl "http://localhost:8055/items/articles" \
  -H "Authorization: Bearer ACCESS_TOKEN"

# Get single item
curl "http://localhost:8055/items/articles/1" \
  -H "Authorization: Bearer ACCESS_TOKEN"

# Create item
curl -X POST "http://localhost:8055/items/articles" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -d '{"title":"New Article","body":"Content here","status":"published"}'

# Update item
curl -X PATCH "http://localhost:8055/items/articles/1" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -d '{"title":"Updated Title"}'

# Delete item
curl -X DELETE "http://localhost:8055/items/articles/1" \
  -H "Authorization: Bearer ACCESS_TOKEN"

# Bulk create
curl -X POST "http://localhost:8055/items/articles" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -d '[{"title":"Post 1"},{"title":"Post 2"}]'

Filtering and Querying

# Filter with operators
curl "http://localhost:8055/items/articles?filter[status][_eq]=published"

# Deep filter on relations
curl "http://localhost:8055/items/articles?filter[author][name][_contains]=Alice"

# Multiple filters (AND)
curl "http://localhost:8055/items/articles?filter[_and][0][status][_eq]=published&filter[_and][1][date][_gte]=2025-01-01"

# OR filters
curl "http://localhost:8055/items/articles?filter[_or][0][status][_eq]=published&filter[_or][1][status][_eq]=featured"

# Sort, limit, offset
curl "http://localhost:8055/items/articles?sort=-date_created&limit=10&offset=20"

# Select specific fields
curl "http://localhost:8055/items/articles?fields=id,title,slug,author.name"

# Deep populate relations
curl "http://localhost:8055/items/articles?fields=*,author.*,tags.tag_id.*"

# Search
curl "http://localhost:8055/items/articles?search=kubernetes"

# Aggregate
curl "http://localhost:8055/items/articles?aggregate[count]=*&groupBy[]=status"

Filter Operators

OperatorDescription
_eqEqual to
_neqNot equal to
_lt / _lteLess than / less than or equal
_gt / _gteGreater than / greater than or equal
_inIn array
_ninNot in array
_nullIs null
_nnullIs not null
_containsContains substring
_ncontainsDoes not contain
_starts_withStarts with
_ends_withEnds with
_betweenBetween two values
_emptyIs empty
_nemptyIs not empty

JavaScript SDK

import { createDirectus, rest, authentication, readItems, createItem, updateItem, deleteItem, realtime } from "@directus/sdk"

const client = createDirectus("http://localhost:8055")
  .with(authentication())
  .with(rest())

// Authenticate
await client.login("user@example.com", "password")

// Read items
const articles = await client.request(
  readItems("articles", {
    filter: { status: { _eq: "published" } },
    sort: ["-date_created"],
    limit: 10,
    fields: ["id", "title", "slug", { author: ["name", "avatar"] }],
  })
)

// Create item
await client.request(createItem("articles", { title: "New Post", status: "draft" }))

// Update item
await client.request(updateItem("articles", 1, { status: "published" }))

// Delete item
await client.request(deleteItem("articles", 1))

Configuration

Environment Variables

# Database
DB_CLIENT=pg
DB_HOST=localhost
DB_PORT=5432
DB_DATABASE=directus
DB_USER=directus
DB_PASSWORD=password

# Security
SECRET=your-random-secret-key
ACCESS_TOKEN_TTL=15m
REFRESH_TOKEN_TTL=7d

# Storage
STORAGE_LOCATIONS=local,s3
STORAGE_LOCAL_ROOT=./uploads
STORAGE_S3_DRIVER=s3
STORAGE_S3_KEY=your-access-key
STORAGE_S3_SECRET=your-secret-key
STORAGE_S3_BUCKET=your-bucket
STORAGE_S3_REGION=us-east-1

# Email
EMAIL_FROM=noreply@example.com
EMAIL_TRANSPORT=smtp
EMAIL_SMTP_HOST=smtp.example.com
EMAIL_SMTP_PORT=587
EMAIL_SMTP_USER=user
EMAIL_SMTP_PASSWORD=password

# CORS
CORS_ENABLED=true
CORS_ORIGIN=http://localhost:3000

# Cache
CACHE_ENABLED=true
CACHE_STORE=redis
CACHE_REDIS_HOST=127.0.0.1
CACHE_AUTO_PURGE=true

Advanced Usage

Flows (Automation)

Flows are created in the admin app under Settings > Flows. They consist of triggers and operations:

TriggerDescription
Event HookFires on CRUD events (items.create, items.update, etc.)
Schedule (Cron)Runs on a schedule
ActionManual trigger from the admin app
WebhookTriggered by external HTTP request
OperationDescription
Send EmailSend an email notification
Send WebhookMake an HTTP request
Run ScriptExecute custom JavaScript
Create DataInsert a record
Update DataModify a record
Read DataQuery records
ConditionBranch logic based on conditions
Log to ConsoleLog data for debugging

Custom Extensions

# Create a custom endpoint
npx create-directus-extension@latest
# Select "endpoint" type

# Extension structure
extensions/
  endpoints/
    my-endpoint/
      src/
        index.ts
      package.json
// extensions/endpoints/my-endpoint/src/index.ts
import { defineEndpoint } from "@directus/extensions-sdk"

export default defineEndpoint((router, context) => {
  router.get("/", async (req, res) => {
    const { services, getSchema } = context
    const { ItemsService } = services
    const schema = await getSchema()
    const articlesService = new ItemsService("articles", { schema, accountability: req.accountability })
    const articles = await articlesService.readByQuery({ limit: 10 })
    res.json(articles)
  })
})

Realtime (WebSockets)

const client = createDirectus("http://localhost:8055")
  .with(authentication())
  .with(realtime())

await client.connect()

// Subscribe to changes
const { subscription } = await client.subscribe("articles", {
  event: "create",
  query: { fields: ["id", "title", "status"] },
})

for await (const message of subscription) {
  console.log("New article:", message)
}

Troubleshooting

IssueSolution
Admin app blank after upgradeRun npx directus database migrate:latest then restart
Permission denied on APICheck role permissions in Settings > Access Control
Slow queriesEnable caching with CACHE_ENABLED=true; add database indexes
File uploads failingCheck storage configuration and disk permissions
WebSocket disconnectsVerify WEBSOCKETS_ENABLED=true; check proxy WebSocket support
Extension not loadingPlace extensions in the extensions/ directory; restart Directus
Database migration errorsBack up data first; run npx directus database migrate:latest
CORS errorsSet CORS_ORIGIN to your frontend URL; ensure CORS_ENABLED=true
Memory issuesIncrease Node.js heap: NODE_OPTIONS=--max-old-space-size=4096