# EmDash Templates Starter templates for building sites with EmDash CMS. Each template includes a seed file with demo content, so you can see how everything works right away. ## Available Templates ### Blog A clean, minimal blog with posts, pages, categories, tags, and search. **Features:** - Featured post hero on homepage - Post grid with reading time estimates - Category and tag archives - Full-text search - RSS feed - SEO metadata and JSON-LD - Dark/light mode **Pages:** Homepage, post archive, single post, single page, category archive, tag archive, search results, 404 ### Marketing A landing page template for products and services with modular content blocks. **Features:** - Hero, features, testimonials, pricing, and FAQ blocks - Contact form with validation - Portable Text content editing - SEO metadata and JSON-LD - Dark/light mode **Pages:** Homepage, pricing, contact, 404 ### Portfolio A portfolio for showcasing creative work with project pages and tag filtering. **Features:** - Project grid with hover effects - Tag-based filtering on work page - Individual project pages with galleries - Contact page - RSS feed for new projects - SEO metadata and JSON-LD - Dark/light mode **Pages:** Homepage, work listing, single project, about, contact, 404 ## Using a Template Each template has two variants: - **Node.js** (`templates/blog`, `templates/marketing`, `templates/portfolio`) — uses SQLite and local file storage - **Cloudflare** (`templates/blog-cloudflare`, etc.) — uses D1 and R2 ### Quick Start ```bash # Copy the template you want cp -r templates/blog my-site cd my-site # Install dependencies pnpm install # Initialize the database and seed demo content pnpm bootstrap # Start the dev server pnpm dev ``` Open http://localhost:4321 to see your site, and http://localhost:4321/\_emdash/admin for the CMS. ### Template Structure ``` templates/blog/ ├── src/ │ ├── components/ # Astro components │ ├── layouts/ # Page layouts │ ├── pages/ # Route pages │ ├── utils/ # Helper functions │ └── live.config.ts # EmDash content loader ├── seed/ │ └── seed.json # Demo content ├── astro.config.mjs # Astro + EmDash config ├── package.json └── tsconfig.json ``` ## Contributing ### Cloudflare Variants The cloudflare variants share most of their code with the base templates. Only these files differ: - `astro.config.mjs` (cloudflare adapter, D1/R2 storage) - `package.json` (different dependencies) - `wrangler.jsonc` (cloudflare config) Everything else is synced from the base template using a script: ```bash ./scripts/sync-cloudflare-templates.sh ``` **Run this after making changes** to `src/`, `seed/`, `tsconfig.json`, `emdash-env.d.ts`, or `.gitignore` in any base template. It copies those files to the corresponding cloudflare variant. The primary Node demo is also synced from the blog template: ```bash ./scripts/sync-blog-demos.sh ``` This script does two kinds of sync: - full template sync for `templates/blog` -> `demos/simple` - frontend-only sync (keeping runtime-specific files) for: - `templates/blog-cloudflare` -> `demos/cloudflare` - `templates/blog-cloudflare` -> `demos/preview` - `templates/blog` -> `demos/postgres` ### Taking Screenshots Template screenshots live in `assets/templates/{template}/latest/` and are used in the README. To update them after making visual changes: ```bash # Screenshot all templates (starts each dev server automatically) pnpm screenshots # Screenshot specific templates pnpm screenshots blog pnpm screenshots blog marketing ``` The script starts each template's dev server, captures screenshots, then stops the server before moving to the next template. Page definitions are in `templates/screenshots.json`. Each page is captured at desktop (1440x900) and mobile (390x844) in both light and dark mode at 2x resolution. Screenshots are JPEG at 80% quality. Output goes to `assets/templates/{template}/{datetime}/` and is copied to `assets/templates/{template}/latest/`. The dated directories are gitignored; only `latest/` is committed. The README references images from `latest/`. Filenames follow the pattern `{page}-{mode}-{breakpoint}.jpg`, e.g. `homepage-light-desktop.jpg`, `post-dark-mobile.jpg`. To add pages for a template, edit `templates/screenshots.json`. ### Adding a New Template 1. Create the base template in `templates/{name}/` 2. Include a seed file at `seed/seed.json` (or configure the path in `package.json` under `emdash.seed`) 3. Add the `typecheck` script to `package.json` 4. Create the cloudflare variant in `templates/{name}-cloudflare/` with the appropriate adapter config 5. Add the template pair to `scripts/sync-cloudflare-templates.sh` 6. Add the template's pages to `templates/screenshots.json` and run the screenshot script 7. Update the README template gallery ### Seed Files Each template includes a seed file with demo content. The seed file format is documented in the CLI (`emdash seed --help`). Key points: - Use `status: "published"` and include `published_at` for content that should appear on the site - Reference media by URL — the seeder downloads and uploads images automatically - Use the `taxonomies` object for categories and tags - The `emdash.seed` field in `package.json` specifies the seed file location ### Testing Templates Templates are covered by smoke tests that verify: - Seed files parse correctly - Seeds apply without errors - The database passes doctor checks after seeding Run the smoke tests: ```bash pnpm --filter emdash exec vitest run --config vitest.smoke.config.ts ```