diff --git a/potluck/AGENTS.md b/potluck/AGENTS.md deleted file mode 100644 index ad06be7..0000000 --- a/potluck/AGENTS.md +++ /dev/null @@ -1,107 +0,0 @@ -This is an EmDash site -- a CMS built on Astro with a full admin UI. - -## Commands - -```bash -pnpm dev # Start the Astro dev server -npx emdash types # Regenerate TypeScript types from a running site -``` - -The admin UI is at `http://localhost:4321/_emdash/admin`. - -## Key Files - -| File | Purpose | -| ------------------------ | ---------------------------------------------------------------------------------- | -| `astro.config.mjs` | Astro config with `emdash()` integration, database, and storage | -| `src/live.config.ts` | EmDash loader registration (boilerplate -- don't modify) | -| `seed/seed.json` | Schema definition + demo content (collections, fields, taxonomies, menus, widgets) | -| `emdash-env.d.ts` | Generated types for collections (auto-regenerated on dev server start) | -| `src/layouts/Base.astro` | Base layout with EmDash wiring (menus, search, page contributions) | -| `src/pages/` | Astro pages -- all server-rendered | - -## Skills - -Agent skills are in `.agents/skills/`. Load them when working on specific tasks: - -- **building-emdash-site** -- Querying content, rendering Portable Text, schema design, seed files, site features (menus, widgets, search, SEO, comments, bylines). Start here. -- **creating-plugins** -- Building EmDash plugins with hooks, storage, admin UI, API routes, and Portable Text block types. -- **emdash-cli** -- CLI commands for content management, seeding, type generation, and visual editing flow. - -## Documentation - -The EmDash docs are available as an MCP server at `https://docs.emdashcms.com/mcp`. When you need to verify an API, hook, config option, field type, or pattern, call `search_docs` against the live documentation rather than relying on training-data recall. The docs reflect current behaviour; assumptions may not. - -This template ships with `.mcp.json`, `.cursor/mcp.json`, and `.vscode/mcp.json` so Claude Code, Cursor, and VS Code auto-discover the docs server. Other tools (OpenCode, Windsurf, etc.) need a manual one-time setup -- see [docs.emdashcms.com/docs-mcp](https://docs.emdashcms.com/docs-mcp). - -## Rules - -- All content pages must be server-rendered (`output: "server"`). No `getStaticPaths()` for CMS content. -- Image fields are objects (`{ src, alt }`), not strings. Use `` from `"emdash/ui"`. -- `entry.id` is the slug (for URLs). `entry.data.id` is the database ULID (for API calls like `getEntryTerms`). -- When Astro's cache is enabled, pass content-query hints to `Astro.cache.set(cacheHint)`. Use the `WithCacheHint` variants for site settings, menus, taxonomies, and widget areas rendered by cached routes. -- 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-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 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 - -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. - -Colours are defined with `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. - -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`. - -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-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 -- `--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. -- Comments are enabled on posts and rendered on the post detail page. Configure moderation before publishing the site, or remove `commentsEnabled` and the comments UI together. diff --git a/potluck/AGENTS.md b/potluck/AGENTS.md new file mode 120000 index 0000000..eada936 --- /dev/null +++ b/potluck/AGENTS.md @@ -0,0 +1 @@ +CONTRIBUTING.md \ No newline at end of file diff --git a/potluck/CONTRIBUTING.md b/potluck/CONTRIBUTING.md new file mode 100644 index 0000000..75c8376 --- /dev/null +++ b/potluck/CONTRIBUTING.md @@ -0,0 +1,85 @@ +# Contributing to potluck + +potluck started as EmDash's `cloudflare:blog` template +(`pnpm create emdash@latest`); it's part of +[the capsite goal tree](../capsite-checklist.md), where it is the site +that publishes the weekly roundup. + +## How it's put together + +- **Issues** are the `issues` collection + ([seed/issues.json](seed/issues.json)): `title`, `week` (an ISO week, + `2026-W40`), `dek` (one-line summary), `body` (Portable Text). The + slug is the week, lowercased: `/issues/2026-w40`. + [issues-sketch.md](issues-sketch.md) is the dry run behind the three + sample issues: real public bookmarks, editorial lines marked *draft*. +- **Pages:** home and `/issues` list issues + ([src/pages/issues/](src/pages/issues/)); `/tag/` lists issues + by diigo tag; search and `/rss.xml` cover issues. The `posts` + collection and its pages are the template's, still in place. +- **Microformats:** an issue list is an `h-feed` of `h-entry`s; an + issue is an `h-entry` (`p-name`, `dt-published`, `p-summary`, + `e-content`). In issue bodies, + [CiteLink.astro](src/components/CiteLink.astro) marks off-site links + as `h-cite` and `/tag/` links as rel-tag `p-category`. +- **Look:** plain HTML, after kmjn.org's + [Plain HTML with a few bureaucratic gestures](https://www.kmjn.org/notes/modern_plain_html.html): + system fonts (no webfonts), one ~800px column, links in the text + color with a dotted underline. Restyle in + [src/styles/theme.css](src/styles/theme.css), which overrides the + defaults in `tokens.css` (unlayered, so it always wins); don't edit + `tokens.css` or `Base.astro` for visual changes. Colors use + `light-dark(, )`. + +## Seeds + +[seed/seed.json](seed/seed.json) (site settings, menus, widgets, the +template's collections) is applied on the first request to an empty +database. [seed/issues.json](seed/issues.json) is separate: +`pnpm seed:issues` applies it to the local D1 database, which exists +after the dev server's first request. Run it with the dev server +stopped. + +## Checks + +```sh +pnpm typecheck # astro check +pnpm build +``` + +## EmDash rules + +- All content pages are server-rendered (`output: "server"`); no + `getStaticPaths()` for CMS content. +- Image fields are objects (`{ src, alt }`), not strings; render with + `` from `"emdash/ui"`. +- `entry.id` is the slug (for URLs); `entry.data.id` is the database + ULID (for API calls like `getEntryTerms`). +- When Astro's cache is enabled, pass query hints to + `Astro.cache.set(cacheHint)`. +- Taxonomy names in queries match the seed's `"name"` exactly (`"tag"`, + not `"tags"`). +- `npx emdash types` regenerates `emdash-env.d.ts` from a running site + (the dev server also regenerates it on start). + +The EmDash docs are an MCP server at `https://docs.emdashcms.com/mcp` +(wired up in `.mcp.json`, `.cursor/mcp.json`, `.vscode/mcp.json`). +Check them rather than recalling APIs from memory. + +## Deploying + +```sh +pnpm wrangler login +pnpm deploy +``` + +The first deploy provisions the D1 database and R2 bucket named in +[wrangler.jsonc](wrangler.jsonc). See +[Deploy to Cloudflare](https://docs.emdashcms.com/deployment/cloudflare/). + +## For agents + +`AGENTS.md` is a symlink to this file. capsite's +[working rules](../AGENTS.md) apply here too (the dev server is the +user's to start and stop). EmDash skills are in `.agents/skills/`: +`building-emdash-site` (start here), `creating-plugins`, `emdash-cli`. diff --git a/potluck/README.md b/potluck/README.md index c2c5eae..62bcb56 100644 --- a/potluck/README.md +++ b/potluck/README.md @@ -1,68 +1,26 @@ -# EmDash Blog Template (Cloudflare) +# potluck -A clean, minimal blog built with [EmDash](https://github.com/emdash-cms/emdash) and deployed on Cloudflare Workers with D1 and R2. +A weekly zine of what you found elsewhere: each issue is one ISO week +(`/issues/2026-w40`) of bookmarks with a few words of editorial around +them. Everyone brings a dish. The bookmarks come from your own diigo +account, so the web you read becomes something you publish on your own +site ([PESOS](https://indieweb.org/PESOS)). For now issues are put +together by hand. Pulling a week from diigo-cache is next. -[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/emdash-cms/templates/tree/main/blog-cloudflare) +Plain HTML that's easy to read, with +[microformats](https://microformats.org/wiki/h-entry) so feed readers +and IndieWeb tools see each issue as an `h-entry` and each bookmark as +an `h-cite`. It's an [EmDash](https://docs.emdashcms.com/) site, so you +edit issues in a real admin UI, and it runs on Cloudflare Workers. -![Blog template homepage](https://raw.githubusercontent.com/emdash-cms/emdash/main/assets/templates/blog/latest/homepage-light-desktop.jpg) +## Getting started -## What's Included - -- Featured post hero on the homepage -- Post archive with reading time estimates -- Category and tag archives -- Full-text search -- RSS feed -- SEO metadata and JSON-LD -- Dark/light mode - -## Pages - -| Page | Route | -|---|---| -| Homepage | `/` | -| All posts | `/posts` | -| Single post | `/posts/:slug` | -| Category archive | `/category/:slug` | -| Tag archive | `/tag/:slug` | -| Search | `/search` | -| Static pages | `/pages/:slug` | -| 404 | fallback | - -## Screenshots - -| | Desktop | Mobile | -|---|---|---| -| Light | ![homepage light desktop](https://raw.githubusercontent.com/emdash-cms/emdash/main/assets/templates/blog/latest/homepage-light-desktop.jpg) | ![homepage light mobile](https://raw.githubusercontent.com/emdash-cms/emdash/main/assets/templates/blog/latest/homepage-light-mobile.jpg) | -| Dark | ![homepage dark desktop](https://raw.githubusercontent.com/emdash-cms/emdash/main/assets/templates/blog/latest/homepage-dark-desktop.jpg) | ![homepage dark mobile](https://raw.githubusercontent.com/emdash-cms/emdash/main/assets/templates/blog/latest/homepage-dark-mobile.jpg) | - -## Infrastructure - -- **Runtime:** Cloudflare Workers -- **Database:** D1 -- **Storage:** R2 -- **Framework:** Astro with `@astrojs/cloudflare` - -## Local Development - -```bash +```sh pnpm install -pnpm dev +pnpm dev # open http://localhost:4321/_emdash/admin, finish the setup wizard, then Ctrl-C +pnpm seed:issues # three sample issues, W38–W40 of 2026 +pnpm dev # → http://localhost:4321/issues ``` -Open http://localhost:4321/_emdash/admin and complete the setup wizard. EmDash runs database migrations and applies the blog seed during setup. The site is available at http://localhost:4321. - -## Deploying - -```bash -pnpm wrangler login -pnpm deploy -``` - -The first deployment provisions the named D1 database and R2 bucket from `wrangler.jsonc`. See [Deploy to Cloudflare](https://docs.emdashcms.com/deployment/cloudflare/) for production setup, or use the deploy button above. - -## See Also - -- [Node.js variant](../blog) -- same template using SQLite and local file storage -- [All templates](../) -- [EmDash documentation](https://docs.emdashcms.com/) +Next: [CONTRIBUTING](CONTRIBUTING.md) covers how it's put together, +checks, and deploying. diff --git a/potluck/package.json b/potluck/package.json index 6d67a2d..8ff8e18 100644 --- a/potluck/package.json +++ b/potluck/package.json @@ -9,6 +9,7 @@ }, "scripts": { "dev": "astro dev", + "seed:issues": "emdash seed seed/issues.json -d \"$(find .wrangler/state/v3/d1 -name '*.sqlite' ! -name metadata.sqlite)\"", "build": "astro build", "preview": "astro preview", "deploy": "astro build && wrangler deploy", @@ -29,4 +30,4 @@ "wrangler": "^4.125.0" }, "packageManager": "pnpm@11.9.0+sha512.bd682d5d03fe525ef7c9fd6780c6884d1e756ac4c9c9fe00c538782824310dcf90e3ddc4f53835f06dfaebd5085e41855e0bcbb3b60de2ac5bbab89e5036f03b" -} \ No newline at end of file +}