directus/directus

The flexible backend for all your projects 🐰 Turn your DB into a headless CMS, admin panels, or apps with a custom UI, instant APIs, auth & more.

34,853 stars TypeScript 7 components

13 hidden assumptions · 7-stage pipeline · 7 components

Like any codebase, this fullstack makes assumptions it never checks — most are routine. The ones worth your attention are below.

Turns any SQL database into a headless CMS with instant REST/GraphQL APIs and web dashboard

Data flows through Directus in multiple paths: (1) Database schema is introspected to auto-generate APIs, (2) Admin users interact through Vue.js interface which makes API calls to modify data, (3) External applications use SDK or direct HTTP calls to access REST/GraphQL endpoints. The system maintains real-time synchronization between database changes and all connected clients through WebSocket connections.

Under the hood, the system uses 4 feedback loops, 4 data pools, 6 control points to manage its runtime behavior.

A 7-component fullstack. 2722 files analyzed. Data flows through 7 distinct pipeline stages.

Hidden Assumptions

Most of what this code assumes is routine. These 3 are the ones most likely to cause trouble here. The rest are minor; they're under "Show everything".

Worth your attention first

If the api/cli module is missing, incompatible, or expects different arguments, the CLI silently fails with unclear error messages or crashes after showing update check

Worth your attention first

If Node.js version format changes (e.g., 'v22.0.0' or '22.0.0-rc1'), +nodeVersion.split('.')[0] could return NaN, causing silent version check bypass and potential runtime failures

Worth your attention first

Changing primaryKey types (e.g., '123' to 123) can cause the useItem composable to not reload data, leaving stale item data in the interface while edits apply to the wrong record

Show everything (10 more)
Scale

Query URLs longer than 8192 characters will cause HTTP 414/431 errors, and the SEARCH method fallback will always be available and accepted by the server

If this fails: If the server doesn't support SEARCH method or has different URL length limits (some proxies limit to 2048), the automatic fallback fails and complex queries become impossible to execute

app/src/composables/use-item/index.ts:MAX_QUERY_URL_LENGTH
Environment

The @ai-sdk/devtools package will be available in the node_modules when AI_DEVTOOLS_ENABLED=true, and localhost:4983 will always be available for the DevTools server

If this fails: If the DevTools package is missing or localhost:4983 is in use, AI debugging fails silently with just a warning, potentially blocking AI development workflow

api/src/ai/devtools/index.ts:doDevToolsInit
Temporal

The devToolsInitPromise will complete before any AI operations need the middleware, and multiple concurrent calls to initAIDevTools won't create race conditions

If this fails: If AI operations start before initialization completes, they proceed without debugging middleware, making debugging intermittent and unreliable during system startup

api/src/ai/devtools/index.ts:initAIDevTools
Contract

The layout.setup function will return a valid Vue composition API object and won't throw exceptions during component initialization

If this fails: If a layout's setup function throws errors or returns invalid objects, the entire layout system crashes with cryptic Vue errors rather than graceful degradation

packages/composables/src/use-layout.ts:createLayoutWrapper
Contract

All components using createLayoutWrapper will only emit updates for properties that are in WRITABLE_PROPS array ['selection', 'layoutOptions', 'layoutQuery']

If this fails: If a layout tries to update non-writable props, the emit will be ignored silently, causing UI state to become inconsistent with component internal state

packages/composables/src/use-layout.ts:isWritableProp
Environment

The inquirer.prompt() will always resolve with all required properties (type, name, language, install) and EXTENSION_TYPES/EXTENSION_LANGUAGES constants are properly defined

If this fails: If inquirer is interrupted or constants are undefined, the create() function receives malformed parameters, causing extension scaffolding to fail with unclear errors

packages/create-directus-extension/lib/index.js:run
Resource

The target directory has write permissions, sufficient disk space for Directus installation, and the filesystem supports creating nested directories (uploads, extensions)

If this fails: Partial installation if disk space runs out mid-installation, or permission errors creating subdirectories after the main directory exists, leaving project in broken state

packages/create-directus-project/lib/index.js:create
Environment

The npm/yarn package manager is available in PATH and can successfully install Directus dependencies without network issues or registry authentication problems

If this fails: If package installation fails due to network, registry, or auth issues, the project folder exists but is non-functional, with no cleanup of partial state

packages/create-directus-project/lib/index.js:create
Scale

Terminal width is sufficient to display the animated bunny spinner (at least numOfSpaces + 2 characters wide) and supports Unicode emoji

