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
-
Create
my-emdash-sitefrom the Node.js Starter template:npm create emdash@latest my-emdash-site -- --template node:starter --pm npm --yesThe explicit
node:starterchoice creates a general-purpose site with Posts and Pages. The scaffolder installs dependencies and writes a generatedEMDASH_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.
-
Enter the project directory and start the development server:
cd my-emdash-site npm run 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.