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.
If you already have an Astro site, follow Add EmDash to an existing Astro project instead.
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
-
Start the interactive scaffolder:
npm
npm create emdash@latestpnpm
pnpm create emdash@latestyarn
yarn create emdashbun
bun create emdash@latest -
Choose the following options when prompted:
- Project name:
my-emdash-site - Where will you deploy? Node.js
- Which template? Starter
- Which package manager? Keep the package manager detected from the command in step 1.
- Install dependencies? Yes
These choices create a general-purpose Node.js site with Posts and Pages. The scaffolder also writes a generated
EMDASH_ENCRYPTION_KEYto the gitignored.envfile.If dependency installation fails, the project files remain in place. Run the retry command printed by the scaffolder before continuing.
- Project name:
-
Enter the project directory and start the development server:
npm
cd my-emdash-site npm run devpnpm
cd my-emdash-site pnpm devyarn
cd my-emdash-site yarn devbun
cd my-emdash-site bun devKeep 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.
-
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.
-
Enter Your Email and an optional Your Name, then select Continue.
-
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
-
Open Posts, then open Welcome.
-
Change the title to
Hello from EmDash, then select Save. -
Select Publish changes so the saved draft becomes the version shown to visitors.
-
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.