EmDash CMS vs Directus: Which One Should You Choose?

EmDash CMS vs Directus: Which One Should You Choose?

Directus and EmDash start from opposite assumptions about where content should live. Directus assumes you already have — or want — a database, and wraps whatever schema exists with an instant API and admin UI, with no proprietary content model imposed on top. EmDash assumes the CMS owns the schema: content types are defined through EmDash, which creates and manages its own structured tables. Neither assumption is wrong; they're suited to genuinely different starting points.

Table of Contents
  1. Quick Answer
  2. The Database-First Philosophy
  3. Pricing
  4. Content Modeling: Whatever Exists vs. What the CMS Defines
  5. Plugin and Extension Security
  6. Where Directus Pulls Ahead
  7. Where EmDash Pulls Ahead
  8. Frequently Asked Questions
  9. Can EmDash be pointed at an existing database like Directus can?
  10. Is Directus a good fit for a brand-new project with no existing data?
  11. Is Directus's free tier really unlimited for small teams?
  12. Which platform has better security for third-party extensions?
  13. The Bottom Line
  14. Sources

Quick Answer

Directus is the stronger choice if you already have an existing database (or a specific schema you need to control directly) and want instant API and admin capabilities layered on top without migrating that data anywhere. EmDash is the stronger choice if you're starting fresh, want the CMS itself to manage schema, migrations, and content structure, and value sandboxed plugin security as a platform default.

The Database-First Philosophy

The database-first philosophy is what sets Directus apart from every other platform. Your database schema is the source of truth, not a proprietary content model. Unlike traditional CMSes, Directus does not impose a schema — it works with whatever database tables you already have.

In practice: point Directus at an existing PostgreSQL, MySQL, SQLite, MariaDB, MS SQL, or Oracle database, and it instantly generates a REST and GraphQL API plus a no-code admin application over your actual tables — no data migration, no remodeling your content to fit the CMS's assumptions. That's a genuinely powerful capability for teams with an existing database (from another application, a legacy system, or a specific compliance requirement around schema ownership) who don't want a CMS dictating how that data is structured.

EmDash works the other way around: content types are defined through EmDash's schema system, and EmDash creates and owns the corresponding database tables. This is a real trade-off, not just a technical detail. Directus's model means your database can be shared with other applications that also read/write it directly, with Directus as one access layer among possibly several. EmDash's model means the CMS is authoritative over its own content structure — cleaner if EmDash is your only interface to that content, more restrictive if you need several systems to write directly to the same tables using their own conventions.

Read also:

Pricing

Directus is free to self-host, with Cloud starting at $25/month for the Standard plan and custom Enterprise pricing for SSO and governance at scale. Notably, organizations under $5M annual revenue and fewer than 50 employees can use Directus completely free, without limits, through an Open Innovation Grant license — a genuinely generous offer for small teams and startups. EmDash's self-hosted model is similarly free at the core, with cost tied to your own infrastructure rather than a vendor tier, though it doesn't have an equivalent named grant program.

Content Modeling: Whatever Exists vs. What the CMS Defines

Directus's own guidance is direct about this: it's the smart choice if you already have a database and want CMS capabilities layered on top, and worth skipping if you're starting from scratch with purely content-first needs. That's a genuinely useful framing for this whole comparison. EmDash is built for the content-first case Directus explicitly says to look elsewhere for — a team starting a new project, defining content types through the CMS itself, without an existing database schema to preserve or wrap.

Plugin and Extension Security

Directus's extensibility runs through custom API extensions and hooks operating directly against your database and application logic — powerful, but with a security model that assumes a reasonably trusted development team, since extensions have direct access to the underlying data layer by design. EmDash's plugin architecture takes a more restrictive default: plugins run sandboxed, with explicit, granted permissions rather than direct database access, which matters more the larger or less-trusted your plugin ecosystem becomes.

