Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@ Requires a `wrangler.jsonc` with D1 and R2 bindings:
Register plugins in `astro.config.mjs`:

```javascript
import { auditLogPlugin } from "@emdash-cms/plugin-audit-log";
import auditLog from "@emdash-cms/plugin-audit-log";

emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({ directory: "./uploads", baseUrl: "/_emdash/api/media/file" }),
plugins: [auditLogPlugin()],
plugins: [auditLog],
}),
```

Expand Down
61 changes: 61 additions & 0 deletions blog-cloudflare/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,64 @@ This template ships with `.mcp.json`, `.cursor/mcp.json`, and `.vscode/mcp.json`
- `entry.id` is the slug (for URLs). `entry.data.id` is the database ULID (for API calls like `getEntryTerms`).
- Always call `Astro.cache.set(cacheHint)` on pages that query content.
- Taxonomy names in queries must match the seed's `"name"` field exactly (e.g., `"category"` not `"categories"`).

## This Template

A blog with posts, pages, categories, tags, full-text search, and RSS. Designed for personal writing, technical writing, indie newsletters, and anything where the writing is the product. Editorial-tech aesthetic: confident sans-serif, restrained accent, real article structure with bylines and reading time.

## Pages

| Page | Path | What it shows |
| ----------- | ------------------ | ------------------------------------------------------------------------------------------------------ |
| Home | `/` | Featured post hero (large image + excerpt), latest posts grid |
| All posts | `/posts` | Article count, full post list with excerpts and tag chips |
| Post detail | `/posts/[slug]` | Featured image, title, body, left meta column (authors + date), right TOC + search + categories gutter |
| Search | `/search` | Full-text search UI |
| Page | `/pages/[slug]` | Static page content (Portable Text) |
| Category | `/category/[slug]` | Posts filtered by category |
| Tag | `/tag/[slug]` | Posts filtered by tag |
| RSS | `/rss.xml` | Generated feed |

## Schema

- `posts` collection: `title`, `featured_image`, `content` (Portable Text), `excerpt` (text).
- `pages` collection: `title`, `content` (Portable Text). Used for `/about` etc.
- Taxonomies: `category`, `tag`.
- Single `primary` menu (Home, About, Posts by default).

Site settings have `title` and `tagline` -- both render in the header / footer.

## Visual character

Single typeface: **Inter** on `--font-sans`, used for everything including headings (with tighter letter-spacing on h1/h2). **JetBrains Mono** on `--font-mono` for inline code and code blocks. Body and headings share the same family; weight and size carry the hierarchy.

The accent is `#0066cc` -- used for links, the post-card title hover, and the search input focus ring. There's also a secondary text colour (`--color-text-secondary`) and a `--color-muted` for meta info. Don't add a second accent.

The article layout is the standout feature: a three-column reading view with a left meta column (author bylines, date), centred 680px body column, and a right gutter for search, table of contents, and categories. Don't flatten that into one column on desktop -- the layout signals "this is something to read".

## Customisation

`src/styles/theme.css` is the only file to edit for visual changes. Every CSS variable from `Base.astro` is listed there as a commented default -- uncomment and change to override. The dark mode palette is defined inside `Base.astro` itself; light-mode overrides in `theme.css` won't affect dark mode. To customise dark mode, add `@media (prefers-color-scheme: dark)` and `:root.dark` rules in `theme.css`.

Fonts are configured in `astro.config.mjs` under `fonts:`. To swap the body face, change the `name:` for the entry bound to `cssVariable: "--font-sans"`. Good alternatives: Geist, IBM Plex Sans, Söhne (if you have a licence), Public Sans. If you want a serif-bodied blog, swap to a humanist serif like Source Serif, Crimson Pro, or Lora -- but then also raise `--font-size-base` to `1.0625rem` for readability.

CSS variables worth knowing:

- `--color-accent`, `--color-accent-hover`, `--color-on-accent`, `--color-accent-ring`
- `--color-bg`, `--color-bg-subtle`, `--color-surface`, `--color-text`, `--color-text-secondary`, `--color-muted`, `--color-border`, `--color-border-subtle`
- `--font-sans`, `--font-mono`
- `--tracking-tight` / `--tracking-snug` / `--tracking-wide` / `--tracking-wider` -- letter-spacing tokens used across headings and meta labels
- `--content-width` (680px) -- article body column
- `--wide-width` (1200px) -- max container
- `--gutter-width` (200px) -- right sidebar (TOC) on article pages
- `--meta-col-width` (180px) -- left meta column on article pages
- `--avatar-size-{xs,sm,md,lg}` -- byline avatar sizes at different scales

## What not to do

