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 @@ -12,7 +12,7 @@ import { SettingsPage } from "./components/SettingsPage";
import { ReportsPage } from "./components/ReportsPage";
import { StatusWidget } from "./components/StatusWidget";

// Pages keyed by path (must match admin.pages paths)
// Pages keyed by path (trailing slash optional, so /settings and /settings/ both resolve)
export const pages = {
"/settings": SettingsPage,
"/reports": ReportsPage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,9 @@ routes: {
},
"settings/save": {
handler: async (ctx) => {
const input = await ctx.request.json();
// EmDash parses the request body once and exposes it as ctx.input.
// Don't call ctx.request.json() — the body stream is already consumed.
const input = ctx.input as Record<string, unknown>;
for (const [key, value] of Object.entries(input)) {
if (value !== undefined) await ctx.kv.set(`settings:${key}`, value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,16 @@ Block Kit elements are also used for [Portable Text block editing fields](./port
6. Plugin returns new blocks

```typescript
import type { BlockInteraction } from "@emdash-cms/blocks";

routes: {
admin: {
handler: async (ctx) => {
const interaction = await ctx.request.json();
// EmDash parses the request body once and exposes it as ctx.input;
// read it directly rather than ctx.request.json() (the body is consumed).
// BlockInteraction is the discriminated union of page_load,
// block_action, and form_submit payloads.
const interaction = ctx.input as BlockInteraction;

if (interaction.type === "page_load") {
return {
Expand Down
17 changes: 10 additions & 7 deletions blog-cloudflare/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,26 @@ 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.
Single typeface: **Inter** on `--font-body`, used for everything including headings (`--font-heading` defaults to the body face; 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 (`--font-weight-heading` 600, `--font-weight-display` 700 for h1/page titles).

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 brand colour is `#0066cc` (`--color-brand`) -- 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`.
Design tokens live in `src/styles/tokens.css` with their default values. To restyle the site, override tokens in `src/styles/theme.css` -- declarations there are unlayered, so they always beat the `@layer base` defaults. Don't edit `tokens.css` or `Base.astro` for visual changes.

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.
Colours are defined with `light-dark(<light>, <dark>)`, so each token carries both modes. Overriding with a plain colour changes light and dark at once; use `light-dark()` in the override to keep them distinct. There is no separate dark palette to maintain.

CSS variables worth knowing:
Webfonts are configured in `astro.config.mjs` under `fonts:`. To swap the body face, change the `name:` for the entry bound to `cssVariable: "--font-body"`. 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. To give headings their own face (or use a system font) without touching the font pipeline, override `--font-heading` or `--font-body` in `theme.css`.

- `--color-accent`, `--color-accent-hover`, `--color-on-accent`, `--color-accent-ring`
CSS variables worth knowing (see `tokens.css` for the full list):

- `--color-brand`, `--color-brand-hover`, `--color-on-brand`, `--color-brand-ring`
- `--color-bg`, `--color-bg-subtle`, `--color-surface`, `--color-text`, `--color-text-secondary`, `--color-muted`, `--color-border`, `--color-border-subtle`
- `--font-sans`, `--font-mono`
- `--font-body`, `--font-heading`, `--font-mono`
- `--font-weight-heading` (600) / `--font-weight-display` (700) -- heading weights; lower them if you switch to a serif
- `--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
Expand Down
2 changes: 1 addition & 1 deletion blog-cloudflare/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default defineConfig({
{
provider: fontProviders.google(),
name: "Inter",
cssVariable: "--font-sans",
cssVariable: "--font-body",
weights: [400, 500, 600, 700],
fallbacks: ["sans-serif"],
},
Expand Down
4 changes: 2 additions & 2 deletions blog-cloudflare/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
"dependencies": {
"@astrojs/cloudflare": "^14.0.0",
"@astrojs/react": "^6.0.0",
"@emdash-cms/cloudflare": "^0.27.0",
"@emdash-cms/cloudflare": "^0.28.1",
"@emdash-cms/plugin-forms": "^0.2.4",
"@emdash-cms/plugin-webhook-notifier": "^0.2.0",
"astro": "^7.0.0",
"emdash": "^0.27.0",
"emdash": "^0.28.1",
"react": "19.2.4",
"react-dom": "19.2.4"
},
Expand Down
6 changes: 3 additions & 3 deletions blog-cloudflare/src/components/PostCard.astro
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,15 @@ const formattedDate = date

.card-title {
font-size: var(--font-size-xl);
font-weight: 600;
font-weight: var(--font-weight-heading);
line-height: var(--leading-snug);
letter-spacing: var(--tracking-snug);
margin-bottom: var(--spacing-2);
transition: color var(--transition-fast);
}

.card-link:hover .card-title {
color: var(--color-accent);
color: var(--color-brand);
}

.card-excerpt {
Expand Down Expand Up @@ -256,7 +256,7 @@ const formattedDate = date
}

.byline-more:focus-visible {
outline: 2px solid var(--color-accent);
outline: 2px solid var(--color-brand);
}

.byline-more[data-tooltip]:hover::after,
Expand Down
Loading
Loading