building-emdash-site
Skill10 starsChanged 31 days agoMITView on GitHub
Build the site-facing parts of an EmDash CMS project on Astro, including schema and seeds, content queries, Portable Text rendering, menus, taxonomies, widgets, and deployment configuration. Use for EmDash site and theme work; use creating-plugins instead when the task is plugin authoring alone.
4 other projects use a version of this, 1 of them edited.
Adopted by
Most recently taken up by
- EngDawood/emdash-claude-skillsword for word, first seen Nov 1, 2026
- emdash-cms/emdashword for word, first seen Oct 8, 2026
- EngDawood/emdash-claude-pluginword for word, first seen Sep 30, 2026
- EngDawood/modern-emdash-cmsedited, first seen Jun 20, 2026
Other versions4 projects use a version of this.
Word for word · 3
- emdash-cms/emdash★ 14k100% same
- EngDawood/emdash-claude-plugin★ 4100% same
- EngDawood/emdash-claude-skills★ 4100% same
Edited · 1
- EngDawood/modern-emdash-cms★ 278% same
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository5 other files it gives its agents.
- creating-pluginsSkill
- emdash-cliSkill
- upgrading-emdashSkill
- wordpress-plugin-to-emdashSkill
- wordpress-theme-to-emdashSkill
The file
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 6 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 18
Taxonomy names must match the seed exactly: If your seed defines "name": "category", you must query getTerm("category", slug) -- not …
- Distinctive: line 26
Every EmDash site has these key files:
- Very specific: line 46
Read references/configuration.md for astro.config.mjs, live.config.ts, deployment targets (Node vs Cloudflare), and type generation.
- Distinctive: line 50
Read references/schema-and-seed.md for collection definitions, field types, taxonomies, menus, widget areas, sections, bylines, and the …
- Distinctive: line 54
Read references/querying-and-rendering.md for content queries, Portable Text rendering, the Image component, visual editing attributes, …
- Distinctive: line 58
Read references/site-features.md for site settings, navigation menus, taxonomies, widget areas, search, SEO meta, comments, and page …
- Very specific: line 62
Write seed/seed.json with collections, fields, taxonomies, menus, widgets, and sample content.
- Distinctive: line 128
Add custom admin pages or dashboard widgets
- Distinctive: line 129
Add reusable behavior or custom Portable Text types (e.g., embedded maps or code playgrounds)
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Building an EmDash Site
EmDash is a CMS built on Astro. It stores schema in the database (not in code), serves content via live content collections, and provides a full admin UI at /_emdash/admin. Sites are standard Astro projects with the emdash integration.
Common Gotchas
These are the things that silently break sites. Know them before you start.
- Image fields are objects, not strings.
post.data.featured_imageis{ id, src, alt }. Writing<img src={post.data.featured_image} />renders[object Object]. Use<Image image={post.data.featured_image} />from"emdash/ui". entry.idvsentry.data.idare different things.entry.idis the slug, prefixed with the locale (en/my-post) for locales whose URLs are prefixed (use in URLs;entry.data.slugis the bare slug).entry.data.idis the database ULID (use forgetEntryTerms,Comments, and other API calls that need the real ID). Mixing them up causes silent empty results.- Taxonomy names must match the seed exactly. If your seed defines
"name": "category", you must querygetTerm("category", slug)-- not"categories". Wrong name = empty results, no error. - Register cache hints when Astro's cache is enabled. Content queries return a
cacheHint; pass it toAstro.cache.set(cacheHint). UsegetSiteSettingsWithCacheHint(),getMenuWithCacheHint(),getTaxonomyTermsWithCacheHint(), andgetWidgetAreaWithCacheHint()when a cached route renders those values. - No
getStaticPathsfor CMS content. EmDash content is dynamic. Pages must be server-rendered (output: "server"inastro.config.mjs).
File Structure
Every EmDash site has these key files:
my-site/
├── astro.config.mjs # Astro config with emdash() integration
├── src/
│ ├── live.config.ts # EmDash loader registration (boilerplate)
│ ├── pages/ # Astro pages (all server-rendered)
│ ├── layouts/ # Layout components
│ └── components/ # Reusable components
├── seed/
│ └── seed.json # Schema + demo content
├── emdash-env.d.ts # Generated types (from `emdash types`)
└── package.jsonWorkflow
1. Configure the project
Read references/configuration.md for astro.config.mjs, live.config.ts, deployment targets (Node vs Cloudflare), and type generation.
2. Design the schema
Read references/schema-and-seed.md for collection definitions, field types, taxonomies, menus, widget areas, sections, bylines, and the complete seed file format.
3. Build the pages
Read references/querying-and-rendering.md for content queries, Portable Text rendering, the Image component, visual editing attributes, caching, and common page patterns (list, detail, taxonomy archive, RSS, search, 404).
4. Wire up site features
Read references/site-features.md for site settings, navigation menus, taxonomies, widget areas, search, SEO meta, comments, and page contributions.
5. Create the seed file
Write seed/seed.json with collections, fields, taxonomies, menus, widgets, and sample content.
6. Run and verify
pnpm dev # Start the Astro dev serverThe runtime runs pending migrations on the first request and, before setup is completed, applies the seed's schema and structure once. Sample content needs an explicit step; see Applying Seeds. The Astro integration generates emdash-env.d.ts when the server starts. The admin UI is at http://localhost:4321/_emdash/admin.
Quick API Cheat Sheet
// Content (entries have .data.byline and .data.bylines eagerly loaded)
import { getEmDashCollection, getEmDashEntry } from "emdash";
const { entries, nextCursor, cacheHint } = await getEmDashCollection("posts", {
limit: 10,
cursor,
orderBy: { published_at: "desc" },
});
const { entry: post, cacheHint: entryCacheHint } = await getEmDashEntry("posts", slug);
// Site features
import {
getSiteSettings,
getSiteSettingsWithCacheHint,
getMenu,
getMenuWithCacheHint,
getTaxonomyTerms,
getTaxonomyTermsWithCacheHint,
getTerm,
getEntryTerms,
getEntriesByTerm,
getWidgetArea,
getWidgetAreaWithCacheHint,
search,
getSection,
getSeoMeta,
} from "emdash";
// Bylines (standalone queries -- usually not needed since entries have bylines attached)
import { getByline, getBylineBySlug } from "emdash";
// UI components
import {
PortableText,
Blocks,
defineBlockComponents,
Image,
WidgetArea,
EmDashHead,
EmDashBodyStart,
EmDashBodyEnd,
} from "emdash/ui";
import { Comments, CommentForm } from "emdash/ui/comments";
import LiveSearch from "emdash/ui/search";
// Page context (for plugin contributions)
import { createPublicPageContext } from "emdash/page";Plugins
EmDash supports plugins for extending the CMS with hooks, storage, settings, admin UI, API routes, and custom Portable Text block types. Consider a plugin when you need to:
- React to content lifecycle events (e.g., send a notification on publish, sync to an external service)
- Add custom admin pages or dashboard widgets
- Add reusable behavior or custom Portable Text types (e.g., embedded maps or code playgrounds)
- Provide a reusable service (e.g., analytics, forms, comments via a third-party provider)
Plugins are registered in astro.config.mjs:
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({ directory: "./uploads", baseUrl: "/_emdash/api/media/file" }),
plugins: [myPlugin()],
}),To build a plugin, load the creating-plugins skill (in .agents/skills/creating-plugins/). It covers plugin anatomy, hooks, storage, admin UI, API routes, Portable Text blocks, capabilities, and the full definePlugin() API.
Reference Documents
| File | Contents |
| references/configuration.md | Project setup, astro.config, live.config, deployment, types |
| references/schema-and-seed.md | Collections, fields, taxonomies, menus, widgets, seed format |
| references/querying-and-rendering.md | Content APIs, PortableText, Image, caching, page patterns |
| references/site-features.md | Settings, menus, widgets, search, SEO, comments, page contributions |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

