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 + SQLitefor fastest local onboarding and lowest operational complexityCloudflare Workers + D1 + R2for 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
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 callssrc/layouts: shared frame concerns (head tags, nav frame, footer shell)src/pages: route composition and data wiring for renderingsrc/lib: business rules, data adapters, and platform-specific glueseed: 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:
- Create with the official scaffold
- Choose one template (blog, marketing, or portfolio)
- Keep generated conventions unless they conflict with a clear team standard
- 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
# 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:
- document runtime choice and migration criteria in the repository
- define content type naming conventions before volume grows
- implement deployment runbook for your chosen platform
Directory structure is architecture, not cosmetics. Locking it early saves weeks later.