This commit is contained in:
Matt Kane
2026-04-01 11:51:57 +01:00
parent c8e318da5c
commit ca3c2b77e1
88 changed files with 313 additions and 481 deletions

View File

@@ -261,17 +261,17 @@ The `"."` export has the descriptor. The `"./sandbox"` export has the implementa
Each feature is optional. Add only what your plugin needs:
| Feature | Where | Standard | Native | Purpose |
| ------------------- | ---------------------------- | -------- | ------ | ------------------------------------------------------- |
| **Hooks** | `definePlugin({ hooks })` | Yes | Yes | React to content/media/lifecycle events |
| **Storage** | descriptor `storage` | Yes | Yes | Document collections with indexed queries |
| **KV** | `ctx.kv` in hooks/routes | Yes | Yes | Key-value store for internal state |
| Feature | Where | Standard | Native | Purpose |
| ------------------- | ---------------------------- | -------- | ------ | ----------------------------------------------------- |
| **Hooks** | `definePlugin({ hooks })` | Yes | Yes | React to content/media/lifecycle events |
| **Storage** | descriptor `storage` | Yes | Yes | Document collections with indexed queries |
| **KV** | `ctx.kv` in hooks/routes | Yes | Yes | Key-value store for internal state |
| **API Routes** | `definePlugin({ routes })` | Yes | Yes | REST endpoints at `/_emdash/api/plugins/<id>/<route>` |
| **Admin Pages** | Block Kit `admin` route | Yes | Yes | Admin pages via Block Kit (JSON blocks) |
| **Widgets** | Block Kit `admin` route | Yes | Yes | Dashboard cards via Block Kit |
| **React Admin** | `admin.entry` + React export | No | Yes | React-based admin pages and widgets (native only) |
| **PT Blocks** | `admin.portableTextBlocks` | No | Yes | Custom block types in the Portable Text editor |
| **Site Components** | `componentsEntry` | No | Yes | Astro components for rendering blocks on the site |
| **Admin Pages** | Block Kit `admin` route | Yes | Yes | Admin pages via Block Kit (JSON blocks) |
| **Widgets** | Block Kit `admin` route | Yes | Yes | Dashboard cards via Block Kit |
| **React Admin** | `admin.entry` + React export | No | Yes | React-based admin pages and widgets (native only) |
| **PT Blocks** | `admin.portableTextBlocks` | No | Yes | Custom block types in the Portable Text editor |
| **Site Components** | `componentsEntry` | No | Yes | Astro components for rendering blocks on the site |
See the reference files for detailed syntax:

View File