- Don't add a second accent colour or coloured section backgrounds. The page should be black, white, and one blue.
- Don't replace Inter with a display sans (Bebas, Anton, etc.). Headings rely on weight contrast, not novelty faces.
- Don't collapse the article gutter on desktop -- it's part of the reading experience.
- Don't use stock blog copy ("Welcome to my blog", "Stay tuned for more"). Write a real tagline that says what this blog is about.
- Don't seed the home page with three identical placeholder posts. If you only have one real post, show one real post.
- Don't enable comments without a plan to moderate them. The template doesn't ship a comments system by default for a reason.
4 changes: 2 additions & 2 deletions blog-cloudflare/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import cloudflare from "@astrojs/cloudflare";
import react from "@astrojs/react";
import { d1, r2, sandbox } from "@emdash-cms/cloudflare";
import { formsPlugin } from "@emdash-cms/plugin-forms";
import { webhookNotifierPlugin } from "@emdash-cms/plugin-webhook-notifier";
import webhookNotifier from "@emdash-cms/plugin-webhook-notifier";
import { defineConfig, fontProviders } from "astro/config";
import emdash from "emdash/astro";

Expand All @@ -19,7 +19,7 @@ export default defineConfig({
database: d1({ binding: "DB", session: "auto" }),
storage: r2({ binding: "MEDIA" }),
plugins: [formsPlugin()],
sandboxed: [webhookNotifierPlugin()],
sandboxed: [webhookNotifier],
sandboxRunner: sandbox(),
marketplace: "https://marketplace.emdashcms.com",
}),
Expand Down
13 changes: 7 additions & 6 deletions blog-cloudflare/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,20 @@
"typecheck": "astro check"
},
"dependencies": {
"@astrojs/cloudflare": "^13.1.7",
"@astrojs/cloudflare": "^13.5.3",
"@astrojs/react": "^5.0.0",
"@emdash-cms/cloudflare": "^0.12.0",
"@emdash-cms/cloudflare": "^0.14.0",
"@emdash-cms/plugin-forms": "^0.2.2",
"@emdash-cms/plugin-webhook-notifier": "^0.1.3",
"astro": "^6.0.1",
"emdash": "^0.12.0",
"@emdash-cms/plugin-webhook-notifier": "^0.2.0",
"astro": "^6.3.0",
"emdash": "^0.14.0",
"react": "19.2.4",
"react-dom": "19.2.4"
},
"devDependencies": {
"@astrojs/check": "^0.9.7",
"@cloudflare/workers-types": "^4.20260305.1",
"wrangler": "^4.83.0"
}
},
"packageManager": "pnpm@11.1.3+sha512.c85357fe17ca12dd23dd7071822666dfd7e3cb76fe214e3370b5ea2fb34f2a231185509b63e717f3cd0acb38dd3f8d82bcd5e8172400ae678b70ea4fbed0896d"
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@ Requires a `wrangler.jsonc` with D1 and R2 bindings:
Register plugins in `astro.config.mjs`:

```javascript
import { auditLogPlugin } from "@emdash-cms/plugin-audit-log";
import auditLog from "@emdash-cms/plugin-audit-log";

emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({ directory: "./uploads", baseUrl: "/_emdash/api/media/file" }),
plugins: [auditLogPlugin()],
plugins: [auditLog],
}),
```

Expand Down
61 changes: 61 additions & 0 deletions blog/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,64 @@ This template ships with `.mcp.json`, `.cursor/mcp.json`, and `.vscode/mcp.json`
- `entry.id` is the slug (for URLs). `entry.data.id` is the database ULID (for API calls like `getEntryTerms`).
- Always call `Astro.cache.set(cacheHint)` on pages that query content.
- Taxonomy names in queries must match the seed's `"name"` field exactly (e.g., `"category"` not `"categories"`).

## This Template

A blog with posts, pages, categories, tags, full-text search, and RSS. Designed for personal writing, technical writing, indie newsletters, and anything where the writing is the product. Editorial-tech aesthetic: confident sans-serif, restrained accent, real article structure with bylines and reading time.

## Pages

| Page | Path | What it shows |
| ----------- | ------------------ | ------------------------------------------------------------------------------------------------------ |
| Home | `/` | Featured post hero (large image + excerpt), latest posts grid |
| All posts | `/posts` | Article count, full post list with excerpts and tag chips |
| Post detail | `/posts/[slug]` | Featured image, title, body, left meta column (authors + date), right TOC + search + categories gutter |
| Search | `/search` | Full-text search UI |
| Page | `/pages/[slug]` | Static page content (Portable Text) |
| Category | `/category/[slug]` | Posts filtered by category |
| Tag | `/tag/[slug]` | Posts filtered by tag |
| RSS | `/rss.xml` | Generated feed |

## Schema

- `posts` collection: `title`, `featured_image`, `content` (Portable Text), `excerpt` (text).
- `pages` collection: `title`, `content` (Portable Text). Used for `/about` etc.
- Taxonomies: `category`, `tag`.
- Single `primary` menu (Home, About, Posts by default).

Site settings have `title` and `tagline` -- both render in the header / footer.

## Visual character

