Skip to content

Create your first EmDash site

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.

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

Terminal window
node --version

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

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

    Terminal window
    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:

    Terminal window
    cd my-emdash-site
    npm run dev

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

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.

  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.

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:

src/pages/index.astro
---
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.

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.