@@ -66,8 +66,8 @@ definePlugin({
## Route URLs
| Plugin ID | Route Name | URL |
| --------- | --------------- | ------------------------------------------ |
| Plugin ID | Route Name | URL |
| --------- | --------------- | ---------------------------------------- |
| `forms` | `status` | `/_emdash/api/plugins/forms/status` |
| `forms` | `submissions` | `/_emdash/api/plugins/forms/submissions` |
| `seo` | `settings/save` | `/_emdash/api/plugins/seo/settings/save` |

View File

@@ -20,44 +20,44 @@ This skill maps WordPress concepts to their EmDash equivalents for plugin portin
### Content & Data
| WordPress | EmDash | Notes |
| ----------------------- | ------------------------------------------- | --------------------------------------------- |
| `register_post_type()` | `SchemaRegistry.createCollection()` | Via Admin API or seed file |
| ----------------------- | ----------------------------------------- | --------------------------------------------- |
| `register_post_type()` | `SchemaRegistry.createCollection()` | Via Admin API or seed file |
| `register_taxonomy()` | `_emdash_taxonomy_defs` table | Hierarchical or flat, attached to collections |
| `register_meta()` / ACF | Collection fields via SchemaRegistry | All become typed schema fields |
| `get_post_meta()` | `entry.data.fieldName` | Direct typed access |
| `get_option()` | `getSiteSetting()` / `ctx.kv` | Site settings or plugin-namespaced KV |
| `register_meta()` / ACF | Collection fields via SchemaRegistry | All become typed schema fields |
| `get_post_meta()` | `entry.data.fieldName` | Direct typed access |
| `get_option()` | `getSiteSetting()` / `ctx.kv` | Site settings or plugin-namespaced KV |
| `WP_Query` | `getEmDashCollection()` | Runtime queries with filters |
| `get_post($id)` | `getEmDashEntry(collection, slug)` | Returns entry or null |
| `wp_insert_post()` | `POST /_emdash/api/content/{type}` | REST API |
| `wp_update_post()` | `PUT /_emdash/api/content/{type}/{id}` | REST API |
| `wp_delete_post()` | `DELETE /_emdash/api/content/{type}/{id}` | Soft delete |
| Custom tables | Plugin storage collections | `ctx.storage.collectionName.put/get/query` |
| Custom tables | Plugin storage collections | `ctx.storage.collectionName.put/get/query` |
### Site Configuration
| WordPress | EmDash | Notes |
| WordPress | EmDash | Notes |
| ------------------------ | --------------------------- | ---------------------------------------- |
| `get_bloginfo('name')` | `getSiteSetting('title')` | From `options` table with `site:` prefix |
| `get_option('blogdesc')` | `getSiteSetting('tagline')` | Site settings API |
| Theme Customizer | Site Settings admin page | `/_emdash/admin/settings` |
| Theme Customizer | Site Settings admin page | `/_emdash/admin/settings` |
| `site_icon` | `getSiteSetting('favicon')` | Media reference |
| `custom_logo` | `getSiteSetting('logo')` | Media reference |
### Navigation Menus
| WordPress | EmDash | Notes |
| WordPress | EmDash | Notes |
| ---------------------- | --------------------------------------- | ----------------------------------- |
| `register_nav_menu()` | Create menu via admin or seed | `_emdash_menus` table |
| `register_nav_menu()` | Create menu via admin or seed | `_emdash_menus` table |
| `wp_nav_menu()` | `getMenu(name)` | Returns `{ items: MenuItem[] }` |
| `wp_nav_menu_item` | `_emdash_menu_items` table | Type: custom, page, post, taxonomy |
| `wp_nav_menu_item` | `_emdash_menu_items` table | Type: custom, page, post, taxonomy |
| `_menu_item_object_id` | `reference_id` + `reference_collection` | Links to content entries |
| Menu locations | Query by name in templates | No locations concept — direct query |
### Taxonomies
| WordPress | EmDash | Notes |
| WordPress | EmDash | Notes |
| --------------------- | --------------------------------------- | ------------------------------ |
| `register_taxonomy()` | `_emdash_taxonomy_defs` table | Define via admin, seed, or API |
| `register_taxonomy()` | `_emdash_taxonomy_defs` table | Define via admin, seed, or API |
| `get_terms()` | `getTaxonomyTerms(name)` | Returns tree for hierarchical |
| `get_the_terms()` | `getEntryTerms(collection, id, name)` | Terms for specific entry |
| `wp_set_post_terms()` | `TaxonomyRepository.setTermsForEntry()` | Replace terms for entry |
@@ -66,9 +66,9 @@ This skill maps WordPress concepts to their EmDash equivalents for plugin portin
### Widgets & Sidebars
| WordPress | EmDash | Notes |
| WordPress | EmDash | Notes |
| -------------------- | -------------------------------------- | ------------------------------- |
| `register_sidebar()` | `_emdash_widget_areas` table | Create via admin or seed |
| `register_sidebar()` | `_emdash_widget_areas` table | Create via admin or seed |
| `dynamic_sidebar()` | `getWidgetArea(name)` | Returns `{ widgets: Widget[] }` |
| `WP_Widget` class | Widget types: content, menu, component | Simplified — 3 types only |
| Text widget | `type: 'content'` + Portable Text | Rich text widget |
@@ -77,7 +77,7 @@ This skill maps WordPress concepts to their EmDash equivalents for plugin portin
### Admin UI
| WordPress | EmDash | Notes |
| WordPress | EmDash | Notes |
| ------------------------ | --------------------------------- | ---------------------------------------- |
| `add_menu_page()` | `admin.pages` in `definePlugin()` | Plugin config |
| `add_submenu_page()` | Nested admin pages | Parent determines hierarchy |
@@ -88,7 +88,7 @@ This skill maps WordPress concepts to their EmDash equivalents for plugin portin
### Hooks
| WordPress | EmDash | Notes |
| WordPress | EmDash | Notes |
| ---------------------------------- | --------------------------------------- | ----------------------------------------------------- |
| `add_action('init')` | `plugin:install` hook | Runs once on first install |
| `add_action('save_post')` | `content:afterSave` hook | Filter by `event.collection` |
@@ -100,7 +100,7 @@ This skill maps WordPress concepts to their EmDash equivalents for plugin portin
### Frontend Output
| WordPress | EmDash | Notes |
| WordPress | EmDash | Notes |
| ----------------------- | ---------------------------- | ---------------------------------------------------- |
| `add_shortcode()` | Portable Text custom block | Content → block. Template → component. Trusted only. |
| `register_block_type()` | PT block + `componentsEntry` | Block data → Astro component props. Trusted only. |
@@ -109,7 +109,7 @@ This skill maps WordPress concepts to their EmDash equivalents for plugin portin
### Plugin Storage
| WordPress | EmDash | Notes |
| WordPress | EmDash | Notes |
| ------------------------ | ------------------------ | ---------------------------------- |
| `get_option('plugin_*')` | `ctx.kv.get(key)` | Namespaced to plugin automatically |
| `update_option()` | `ctx.kv.set(key, value)` | Scoped KV storage |

View File

@@ -37,7 +37,7 @@ theme.json # Block themes (WP 5.9+) - structured design tokens
### CSS Variable Mapping
| WP Pattern | EmDash Variable |
| WP Pattern | EmDash Variable |
| ---------------- | ------------------ |
| Body font family | `--font-body` |
| Heading font | `--font-heading` |

View File

@@ -7,13 +7,13 @@ Implement CMS-driven features: site settings, menus, taxonomies, and widgets.
Map WordPress customizer values to EmDash site settings:
| WP Customizer Setting | EmDash Site Setting |
| --------------------- | --------------------- |
| Site Title | `title` |
| Tagline | `tagline` |
| Site Icon | `favicon` |
| Custom Logo | `logo` |
| Posts per page | `postsPerPage` |
| Date format | `dateFormat` |
| --------------------- | ------------------- |
| Site Title | `title` |
| Tagline | `tagline` |
| Site Icon | `favicon` |
| Custom Logo | `logo` |
| Posts per page | `postsPerPage` |
| Date format | `dateFormat` |
```astro
---
@@ -134,7 +134,7 @@ const sidebar = await getWidgetArea("sidebar");
Map WP widgets to Astro components:
| WP Widget | EmDash Component |
| WP Widget | EmDash Component |
| ---------------- | ------------------- |
| Recent Posts | `core:recent-posts` |
| Categories | `core:categories` |

View File

@@ -900,15 +900,15 @@ const { entry: page } = await getEmDashEntry("pages", "about");
### Key Differences
| Aspect | Astro Collections | EmDash Collections |
| ---------------------- | ------------------------------- | ----------------------------------------------- |
| **Config file** | `src/content.config.ts` | `src/live.config.ts` |
| **Schema definition** | In config file with Zod | In EmDash admin UI or seed file |
| **Data source** | Files, APIs, custom loaders | SQLite database |
| Aspect | Astro Collections | EmDash Collections |
| ---------------------- | ------------------------------- | ------------------------------------------- |
| **Config file** | `src/content.config.ts` | `src/live.config.ts` |
| **Schema definition** | In config file with Zod | In EmDash admin UI or seed file |
| **Data source** | Files, APIs, custom loaders | SQLite database |
| **Query functions** | `getCollection()`, `getEntry()` | `getEmDashCollection()`, `getEmDashEntry()` |
| **Content editing** | Edit source files directly | Admin UI or API |
| **Type safety** | Generated from schema | Runtime validation |
| **Rendering Markdown** | `render()` from `astro:content` | `<PortableText />` component |
| **Content editing** | Edit source files directly | Admin UI or API |
| **Type safety** | Generated from schema | Runtime validation |
| **Rendering Markdown** | `render()` from `astro:content` | `<PortableText />` component |
### When to Use Which

View File

@@ -2,7 +2,7 @@
## Template Hierarchy
| WP Template | Purpose | EmDash Equivalent |
| WP Template | Purpose | EmDash Equivalent |
| ------------------------- | ----------------------- | ------------------------------------------------------- |
| `index.php` | Fallback for everything | `src/pages/index.astro` |
| `front-page.php` | Static front page | `src/pages/index.astro` |
@@ -26,7 +26,7 @@
## Template Parts
| WP Pattern | EmDash Pattern |
| WP Pattern | EmDash Pattern |
| ---------------------------------------------------------- | ---------------------------- |
| `get_template_part('content', 'post')` | `<PostCard />` component |
| `get_template_part('template-parts/header/site-branding')` | `<SiteBranding />` component |
@@ -116,10 +116,10 @@ EmDash: Create collection via admin UI or API. The collection will be created du
### Content Retrieval
| WP Function | EmDash Equivalent |
| WP Function | EmDash Equivalent |
| ----------------------------- | ------------------------------------------------- |
| `have_posts()` / `the_post()` | `getEmDashCollection()` |
| `get_post()` | `getEmDashEntry()` |
| `have_posts()` / `the_post()` | `getEmDashCollection()` |
| `get_post()` | `getEmDashEntry()` |
| `the_title()` | `post.data.title` |
| `the_content()` | `<PortableText value={post.data.content} />` |
| `the_excerpt()` | `post.data.excerpt` |
@@ -132,7 +132,7 @@ EmDash: Create collection via admin UI or API. The collection will be created du
### Taxonomies
| WP Function | EmDash Equivalent |
| WP Function | EmDash Equivalent |
| ---------------------------- | -------------------------------------------------- |
| `get_categories()` | `getTaxonomyTerms("categories")` |
| `get_tags()` | `getTaxonomyTerms("tags")` |
@@ -149,7 +149,7 @@ EmDash supports hierarchical taxonomies (like categories) and flat taxonomies (l
### Site Info
| WP Function | EmDash Equivalent |
| WP Function | EmDash Equivalent |
| ------------------------- | --------------------------------------- |
| `bloginfo('name')` | `getSiteSetting("title")` |
| `bloginfo('description')` | `getSiteSetting("tagline")` |
@@ -173,7 +173,7 @@ EmDash supports hierarchical taxonomies (like categories) and flat taxonomies (l
### Media
| WP Function | EmDash Equivalent |
| WP Function | EmDash Equivalent |
| --------------------------- | -------------------------- |
| `wp_get_attachment_image()` | `<img src={media.url} />` |
| `wp_get_attachment_url()` | `media.url` |
@@ -181,7 +181,7 @@ EmDash supports hierarchical taxonomies (like categories) and flat taxonomies (l
### Navigation
| WP Function | EmDash Equivalent |
| WP Function | EmDash Equivalent |
| ------------------------ | ------------------------------------- |
| `wp_nav_menu()` | `getMenu("menu-name")` + render items |
| `wp_list_pages()` | Query pages collection or use menu |
@@ -198,10 +198,10 @@ WordPress hooks don't have direct equivalents. Most hook functionality becomes:
3. **Build-time logic** - In Astro config or components
| WP Hook | EmDash Approach |
| -------------------- | ------------------------------------------ |
| `wp_head` | Add to `<head>` in layout |
| `wp_footer` | Add before `</body>` in layout |
| `the_content` filter | PortableText components |
| -------------------- | ---------------------------------------- |
| `wp_head` | Add to `<head>` in layout |
| `wp_footer` | Add before `</body>` in layout |
| `the_content` filter | PortableText components |
| `pre_get_posts` | Query filters in `getEmDashCollection()` |
| `save_post` | EmDash plugin hook: `content:beforeSave` |
@@ -280,14 +280,14 @@ sidebar?.widgets.forEach((widget) => {
### Widget Types
| WP Widget | EmDash Widget Type | Notes |
| WP Widget | EmDash Widget Type | Notes |
| ------------ | ------------------------------- | ----------------------------- |
| Text/HTML | `content` | Portable Text (rich content) |
| Custom Menu | `menu` | References menu by name |
| Recent Posts | `component` `core:recent-posts` | Built-in component with props |
| Categories | `component` `core:categories` | Built-in component |
| Tag Cloud | `component` `core:tag-cloud` | Built-in component |
| Search | `<LiveSearch />` component | Use `emdash/ui` LiveSearch |
| Search | `<LiveSearch />` component | Use `emdash/ui` LiveSearch |
| Archives | `component` `core:archives` | Built-in component |
### Core Widget Components
@@ -358,7 +358,7 @@ const results = query ? await search(query, { limit: 20 }) : { results: [] };
### Search Features
| WordPress | EmDash |
| WordPress | EmDash |
| ---------------------------- | ------------------------------- |
| Basic keyword search | FTS5 with Porter stemming |
| Search all public post types | Per-collection search enable |

View File

@@ -104,7 +104,7 @@ Common elements to check:
### Common Color Mapping
| WP Pattern | EmDash Variable |
| WP Pattern | EmDash Variable |
| ---------------- | ------------------- |
| Background | `--color-base` |
| Text | `--color-contrast` |