Single typeface: **Inter** on `--font-sans`, used for everything including headings (with tighter letter-spacing on h1/h2). **JetBrains Mono** on `--font-mono` for inline code and code blocks. Body and headings share the same family; weight and size carry the hierarchy.

The accent is `#0066cc` -- used for links, the post-card title hover, and the search input focus ring. There's also a secondary text colour (`--color-text-secondary`) and a `--color-muted` for meta info. Don't add a second accent.

The article layout is the standout feature: a three-column reading view with a left meta column (author bylines, date), centred 680px body column, and a right gutter for search, table of contents, and categories. Don't flatten that into one column on desktop -- the layout signals "this is something to read".

## Customisation

`src/styles/theme.css` is the only file to edit for visual changes. Every CSS variable from `Base.astro` is listed there as a commented default -- uncomment and change to override. The dark mode palette is defined inside `Base.astro` itself; light-mode overrides in `theme.css` won't affect dark mode. To customise dark mode, add `@media (prefers-color-scheme: dark)` and `:root.dark` rules in `theme.css`.

Fonts are configured in `astro.config.mjs` under `fonts:`. To swap the body face, change the `name:` for the entry bound to `cssVariable: "--font-sans"`. Good alternatives: Geist, IBM Plex Sans, Söhne (if you have a licence), Public Sans. If you want a serif-bodied blog, swap to a humanist serif like Source Serif, Crimson Pro, or Lora -- but then also raise `--font-size-base` to `1.0625rem` for readability.

CSS variables worth knowing:

- `--color-accent`, `--color-accent-hover`, `--color-on-accent`, `--color-accent-ring`
- `--color-bg`, `--color-bg-subtle`, `--color-surface`, `--color-text`, `--color-text-secondary`, `--color-muted`, `--color-border`, `--color-border-subtle`
- `--font-sans`, `--font-mono`
- `--tracking-tight` / `--tracking-snug` / `--tracking-wide` / `--tracking-wider` -- letter-spacing tokens used across headings and meta labels
- `--content-width` (680px) -- article body column
- `--wide-width` (1200px) -- max container
- `--gutter-width` (200px) -- right sidebar (TOC) on article pages
- `--meta-col-width` (180px) -- left meta column on article pages
- `--avatar-size-{xs,sm,md,lg}` -- byline avatar sizes at different scales

## What not to do

- Don't add a second accent colour or coloured section backgrounds. The page should be black, white, and one blue.
- Don't replace Inter with a display sans (Bebas, Anton, etc.). Headings rely on weight contrast, not novelty faces.
- Don't collapse the article gutter on desktop -- it's part of the reading experience.
- Don't use stock blog copy ("Welcome to my blog", "Stay tuned for more"). Write a real tagline that says what this blog is about.
- Don't seed the home page with three identical placeholder posts. If you only have one real post, show one real post.
- Don't enable comments without a plan to moderate them. The template doesn't ship a comments system by default for a reason.
4 changes: 2 additions & 2 deletions blog/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import node from "@astrojs/node";
import react from "@astrojs/react";
import { auditLogPlugin } from "@emdash-cms/plugin-audit-log";
import auditLog from "@emdash-cms/plugin-audit-log";
import { defineConfig, fontProviders } from "astro/config";
import emdash, { local } from "emdash/astro";
import { sqlite } from "emdash/db";
Expand All @@ -22,7 +22,7 @@ export default defineConfig({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
plugins: [auditLogPlugin()],
plugins: [auditLog],
}),
],
fonts: [
Expand Down
11 changes: 6 additions & 5 deletions blog/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@
"typecheck": "astro check"
},
"dependencies": {
"@astrojs/node": "^10.0.0",
"@astrojs/node": "^10.1.1",
"@astrojs/react": "^5.0.0",
"@emdash-cms/plugin-audit-log": "^0.1.3",
"astro": "^6.0.1",
"@emdash-cms/plugin-audit-log": "^0.2.0",
"astro": "^6.3.0",
"better-sqlite3": "^12.8.0",
"emdash": "^0.12.0",
"emdash": "^0.14.0",
"react": "19.2.4",
"react-dom": "19.2.4"
},
"devDependencies": {
"@astrojs/check": "^0.9.7"
}
},
"packageManager": "pnpm@11.1.3+sha512.c85357fe17ca12dd23dd7071822666dfd7e3cb76fe214e3370b5ea2fb34f2a231185509b63e717f3cd0acb38dd3f8d82bcd5e8172400ae678b70ea4fbed0896d"
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@ Requires a `wrangler.jsonc` with D1 and R2 bindings:
Register plugins in `astro.config.mjs`:

```javascript
import { auditLogPlugin } from "@emdash-cms/plugin-audit-log";
import auditLog from "@emdash-cms/plugin-audit-log";

emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({ directory: "./uploads", baseUrl: "/_emdash/api/media/file" }),
plugins: [auditLogPlugin()],
plugins: [auditLog],
}),
```

Expand Down
Loading
Loading