Skip to content

EmDash & Astro

EmDash is an open-source, full-stack CMS built specifically for Astro, adding database-backed content, an admin UI, a media library, menus, and taxonomies to your site.

EmDash runs within your Astro project and relies on a database. You can access the admin interface at /_emdash/admin to edit content. Your pages will display it by querying the database using live content collections.

This guide uses the Node.js adapter and a local SQLite database. See the EmDash docs for a list of supported databases.

React powers the EmDash admin interface and is a required dependency. If your project does not use React, install it using the astro add command for your package manager:

Terminal window
npx astro add react

You also need to install the EmDash package:

Terminal window
npm install emdash

Add the emdash() integration to your Astro config file, and configure a database and a media storage backend:

astro.config.mjs
import { defineConfig } from "astro/config";
import node from "@astrojs/node";
import react from "@astrojs/react";
import emdash, { local } from "emdash/astro";
import { sqlite } from "emdash/db";
export default defineConfig({
output: "server",
adapter: node({ mode: "standalone" }),
integrations: [
react(),
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
}),
],
});

Create a src/live.config.ts file so that Astro’s content layer can resolve EmDash content:

src/live.config.ts
import { defineLiveCollection } from "astro:content";
import { emdashLoader } from "emdash/runtime";
export const collections = {
_emdash: defineLiveCollection({ loader: emdashLoader() }),
};

The _emdash collection internally routes to your content types (e.g. posts and pages). Any existing file-based collections in src/content.config.ts keep working alongside it.

EmDash requires you to complete the setup wizard before testing your own pages. Until the setup is complete, there is no published content and queries return empty results.

  1. Start Astro’s dev server to initialize the database and launch the admin UI:

    Terminal window
    npm run dev

    On first run, EmDash creates data.db with its schema and two default collections, pages and posts.

  2. Visit http://localhost:4321/_emdash/admin in the browser. EmDash redirects you to the setup wizard.

  3. In the Site step, enter a site title and an optional tagline.

  4. In the Account step, enter your email address and name. This creates the administrator account.

  5. In the Sign In step, secure your account. Choose Create Passkey to register a passkey with your device’s biometric authentication, security key, or PIN.

  6. Sign in with your new passkey to reach the dashboard.

  1. In the dashboard, click the + Post button.

  2. Add a title and some content. EmDash stores rich text as Portable Text, edited in a block editor. A URL slug is generated from the title and can be edited in the sidebar.

  3. Click Save, then Publish. Only published posts are visible to site visitors.

Query your content with getEmDashCollection() and getEmDashEntry(). Both follow the live collections pattern and return results at request time, so published changes appear without a rebuild.

The following example displays a list of all published post titles, each linking to an individual post page:

src/pages/blog.astro
---
import { getEmDashCollection } from "emdash";
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
---
<ul>
{posts.map((post) => (
<li>
<a href={`/posts/${post.data.slug}`}>{post.data.title}</a>
</li>
))}
</ul>

To display content from an individual post, fetch it by its slug and render the Portable Text content with the <PortableText /> component:

src/pages/posts/[...slug].astro
---
import { getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";
const { slug } = Astro.params;
const { entry: post } = await getEmDashEntry("posts", slug);
if (!post) {
return Astro.redirect("/404");
}
---
<article>
<h1>{post.data.title}</h1>
<PortableText value={post.data.content} />
</article>

See the EmDash querying guide for more information on filtering, pagination, previewing drafts, and visual editing.

EmDash deploys together with your site as a single Astro project. Choose a host that supports your adapter, and provision a production database and media storage.

See the EmDash deployment guide for Node.js and the EmDash deployment guide for Cloudflare for specific instructions. You can also visit Astro’s deployment guides and follow the instructions to deploy with your preferred hosting provider.

More CMS guides

Featured CMS partners

  • CloudCannon

    Git-based CMS built for speed, security, and zero headaches.

All CMS guides

Contribute Community Sponsor