Create your first EmDash site

On this page

This tutorial creates a Node.js site from the Starter template. The result uses SQLite and local media storage, so you can complete the tutorial without a cloud account.

Prerequisites

Install Node.js 22.16 or later and npm. Check the installed Node.js version before continuing:

node --version

The command must report v22.16.0 or a later version.

Scaffold the site

  1. Create my-emdash-site from the Node.js Starter template:

    npm create emdash@latest my-emdash-site -- --template node:starter --pm npm --yes

    The explicit node:starter choice creates a general-purpose site with Posts and Pages. The scaffolder installs dependencies and writes a generated EMDASH_ENCRYPTION_KEY to the gitignored .env file.

    If dependency installation fails, the project files remain in place. Run the retry command printed by the scaffolder before continuing.

  2. Enter the project directory and start the development server:

    cd my-emdash-site
    npm run dev

    Keep this terminal open. Astro prints the local site URL, normally http://localhost:4321/.

Complete setup

Open http://localhost:4321/_emdash/admin/. A new site redirects to the setup wizard.

  1. Enter a Site Title and optional Tagline. Leave Include sample content selected so the tutorial starts with the template’s Welcome post and About page, then select Continue.

  2. Enter Your Email and an optional Your Name, then select Continue.

  3. Register a passkey when the browser opens its credential prompt. After registration, select Open the dashboard.

The dashboard opens with Posts and Pages in the navigation. The setup wizard has applied the Starter template’s content model and sample content to the local SQLite database.

Publish an edit

  1. Open Posts, then open Welcome.

  2. Change the title to Hello from EmDash, then select Save.

  3. Select Publish changes so the saved draft becomes the version shown to visitors.

  4. Open http://localhost:4321/ in another tab. The home page lists Hello from EmDash.

The Starter template calls getEmDashCollection("posts") when Astro renders the home page. Reloading the page reads the published version from EmDash at runtime.

How the generated site works

The scaffold produces a normal Astro project with EmDash connected in three places.

astro.config.mjs enables server rendering and the Node.js adapter. It also registers React for the admin panel and gives EmDash a SQLite database and a directory for uploaded media. The src/live.config.ts file connects that database-backed content to Astro’s Live Content Collections.

The home page then queries the posts collection. Its query is equivalent to the following part of the generated page:

---
import { getEmDashCollection } from "emdash";

const { entries: posts, cacheHint } = await getEmDashCollection("posts", {
	orderBy: { published_at: "desc" },
});

if (Astro.cache?.enabled) Astro.cache.set(cacheHint);
---

<ul>
	{posts.map((post) => <li>{post.data.title}</li>)}
</ul>

seed/seed.json defines the Posts and Pages collections, their fields, and the sample content that the setup wizard applied. During local development, EmDash reads that model and refreshes emdash-env.d.ts, so your editor can check collection names and fields in query code.

The generated .env supplies the encryption key at runtime. It is separate from the SQLite file that stores the model and content.

Next steps

Read Architecture for how these parts work together. To add EmDash to a site that already exists, follow Add EmDash to an existing Astro project. The Querying content guide covers filters, pagination, drafts, and error handling. When the site is ready to leave your machine, deploy it to Cloudflare Workers or Node.js. The Media library guide explains uploads, media fields, replacement, and deletion.