Directus

directus.iocontributed by Samuele Ongaro

YES

Replaceable in one session with an AI coding agent.

A headless CMS and admin panel that wraps a SQL database you already own, generating a REST and GraphQL API and an editing interface from the existing schema.

Promptfree, for everyone, and the only version there is
Build me the admin and API layer I actually need instead of a hosted Directus: an editing interface over my existing SQL database, with permissions enforced at the API and a revision per record.

Read this first: the product you are replacing is open source and self-hosting it is a real answer, particularly because generating an admin panel from an arbitrary schema is genuinely a lot of work. Build this when the schema is yours and stable — a generated interface over ten known tables is an afternoon each, and it will fit your data better than a generic one ever does.

STACK
- Node 20+ with Fastify, server-rendered HTML with a little vanilla JS
- Your existing database through its own driver; SQLite through better-sqlite3 for this layer's own state
- No client-side framework
- Caddy in front

THE DATA MODEL, MEANING THIS LAYER'S OWN
- collections: id, table_name, label, singular, icon, sort_field, default_sort, is_hidden
- fields: id, collection_id, column_name, label, kind, interface, options_json, position, is_readonly, is_required, validation_json, hidden_in_list
- relations: id, from_collection, from_field, to_collection, kind — one-to-many, many-to-one, many-to-many with its join table
- roles, users, permissions: role_id, collection, action, fields_json, filter_json — action is read, create, update or delete, and filter_json is a predicate joined into every query for that role
- revisions: id, collection, record_id, actor_id, action, before_json, after_json, at — append-only, enforced by a trigger
- activity: id, actor_id, action, collection, record_id, ip_hash, at
- files: id, path, sha256, mime, bytes, width, height, title, alt, folder_id, uploaded_by, created_at
- The configuration is introspected from the database on first run and then stored, so a column rename is a deliberate edit rather than a silent break

INTROSPECTION
- Read the schema: tables, columns, types, nullability, defaults, primary and foreign keys, unique constraints, check constraints
- Map each column type to a default interface — text, number, boolean, date, select from an enum, relation from a foreign key
- Every mapping is overridable and the override is stored. Guessing is a starting point, not an answer
- Detect a change in the underlying schema on boot and report it rather than adapting silently

PERMISSIONS, ENFORCED WHERE IT MATTERS
- At the API layer, not in the interface. The interface hides what a role cannot do; the API refuses it
- Per collection, per action, per field — a role can read a record but not its salary column, and that column is absent from the response rather than blanked in the browser
- Row filters as predicates: a regional manager sees rows where region matches their own, expressed once and joined into every query for that role
- Default deny. A new table is invisible until permission is granted
- A page generated from the permissions table showing exactly what each role can do

THE ADMIN INTERFACE
- List: filters per field type, sort, pagination with a hard row limit, and a column set per role
- Detail: fields in configured groups, related records inline, and the revision history beside them
- Interfaces per type: plain text, rich text as Markdown, a code editor, date and time with a zone, a select, a many-to-one picker with search, a many-to-many list with add and remove, a file picker, a map if there are coordinates
- Validation from the database's own constraints plus whatever is configured, applied on the server first
- Keyboard navigation for the list, and it works on a phone
- Dark and light

REVISIONS
- Every write records before and after values, the actor and the time
- Revert a record to any earlier revision, which itself writes a new revision — history is never rewritten
- A diff view between two revisions
- This is the feature people name when asked why they use the product, and it is thirty lines plus a trigger

THE API
- REST per collection: list with filtering, field selection, relation expansion, sorting and pagination
- Filters expressed in a small, explicitly parsed query language. Never anything that reaches the database as text a caller supplied
- Tokens with role scopes; the same permission code path as the interface, not a parallel one
- Webhooks on create, update and delete, signed and retried with backoff
- A statement timeout and a row cap on everything

FILES
- Uploads streamed to disk, type from content, stored by hash outside the web root
- Image transforms on demand with signed parameters and a cached result
- Deletion is real, including derivatives, and is refused while a record still references the file

OPERATIONS
- .env: DATABASE_URL, DATABASE_PATH, STORAGE_PATH, BASE_URL, SESSION_SECRET, OIDC_*, HASH_SALT
- Migrations for this layer's own tables on boot, each once
- Nightly backup of both databases and the file store, restore script
- Health endpoint that touches both databases

WHAT MATTERS MOST
Field-level permissions and revisions. Build the permission check into the single query path before any screen exists, and confirm a forbidden field is absent from the JSON rather than hidden in the page. An admin panel is a standing door into the whole database, and every shortcut taken here is a shortcut somebody else eventually walks through.

Give me the repository, migrations, .env.example, an introspection run against a seed schema, and a README with deploy steps behind Caddy.

What you lose

  • A complete admin interface generated from any SQL schema, with relations, file handling and revisions
  • Granular role and permission rules enforced at the API layer rather than in your code
  • A revision history per record, which is a lot of plumbing to reproduce

If you would rather not build

  • Django admin, if the stack allows it

What it costs

read from their page 15 Aug 2026

PlanBilled monthlyBilled yearlyLast read
—$99/mo—15 Aug 2026

Their pricing page is where these came from. Seeing a different price? Tell us.

The escape hatch

open source · no votes, no paid placement

Directus

$0

The product itself; wraps an existing SQL database.

directus/directusfree · open source

Refine

$0

A React framework for admin panels, if you would rather write it than generate it.

refinedev/refinefree · open source

Why this verdict

our own opinion · changed only by a person

72/100

Verdict yes at 72. Generating an admin from a schema is a genuinely satisfying build; permissions and revisions are the parts to do carefully.

History

tracked since 10 Aug 2026 · nothing is ever overwritten

Interest · last 30 dayspeak 2/day
views01230 Aug4 Sept9 Sept14 Sept19 Sept24 Sept28 Sept
— views— prompt copies none yet— votes none yet

Questions about Directus

answered from the record above

Is Directus free?

No — the plan we track is $99 a month. Directus Cloud at $99/month as an add-on to the free Core tier; the Team plan is $599/month billed monthly, $499 annually. Self-hosting the software is free.

Can you replace Directus by building your own?

YES. Replaceable in one session with an AI coding agent. Replacement score 72 out of 100, build time one session. Read what you lose before you decide.

How much does Directus cost?

$99 a month on Starter — $1,188 a year. Recorded 14 Aug 2026.

What do you lose by replacing Directus?

A complete admin interface generated from any SQL schema, with relations, file handling and revisions; Granular role and permission rules enforced at the API layer rather than in your code; A revision history per record, which is a lot of plumbing to reproduce. If any of those carry weight for you, keep paying.

Is there an open-source alternative to Directus?

Yes: Directus, Refine. The prompt on this page is for when you want it your way instead.

Related entries

same category first, most replaced first

All 16 in No-code apps & databases

Not sending yet

Every week, something stops being worth paying for.

New verdicts, prices that moved, entries added. One email a week. Unsubscribe in one click. Nothing is being sent yet — your address is kept here, and the first issue is the first thing it is used for.

free forever · no tracking pixel · stored here, never passed to anyone

Esc