If this fails: Spinner animation breaks or displays incorrectly on narrow terminals or systems without Unicode support, potentially causing terminal display corruption

packages/create-directus-project/lib/index.js:bunnyFrames
Domain

Directus will always require exactly Node.js version 22 major, hardcoded as const expectedMajor = 22, and this version requirement won't need updates for patch releases or security updates

If this fails: When Directus adds support for Node.js 24 or requires 22.5+ for security fixes, the version check becomes a false blocker, preventing valid installations

packages/create-directus-project/lib/check-requirements.js:expectedMajor

Open the standalone hidden-assumptions report for directus →

How Data Flows Through the System

Data flows through Directus in multiple paths: (1) Database schema is introspected to auto-generate APIs, (2) Admin users interact through Vue.js interface which makes API calls to modify data, (3) External applications use SDK or direct HTTP calls to access REST/GraphQL endpoints. The system maintains real-time synchronization between database changes and all connected clients through WebSocket connections.

  1. Database introspection — The API server connects to SQL databases using configured drivers, reads table schemas, relationships, and constraints to automatically generate REST and GraphQL endpoints without requiring migrations [Database schema → API endpoints] (config: DB_CLIENT, DB_HOST, DB_PORT +1)
  2. Request authentication — Incoming API requests go through authentication middleware using JWT tokens, session validation, or OAuth providers before accessing protected resources [HTTP request → Authenticated user context] (config: AUTH_PROVIDERS, SECRET, ACCESS_TOKEN_TTL)
  3. Permission validation — The permissions system checks user roles and item-level permissions against requested operations using the configured RBAC rules and conditional filters [Authenticated user context → Permission grants] (config: ADMIN_EMAIL, ADMIN_PASSWORD)
  4. Data transformation — Query results are transformed based on requested fields, applied filters, sorting, and pagination parameters before serialization to JSON or GraphQL response format [Raw database results → API response] (config: QUERY_LIMIT_DEFAULT, MAX_RELATIONAL_DEPTH)
  5. Admin interface interaction — The Vue.js app loads item data through useItem composable, tracks edits in reactive refs, validates changes, and saves back to API with optimistic updates and error handling [User interactions → UsableItem] (config: PUBLIC_URL)
  6. File storage handling — File uploads are processed through configurable storage drivers (local, S3, Azure, GCS) with automatic thumbnail generation and MIME type validation for AI processing [File uploads → Stored files] (config: STORAGE_LOCATIONS, STORAGE_LOCAL_ROOT, STORAGE_LOCAL_DRIVER)
  7. Extension execution — Custom extensions (hooks, interfaces, panels) are loaded and executed at runtime, extending core functionality through the extension registry and SDK [Extension configurations → Extended functionality] (config: EXTENSIONS_PATH, EXTENSIONS_AUTO_RELOAD)

Data Models

The data structures that flow between stages — the contracts that hold the system together.

UsableItem app/src/composables/use-item/index.ts
TypeScript interface with edits: Ref<Item>, hasEdits: ComputedRef<boolean>, item: Ref<T | null>, permissions: UsablePermissions, loading/saving/deleting state flags, and methods for save/remove/archive operations
Created when editing items in admin interface, tracks changes in edits ref, validates and persists to database through API calls
LayoutConfig packages/composables/src/use-layout.ts
Interface with id: string, setup function that returns Vue component configuration, defines how data collections are displayed in different views (table, cards, map, etc.)
Registered as extension, wrapped by createLayoutWrapper to create Vue components with standardized props and emits
Env packages/env/src/constants/defaults.ts
TypeScript interface defining all environment variables with types - includes HOST: string, PORT: number, DATABASE config, storage settings, rate limiting, and feature flags with comprehensive defaults
Loaded at startup from .env files, merged with defaults, used throughout system for configuration
AiAllowedMimeType packages/ai/src/files.ts
Union type of allowed MIME types: 'image/jpeg' | 'image/png' | 'image/gif' | 'image/webp' | 'application/pdf' | 'text/plain' | 'audio/mpeg' | 'audio/wav' | 'video/mp4'
Used to validate file uploads before processing by AI models, ensures only supported formats are accepted
Action packages/constants/src/activity.ts
Enum with values CREATE, UPDATE, DELETE, REVERT, VERSION_SAVE, COMMENT, UPLOAD, LOGIN, LOGOUT, RUN, INSTALL - tracks all user and system activities
Created whenever users or system perform actions, stored in activity log for audit and history tracking

System Behavior

How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.

Data Pools