Where Directus Pulls Ahead

  • Instant API and admin UI over an existing database — no data migration or remodeling required.
  • Genuine database-first flexibility: your schema stays the source of truth, not a CMS-imposed model.
  • A generous free-usage grant for small organizations and startups under specific revenue/headcount thresholds.
  • Works across multiple SQL database engines (PostgreSQL, MySQL, SQLite, MariaDB, MS SQL, Oracle) rather than one specific dialect.

Where EmDash Pulls Ahead

  • Sandboxed, permission-scoped plugin security as an architectural default rather than direct data-layer access.
  • A content-first model well suited to teams starting fresh, without an existing schema to preserve.
  • A built-in MCP server for AI-native, programmatic content management.
  • Content structure owned and managed by the CMS itself, simpler when EmDash is your only interface to that content.

Frequently Asked Questions

Can EmDash be pointed at an existing database like Directus can?

No — EmDash creates and manages its own schema rather than wrapping an arbitrary existing database. If you specifically need to layer a CMS over data you already have, Directus's database-first model is built for exactly that in a way EmDash currently isn't.

Is Directus a good fit for a brand-new project with no existing data?

It can be, but it's not really playing to its core strength there — Directus's own positioning explicitly frames it as the choice when you already have a database, and suggests content-first platforms for starting from scratch. That's the scenario EmDash is built for.

Is Directus's free tier really unlimited for small teams?

For organizations under $5M in annual revenue and fewer than 50 employees, yes — Directus's Open Innovation Grant license provides free, unlimited self-hosted use under those thresholds, which is a meaningfully generous offer worth factoring into a cost comparison.

Which platform has better security for third-party extensions?

EmDash's sandboxed, permission-scoped plugin model is architecturally more restrictive by default. Directus's extension model assumes more direct trust in your development team, which is a reasonable trade-off for a platform explicitly built around direct database access in the first place.

The Bottom Line

If you already have a database and want instant API and admin capabilities without remodeling your data, Directus's database-first philosophy is purpose-built for exactly that. If you're starting a new project and want the CMS to own and manage a structured content schema — with sandboxed plugin security and AI-native tooling built in — EmDash is the stronger fit. For more on how EmDash approaches structured content generally, see our full EmDash overview.

Sources

Share

Comments

Write a comment

Related Articles

Login Works in Production but Fails on localhost: The secure Cookie Flag Gotcha

July 16, 2026

Login Works in Production but Fails on localhost: The secure Cookie Flag Gotcha

Google Analytics (GA4) Not Tracking Anything and No Console Errors: Check Your CSP First

July 16, 2026

Google Analytics (GA4) Not Tracking Anything and No Console Errors: Check Your CSP First

Native Module Build Fails on Shared Hosting (node-gyp, Old glibc/Python): The .npmrc Fix

July 16, 2026

Native Module Build Fails on Shared Hosting (node-gyp, Old glibc/Python): The .npmrc Fix

Login Works in Production but Fails on localhost: The secure Cookie Flag Gotcha

Login Works in Production but Fails on localhost: The secure Cookie Flag Gotcha

TL;DR — A custom session-cookie login flow appeared to succeed on localhost (the OTP verified, the response looked fine) but every subsequent request to a login-gated page treated the visitor as logged out. Identical code worked fine on the live HTTPS site. The cookie's Secure attribute was hardcoded to true — and per the cookie spec, browsers never store or send a Secure cookie over a plain, non-HTTPS connection.

Table of Contents
  1. Diagnostic
  2. Root cause
  3. Fix
  4. Lessons learned

Diagnostic

Check the actual Set-Cookie response header and the browser's own cookie storage panel — on localhost over http://, the cookie is sent by the server but never actually stored by the browser.

Root cause

// before -- assumes the app is always served over HTTPS
setCookie("session", token, { secure: true, httpOnly: true });
emdashkits.com

A cookie config that quietly assumes "we're always on HTTPS" breaks the instant you test over plain HTTP, which local dev servers commonly are.

