# Emdash Spin Up Demo

> Bring the EmDash monorepo from a fresh clone to a running dev server with the `demos/simple` demo and an authenticated admin session. Use when the user asks to "test/try emdash", "run a demo", "spin up the framework", or after a fresh `git clone` / `git clean -fdx`. Covers the pnpm/corepack setup, the build-before-bootstrap order requirement, the demo bootstrap CLI, the dev-bypass shortcut for instant admin login, and the list of harmless warnings that are expected on first run. Do NOT use for scaffolding a brand-new project outside the monorepo (that's `create-emdash`) or for authoring a new site (that's the `building-emdash-site` skill).

- Skill: `goodluckz/emdash-spin-up-demo` (Agent Skill)
- Install (CLI): `npx skillmds@latest add goodluckz/emdash-spin-up-demo`
- Raw SKILL.md: https://api.skillmd.com/api/skills/goodluckz/emdash-spin-up-demo/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: goodluckz (https://skillmd.com/u/goodluckz)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/goodluckz/emdash-spin-up-demo

---


# Spin up the EmDash simple demo

This is a one-shot recipe: from a fresh checkout of the EmDash monorepo to a logged-in admin in your browser. Total runtime ~30s on warm caches, ~3 minutes on a cold one.

The default monorepo path is `~/Projects/web design/emdash`. If the user is in a different EmDash checkout, treat that as the repo root.

## The recipe

All commands run from the repo root unless noted.

```bash
# 1. Make sure pnpm is on PATH at the version the repo pins
corepack enable
# (No-op if pnpm@10.28.0 is already shimmed.)

# 2. Install workspace deps (~20s on warm caches)
COREPACK_ENABLE_DOWNLOAD_PROMPT=0 pnpm install

# 3. Build all packages — REQUIRED before bootstrap
pnpm build

# 4. Bootstrap the demo's database (creates data.db, applies seed,
#    downloads 7 Unsplash images into demos/simple/uploads/)
cd demos/simple && pnpm bootstrap

# 5. Start the dev server (long-running; run in background)
pnpm dev
```

Once the dev server prints `astro v6.x.x ready in ... ms` and `Local http://localhost:4321/`, the user logs in via:

> **`http://localhost:4321/_emdash/api/setup/dev-bypass?redirect=/_emdash/admin`**

This creates `dev@emdash.local` (role 50 = ADMIN) and sets a session cookie automatically. Works only on a dev server (`import.meta.env.DEV === true`); returns 403 in prod.

## Why each step exists

| Step | Why |
| --- | --- |
| `corepack enable` | The repo pins `"packageManager": "pnpm@10.28.0"` in `package.json`. Corepack ships with Node and is the canonical way to honor that pin. A globally-installed pnpm at a different version will at best print warnings and at worst miscompute the lockfile. |
| `pnpm install` before `pnpm build` | `workspace:*` deps need `node_modules/` linked first. |
| `pnpm build` before `pnpm bootstrap` | `demos/simple/astro.config.mjs` imports `emdash/astro`, `emdash/db`, `emdash/runtime` — these resolve to `packages/core/dist/*.mjs` per `packages/core/package.json` exports. Without `dist/`, the demo can't even start, and `pnpm bootstrap` invokes the `emdash` CLI which lives at `packages/core/dist/cli/index.mjs`. |
| `pnpm bootstrap` (= `emdash init && emdash seed`) | `init` runs migrations against `data.db`. `seed` re-runs migrations (idempotent), then applies `demos/simple/seed/seed.json` and downloads media. Default conflict strategy is `skip`, so re-running is safe. |
| dev-bypass URL | Fastest auth path. EmDash's normal login is passkey-based and can't be automated. The endpoint is dev-only and creates a session in one round-trip. |

## Warnings that are EXPECTED — do not chase them

If the user reports any of these, reassure them. Don't go fix them — they're known and harmless for this demo.

**During `pnpm install`** (40+ lines):
```
WARN  Failed to create bin at .../node_modules/.bin/emdash. ENOENT:
      no such file or directory, open '.../emdash/dist/cli/index.mjs'
```
`dist/` doesn't exist yet on a clean install. The repo's `postbuild` hook (`scripts/relink-bins-if-needed.mjs`) detects missing bins and re-links them after `pnpm build`. Confirm with `ls demos/simple/node_modules/.bin/emdash` after the build.