SQL Database (database)
Primary data store containing user content, system configuration, permissions, and activity logs - abstracted through database drivers
File Storage (file-store)
Configurable file storage backend supporting local filesystem, S3, Azure Blob, GCS with automatic organization and metadata tracking
Extension Registry (registry)
Runtime registry of loaded extensions including hooks, interfaces, panels, and modules with hot-reload capabilities
Environment Configuration (state-store)
Centralized configuration store merging environment variables with defaults, controlling all system behavior

Feedback Loops

Delays

Control Points

Technology Stack

Node.js (runtime)
Runtime environment for the backend API server and CLI tools
Vue.js (framework)
Frontend framework for the admin dashboard interface with reactive data binding
TypeScript (framework)
Primary language providing type safety across packages and API contracts
Express.js (framework)
HTTP server framework handling REST API requests and middleware
GraphQL (framework)
Query language providing flexible data fetching alongside REST APIs
Multiple SQL Databases (database)
Data persistence supporting PostgreSQL, MySQL, SQLite, MariaDB, Oracle, CockroachDB, MS-SQL
Knex.js (library)
SQL query builder providing database abstraction layer
Pinia/Vuex (library)
State management for Vue.js admin interface
WebSocket (library)
Real-time communication between server and clients for live updates
Docker (infra)
Containerization for easy deployment as shown in docker-compose.yml

Key Components

Package Structure

directus (app)
Main CLI entry point that checks for updates and delegates to the API server
api (app)
Core backend server providing REST/GraphQL APIs, authentication, and database abstraction
app (app)
Vue.js admin dashboard for content management with AI integration and item editing
sdk (library)
TypeScript SDK for connecting to Directus APIs with authentication and GraphQL support
ai (library)
AI integration utilities with file type validation and model abstractions
composables (shared)
Vue composables for collection management, layouts, and reactive state
constants (shared)
Shared constants for activities, extensions, fields, and permissions
create-directus-extension (tooling)
CLI tool for scaffolding new Directus extensions with interactive prompts
create-directus-project (tooling)
CLI tool for bootstrapping new Directus projects with directory setup and dependency installation
env (shared)
Environment variable management with type-safe defaults and validation

Explore the interactive analysis

See the full architecture map, data flow, and code patterns visualization.

Analyze on CodeSea

Compare directus

Related Fullstack Repositories

Frequently Asked Questions

What is directus used for?

Turns any SQL database into a headless CMS with instant REST/GraphQL APIs and web dashboard directus/directus is a 7-component fullstack written in TypeScript. Data flows through 7 distinct pipeline stages. The codebase contains 2722 files.

How is directus architected?

directus is organized into 4 architecture layers: Database Abstraction Layer, Admin Interface Layer, Integration Layer, Extension Ecosystem. Data flows through 7 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.

How does data flow through directus?

Data moves through 7 stages: Database introspection → Request authentication → Permission validation → Data transformation → Admin interface interaction → .... Data flows through Directus in multiple paths: (1) Database schema is introspected to auto-generate APIs, (2) Admin users interact through Vue.js interface which makes API calls to modify data, (3) External applications use SDK or direct HTTP calls to access REST/GraphQL endpoints. The system maintains real-time synchronization between database changes and all connected clients through WebSocket connections. This pipeline design reflects a complex multi-stage processing system.

What technologies does directus use?

The core stack includes Node.js (Runtime environment for the backend API server and CLI tools), Vue.js (Frontend framework for the admin dashboard interface with reactive data binding), TypeScript (Primary language providing type safety across packages and API contracts), Express.js (HTTP server framework handling REST API requests and middleware), GraphQL (Query language providing flexible data fetching alongside REST APIs), Multiple SQL Databases (Data persistence supporting PostgreSQL, MySQL, SQLite, MariaDB, Oracle, CockroachDB, MS-SQL), and 4 more. This broad technology surface reflects a mature project with many integration points.

What system dynamics does directus have?

directus exhibits 4 data pools (SQL Database, File Storage), 4 feedback loops, 6 control points, 4 delays. The feedback loops handle polling and cache-invalidation. These runtime behaviors shape how the system responds to load, failures, and configuration changes.

What design patterns does directus use?

5 design patterns detected: Database Abstraction Pattern, Extension Plugin Architecture, Composable State Management, Environment-Driven Configuration, CLI Tool Generation.

How does directus compare to alternatives?

CodeSea has side-by-side architecture comparisons of directus with strapi, payload. These comparisons show tech stack differences, pipeline design, system behavior, and code patterns. See the comparison pages above for detailed analysis.

Analyzed on April 20, 2026 by CodeSea. Written by .