# 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.

Source: https://emdashcmseverything.com/docs/emdash-cms-project-bootstrap-and-directory-layout/

- Published: 2026-04-08

## 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.

## Recommended baseline directory layout

```text
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.

## Recommended bootstrap commands

```bash
# 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.
