Emdash CMS Project Bootstrap and Directory Layout

A practical architecture guide for starting a new EmDash project with a directory layout that scales cleanly from proof-of-concept to production.

Who this guide is for

Use this guide when you are starting from an empty repository and want a directory structure that can support:

  • editorial content changes every day
  • frontend iteration without breaking CMS assumptions
  • a deployment move from local development to Cloudflare later

The goal is not to produce the most clever folder tree. The goal is to reduce long-term maintenance cost.

Start with the runtime decision first

Before creating files, decide which runtime you are optimizing for in the next 30 to 90 days:

  • Node.js + SQLite for fastest local onboarding and lowest operational complexity
  • Cloudflare Workers + D1 + R2 for production SSR, managed storage, and tighter integration with the EmDash plugin model

If your team is still validating content strategy, start with Node.js first and keep Cloudflare-ready naming from day one. This avoids early platform lock-in while keeping migration straightforward.

your-emdash-site/
├── src/
│   ├── components/            # Reusable UI pieces only
│   ├── layouts/               # Shared page shells
│   ├── pages/                 # Astro routes
│   ├── lib/                   # Domain logic and integrations
│   ├── styles/                # Global and shared style tokens
│   └── live.config.ts         # Live content collection mapping
├── seed/                      # Seed data for bootstrap/demo
├── public/                    # Static assets (favicons, static images)
├── docs/                      # Product docs and editorial content (MDX)
├── astro.config.mjs
├── package.json
├── tsconfig.json
└── emdash-env.d.ts

If your existing project already uses utils/ instead of lib/, keep it for now. Rename only when you can enforce clear ownership rules.

Directory ownership model

The structure works only when ownership is explicit:

  • src/components: presentation-only units; no direct database or storage calls
  • src/layouts: shared frame concerns (head tags, nav frame, footer shell)
  • src/pages: route composition and data wiring for rendering
  • src/lib: business rules, data adapters, and platform-specific glue
  • seed: reproducible baseline content for new environments

This split prevents the most common drift: utility code silently becoming business logic.

Bootstrapping path that avoids rework

For production projects, use this sequence:

  1. Create with the official scaffold
  2. Choose one template (blog, marketing, or portfolio)
  3. Keep generated conventions unless they conflict with a clear team standard
  4. Add only one structural customization at a time

Why this sequence matters: most launch delays are not from missing features. They come from early structural divergence that later breaks docs, scripts, and onboarding.

# Scaffold a new Emdash CMS project
npm create emdash@latest my-emdash-site
cd my-emdash-site

# Install and start local development
npm install
npm run dev

Common anti-patterns to avoid

1) Route-first coding without content model decisions

Building page routes before agreeing on collection and taxonomy shape causes expensive rewrites.

2) Mixing deployment concerns into UI folders

Do not place deployment-specific scripts and config helpers under components or pages. Keep platform concerns in config files and src/lib.

3) Unbounded utils folders

If everything goes into utils, discoverability collapses. Prefer named domains in src/lib such as src/lib/content, src/lib/media, and src/lib/auth.

Definition of done for initial project setup

Treat bootstrap as complete only when all checks pass:

  • local dev server runs without manual patching
  • one sample content flow works end-to-end
  • seed data can be imported in a fresh environment
  • CI build passes with no environment-specific hacks
  • a new contributor can navigate the repository in under ten minutes

What to do next

After structure is stable:

  1. document runtime choice and migration criteria in the repository
  2. define content type naming conventions before volume grows
  3. implement deployment runbook for your chosen platform

Directory structure is architecture, not cosmetics. Locking it early saves weeks later.