Read also:

Fix

// after -- derive secure from the actual request protocol
const isHttps = request.url.startsWith("https://");
setCookie("session", token, { secure: isHttps, httpOnly: true });
emdashkits.com

Lessons learned

  • Any Secure-flagged cookie needs to key off the real request scheme, not an assumption baked in once at cookie-creation time.
  • "Works in production, silently fails in local dev" is a strong signal to check cookie flags before anything else in an auth flow.
  • Check other cookies in the same codebase for the same hardcoded assumption — if one cookie has this bug, sibling cookies set the same way are worth auditing too.
Share
Previous Article

Google Analytics (GA4) Not Tracking Anything and No Console Errors: Check Your CSP First

Comments

Write a comment

Related Articles

Google Analytics (GA4) Not Tracking Anything and No Console Errors: Check Your CSP First

July 16, 2026

Google Analytics (GA4) Not Tracking Anything and No Console Errors: Check Your CSP First

Native Module Build Fails on Shared Hosting (node-gyp, Old glibc/Python): The .npmrc Fix

July 16, 2026

Native Module Build Fails on Shared Hosting (node-gyp, Old glibc/Python): The .npmrc Fix

Uploaded Images Disappear After Every Deploy on Shared Hosting (and Other Reverse-Proxy Gotchas)

July 16, 2026

Uploaded Images Disappear After Every Deploy on Shared Hosting (and Other Reverse-Proxy Gotchas)

Google Analytics (GA4) Not Tracking Anything and No Console Errors: Check Your CSP First

Google Analytics (GA4) Not Tracking Anything and No Console Errors: Check Your CSP First

TL;DR — GA4's gtag.js snippet was installed correctly, the page loaded with no visible JavaScript error, and GA4's real-time report still showed zero activity. The CMS's default Content-Security-Policy had no allowance for analytics domains and no config option to add one — so every request to Google's tracking endpoints was blocked at the browser level before it could fail loudly.

Table of Contents
  1. Diagnostic
  2. Root cause
  3. Lessons learned

Diagnostic

Check the browser's dedicated CSP violation reporting, not the regular console error list — CSP blocks are reported through their own channel, not thrown as normal script errors, so "no console errors" doesn't mean nothing was blocked.

Root cause

The CSP's script-src and connect-src directives had no entry for googletagmanager.com or google-analytics.com, and the CMS exposed no configuration surface to add one — the only way in was patching the CSP directives directly.

// patch-package: add analytics domains to the existing CSP directives
scriptSrc.push("https://www.googletagmanager.com");
connectSrc.push("https://www.google-analytics.com", "https://www.googletagmanager.com");
emdashkits.com
Read also:

Lessons learned

  • "No console errors" is not proof nothing was blocked — CSP violations live in their own reporting surface and are easy to miss if you're only scanning for red error text.
  • Before adding any third-party script tag to a site with a CSP already in place, check the CSP's directives first rather than assuming a silently-empty analytics dashboard means a snippet-installation mistake.
Share
Previous Article

Native Module Build Fails on Shared Hosting (node-gyp, Old glibc/Python): The .npmrc Fix

Next Article

Login Works in Production but Fails on localhost: The secure Cookie Flag Gotcha

Comments

Write a comment

Related Articles

Login Works in Production but Fails on localhost: The secure Cookie Flag Gotcha

July 16, 2026

Login Works in Production but Fails on localhost: The secure Cookie Flag Gotcha

Native Module Build Fails on Shared Hosting (node-gyp, Old glibc/Python): The .npmrc Fix

July 16, 2026

Native Module Build Fails on Shared Hosting (node-gyp, Old glibc/Python): The .npmrc Fix

Uploaded Images Disappear After Every Deploy on Shared Hosting (and Other Reverse-Proxy Gotchas)

July 16, 2026

Uploaded Images Disappear After Every Deploy on Shared Hosting (and Other Reverse-Proxy Gotchas)