```
WARN  Ignored build scripts: @parcel/watcher@2.5.4, sharp@0.34.5.
```
Not in the root's `pnpm.onlyBuiltDependencies` allowlist. They ship prebuilt binaries; ignore.

```
WARN  cyclic workspace dependencies:
      packages/auth-atproto, packages/core
```
Known and accepted in this repo.

**During `pnpm dev` startup**:
```
[content] Content config not loaded
```
Live collection loads on demand on first request. Harmless.

```
[hooks] Plugin "audit-log" declares content:beforeSave hook without
        write:content capability — skipping
[hooks] Plugin "audit-log" declares media:afterUpload hook without
        read:media capability — skipping
```
The simple demo wires `auditLogPlugin()` without granting capabilities, so its hooks no-op. The CMS works fine; only the audit log is silent. Don't "fix" this in `astro.config.mjs` — it's the demo's intentional posture.

## End-to-end verification (curl)

After step 5, run these to confirm everything works without opening a browser:

```bash
# Frontend
curl -sI http://localhost:4321/ | head -1                            # → HTTP/1.1 200 OK
curl -s  http://localhost:4321/ | grep -oE '<title>[^<]+</title>'    # → <title>My Blog</title>

# Auth via dev-bypass — creates session, saves cookie
rm -f /tmp/emdash-cookies.txt
curl -sL -c /tmp/emdash-cookies.txt -o /dev/null \
     "http://localhost:4321/_emdash/api/setup/dev-bypass?redirect=/_emdash/admin"

# Admin loads
curl -sI -b /tmp/emdash-cookies.txt http://localhost:4321/_emdash/admin | head -1
# → HTTP/1.1 200 OK

# Whoami
curl -s -b /tmp/emdash-cookies.txt http://localhost:4321/_emdash/api/auth/me
# → {"data":{"email":"dev@emdash.local","role":50,...}}
```

Two parsing gotchas when reading the cookie file:
- The session cookie name is `astro-session` (HttpOnly). EmDash piggybacks on Astro's session, not a custom `emdash_*` cookie.
- In curl's Netscape cookie format, lines starting with `#HttpOnly_` ARE the cookies, not comments. A naive `grep -v '^#'` filter will hide them.

## Expected output of `pnpm bootstrap` on a fresh DB

The seed produces:
- 35 migrations applied
- 2 collections (posts, pages)
- 6 fields, 7 taxonomy terms (3 categories + 4 tags)
- 2 bylines, 1 menu (3 items), 2 widget areas (6 widgets)
- 9 content items (8 posts including 1 draft + 1 page)
- 7 media files downloaded from Unsplash

If counts are noticeably off, the seed file or schema diverged — investigate before continuing.

## Cleanup / reset to clean state

```bash
# From the repo root:
rm -f demos/simple/data.db
rm -rf demos/simple/uploads
# Re-run pnpm bootstrap to repopulate.
```

To stop a backgrounded `pnpm dev`, either kill its task in the harness or:

```bash
pkill -f "astro dev"
```

## Common confusions

- **`templates/blank` is not a runnable demo.** Templates are starter scaffolds meant to be copied into `demos/` (per CONTRIBUTING.md) or used by `create-emdash`. Trying to `pnpm dev` inside `templates/blank` may work but isn't the intended flow.
- **There is no root `pnpm dev` script.** Always `cd demos/<name>` first. The root `package.json` only has build/test/check/format/lint scripts.
- **`create-emdash`** is for scaffolding a new project *outside* the monorepo. It's not part of this recipe — use it when the goal is to start a real site, not when the goal is to try EmDash.
- **The `data.db` and `uploads/` dirs are gitignored** in `demos/simple`. Recreating them via bootstrap is always cheap.

## When this skill does NOT apply

- The user wants to scaffold a new EmDash project from scratch → use `create-emdash` (`pnpm new` from the monorepo root, or `pnpm dlx create-emdash` outside it).
- The user wants to add features, define collections, render content → use the `building-emdash-site` skill.
- The user wants to author a plugin → use the `creating-plugins` skill.
- The user wants to manage content via CLI → use the `emdash-cli` skill.

