Files
Oleks 67b07634ae initial scaffold: emdash catalog, helm chart, woodpecker pipeline, ddev
- app/: Emdash scaffold (Astro 6, node target) with cmses/plugins/pages collections
- app/seed/seed.json: WordPress→Emdash parity for kotkanagrilli.fi (~30 entries)
- Dockerfile + docker/entrypoint.sh: multi-stage build, single PVC at /app/state
- deploy/helm/: chart mirroring emdash-kotkanagrilli (single-replica, sqlite, kotkan)
- deploy/fleet-overlay/: HelmRelease/source/image-automation templates for
  anton-helm-workloads (staging + production)
- .woodpecker/container.yaml: arm64 build, three OCI tags per push
  (immutable 0.1.<pipeline> + floating <branch> + <branch>-latest)
- .ddev/: local dev with nginx proxy to emdash on :4321
- README/DEPLOYMENT/ARCHITECTURE/CLAUDE: docs covering the three-repo
  pipeline (cms-plugins + anton-helm-workloads + Gitea OCI registry)
2026-05-20 11:19:00 +03:00

573 lines
20 KiB
JSON

{
"$schema": "https://emdashcms.com/seed.schema.json",
"version": "1",
"meta": {
"name": "CMS plugins catalog",
"description": "WordPress → Emdash plugin parity catalog, seeded with kotkanagrilli.fi entries",
"author": "oleks"
},
"settings": {
"title": "CMS plugins catalog",
"tagline": "WordPress → Emdash plugin parity, one entry at a time"
},
"collections": [
{
"slug": "cmses",
"label": "CMS platforms",
"labelSingular": "CMS platform",
"urlPattern": "/cms/{slug}",
"supports": ["search", "seo"],
"fields": [
{ "slug": "title", "label": "Name", "type": "string", "required": true, "searchable": true },
{ "slug": "website", "label": "Website URL", "type": "string" },
{ "slug": "description", "label": "Description", "type": "text", "searchable": true }
]
},
{
"slug": "plugins",
"label": "Plugins",
"labelSingular": "Plugin",
"urlPattern": "/plugins/{slug}",
"supports": ["drafts", "search", "seo"],
"fields": [
{ "slug": "title", "label": "Plugin name", "type": "string", "required": true, "searchable": true },
{ "slug": "purpose", "label": "Purpose", "type": "text", "searchable": true,
"description": "One-line description of what the plugin does." },
{ "slug": "source_cms", "label": "Source CMS", "type": "string", "required": true, "searchable": true,
"description": "Name of the CMS this plugin runs on today (e.g. WordPress)." },
{ "slug": "target_cms", "label": "Target CMS", "type": "string", "searchable": true,
"description": "Name of the CMS we're porting to, if applicable." },
{ "slug": "category", "label": "Category", "type": "string",
"description": "e-commerce, SEO, content, performance, etc." },
{
"slug": "status",
"label": "Migration status",
"type": "select",
"required": true,
"defaultValue": "proposed",
"searchable": true,
"options": [
{ "value": "port", "label": "Port — reimplement on target" },
{ "value": "built-in", "label": "Built-in — covered by target core" },
{ "value": "saas", "label": "SaaS — replaced by external service" },
{ "value": "drop", "label": "Drop — not needed" },
{ "value": "gated", "label": "Gated — pending decision" },
{ "value": "done", "label": "Done — ported and shipped" },
{ "value": "proposed", "label": "Proposed — newly submitted" }
]
},
{ "slug": "source_repo_url", "label": "Source repo URL", "type": "string" },
{ "slug": "target_repo_url", "label": "Target repo URL", "type": "string" },
{ "slug": "notes", "label": "Migration notes", "type": "portableText", "searchable": true }
]
},
{
"slug": "pages",
"label": "Pages",
"labelSingular": "Page",
"urlPattern": "/{slug}",
"supports": ["drafts", "revisions", "search", "seo"],
"fields": [
{ "slug": "title", "label": "Title", "type": "string", "required": true, "searchable": true },
{ "slug": "content", "label": "Content", "type": "portableText", "searchable": true },
{ "slug": "excerpt", "label": "Excerpt", "type": "text" }
]
}
],
"content": {
"cmses": [
{
"slug": "wordpress",
"data": {
"title": "WordPress",
"website": "https://wordpress.org",
"description": "PHP/MariaDB CMS with the largest plugin ecosystem. Source platform for the kotkanagrilli.fi migration."
}
},
{
"slug": "emdash",
"data": {
"title": "Emdash",
"website": "https://github.com/emdash-cms/emdash",
"description": "TypeScript/Astro/SQLite CMS positioned as a spiritual successor to WordPress. Target platform for the kotkanagrilli.fi migration."
}
}
],
"pages": [
{
"slug": "about",
"data": {
"title": "About this catalog",
"excerpt": "What this catalog is and how it's organized.",
"content": [
{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "This catalog tracks plugins from one CMS and how they map to another. The seeded entries come from the kotkanagrilli.fi WordPress → Emdash migration, where ~30 third-party and custom plugins needed to be classified before the rebuild." }] },
{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Each entry has a migration status (port, built-in, saas, drop, gated, done, proposed) and free-form notes. New entries can be added through the Emdash admin at /_emdash/admin." }] }
]
}
}
],
"plugins": [
{
"slug": "woocommerce",
"data": {
"title": "WooCommerce",
"purpose": "E-commerce / order management for WordPress.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "e-commerce",
"status": "gated",
"source_repo_url": "https://wordpress.org/plugins/woocommerce/",
"notes": [
{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Fate depends on the kotkanagrilli WooCommerce decision gate: (a) keep WP on a subdomain for ordering, (b) build an Emdash orders+SumUp plugin, (c) outsource to an ordering SaaS." }] }
]
}
},
{
"slug": "woocommerce-payments",
"data": {
"title": "WooCommerce Payments",
"purpose": "WC native payment gateway.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "e-commerce",
"status": "gated",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Tied to the WooCommerce decision." }] }]
}
},
{
"slug": "sumup-payment-gateway-for-woocommerce",
"data": {
"title": "SumUp Payment Gateway for WooCommerce",
"purpose": "SumUp checkout integration for WC.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "e-commerce",
"status": "gated",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Tied to WC decision. SumUp REST API is callable directly from a custom Emdash plugin if option (b) is chosen." }] }]
}
},
{
"slug": "fluid-checkout",
"data": {
"title": "Fluid Checkout",
"purpose": "Improved WooCommerce checkout UX.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "e-commerce",
"status": "gated"
}
},
{
"slug": "woo-checkout-field-editor-pro",
"data": {
"title": "Woo Checkout Field Editor Pro",
"purpose": "Custom checkout fields for WooCommerce.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "e-commerce",
"status": "gated"
}
},
{
"slug": "woocommerce-customizer",
"data": {
"title": "WooCommerce Customizer",
"purpose": "Miscellaneous WooCommerce tweaks.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "e-commerce",
"status": "gated"
}
},
{
"slug": "woc-open-close",
"data": {
"title": "WooCommerce Open/Close",
"purpose": "Show/hide the store as open or closed.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "e-commerce",
"status": "port",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Reimplement as a small Emdash plugin or Astro middleware reading a business-hours config. Not actually WC-coupled despite the name." }] }]
}
},
{
"slug": "google-listings-and-ads",
"data": {
"title": "Google Listings & Ads",
"purpose": "Merchant Center feed for WooCommerce.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "marketing",
"status": "gated"
}
},
{
"slug": "polylang",
"data": {
"title": "Polylang",
"purpose": "FI/EN translation for WordPress.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "i18n",
"status": "port",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Native Emdash collections + locale routing in Astro (src/pages/[lang]/...) replaces Polylang." }] }]
}
},
{
"slug": "connect-polylang-elementor",
"data": {
"title": "Connect Polylang for Elementor",
"purpose": "Glue between Polylang and Elementor.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "i18n",
"status": "drop",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Dropped together with Elementor." }] }]
}
},
{
"slug": "elementor",
"data": {
"title": "Elementor",
"purpose": "Visual page builder for WordPress.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "page-builder",
"status": "drop",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Rebuild pages as Astro components / Emdash portable-text blocks." }] }]
}
},
{
"slug": "cafe-eatery",
"data": {
"title": "Cafe Eatery",
"purpose": "WordPress block theme (parent of the kotkanagrilli child theme).",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "theme",
"status": "drop",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Rebuild as an Astro theme (Phase 2)." }] }]
}
},
{
"slug": "autoptimize",
"data": {
"title": "Autoptimize",
"purpose": "Asset minification + concatenation.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "performance",
"status": "built-in",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Astro/Vite handles bundling natively." }] }]
}
},
{
"slug": "jetpack-boost",
"data": {
"title": "Jetpack Boost",
"purpose": "Performance hints for WordPress.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "performance",
"status": "built-in",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Astro + Cloudflare handle this." }] }]
}
},
{
"slug": "ewww-image-optimizer",
"data": {
"title": "EWWW Image Optimizer",
"purpose": "Image optimization for WordPress media.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "performance",
"status": "built-in",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Astro Image integration + responsive styles already wired in astro.config.mjs." }] }]
}
},
{
"slug": "jetpack",
"data": {
"title": "Jetpack",
"purpose": "Stats, hardening, related-posts, and more.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "ops",
"status": "saas",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Replaced by Cloudflare analytics + WAF." }] }]
}
},
{
"slug": "redis-cache",
"data": {
"title": "Redis Object Cache",
"purpose": "PHP object cache for WordPress.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "performance",
"status": "drop",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "No PHP, no need; Astro + Emdash memoryCache provider already wired." }] }]
}
},
{
"slug": "wp-mail-smtp",
"data": {
"title": "WP Mail SMTP",
"purpose": "Outbound mail via external SMTP.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "mail",
"status": "saas",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "External SMTP configured at the platform layer, or via an Emdash mailer plugin." }] }]
}
},
{
"slug": "cb-change-mail-sender",
"data": {
"title": "CB Change Mail Sender",
"purpose": "Override the sender address on outgoing mail.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "mail",
"status": "port",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Handled by the same Emdash mailer plugin that replaces wp-mail-smtp." }] }]
}
},
{
"slug": "wpforms-lite",
"data": {
"title": "WPForms Lite",
"purpose": "Contact form builder.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "forms",
"status": "port",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Small Astro form action posting to a server endpoint, or a Cloudflare Worker on the CF target." }] }]
}
},
{
"slug": "wp-google-maps",
"data": {
"title": "WP Google Maps",
"purpose": "Map embed for posts/pages.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "content",
"status": "port",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Static iframe embed in the theme — trivial port." }] }]
}
},
{
"slug": "sticky-chat-widget",
"data": {
"title": "Sticky Chat Widget",
"purpose": "Floating WhatsApp/chat button.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "content",
"status": "port",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Static component in the theme — trivial port." }] }]
}
},
{
"slug": "shortcodes-ultimate",
"data": {
"title": "Shortcodes Ultimate",
"purpose": "Shortcode library for the WP editor.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "content",
"status": "drop",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Astro components / portable-text block types replace it." }] }]
}
},
{
"slug": "tinymce-advanced",
"data": {
"title": "TinyMCE Advanced",
"purpose": "Editor enhancement for WordPress.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "editor",
"status": "drop",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Emdash has its own editor." }] }]
}
},
{
"slug": "lara-google-analytics",
"data": {
"title": "Lara Google Analytics",
"purpose": "GA4 tag for WordPress.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "analytics",
"status": "port",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Static <script> in the theme head — trivial port." }] }]
}
},
{
"slug": "social-login",
"data": {
"title": "Social Login",
"purpose": "OAuth login for WordPress.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "auth",
"status": "drop",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Drop unless actually needed; Emdash uses passkeys by default." }] }]
}
},
{
"slug": "twentytwentyfive",
"data": {
"title": "Twenty Twenty-Five",
"purpose": "Default WordPress fallback theme.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "theme",
"status": "drop"
}
},
{
"slug": "store-closed-button",
"data": {
"title": "store-closed-button (mu-plugin)",
"purpose": "Toggle the store between open and closed.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "ops",
"status": "port",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Becomes an Emdash plugin: business-hours config + an admin badge. Replaces store.py CLI." }] }]
}
},
{
"slug": "store-override-admin-bar",
"data": {
"title": "store-override-admin-bar (mu-plugin)",
"purpose": "Admin-bar indicator for the open/close override.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "ops",
"status": "port",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Folded into the same business-hours Emdash plugin." }] }]
}
},
{
"slug": "nginx-cache-indicator",
"data": {
"title": "nginx-cache-indicator (mu-plugin)",
"purpose": "Visual UX hint for nginx cache hits.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "ops",
"status": "port",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Folded into the same admin badge that store-closed-button becomes." }] }]
}
},
{
"slug": "out-of-stock-display",
"data": {
"title": "out-of-stock-display (mu-plugin)",
"purpose": "WC UX fix for out-of-stock items.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "e-commerce",
"status": "gated"
}
},
{
"slug": "cart-fragment-cache-fix",
"data": {
"title": "cart-fragment-cache-fix (mu-plugin)",
"purpose": "Fix for WC cart fragment caching.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "e-commerce",
"status": "gated"
}
},
{
"slug": "checkout-button-fix",
"data": {
"title": "checkout-button-fix (mu-plugin)",
"purpose": "WC checkout button UX fix.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "e-commerce",
"status": "gated"
}
},
{
"slug": "checkout-local-pickup",
"data": {
"title": "checkout-local-pickup (mu-plugin)",
"purpose": "Local-pickup behavior at checkout.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "e-commerce",
"status": "gated"
}
},
{
"slug": "sumup-payment-verify",
"data": {
"title": "sumup-payment-verify (mu-plugin)",
"purpose": "Manual SumUp payment verification step.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "e-commerce",
"status": "gated"
}
},
{
"slug": "sumup-webhook-fix",
"data": {
"title": "sumup-webhook-fix (mu-plugin)",
"purpose": "Patch for the SumUp webhook handler.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "e-commerce",
"status": "gated"
}
},
{
"slug": "load-elementor-fonts",
"data": {
"title": "load-elementor-fonts (mu-plugin)",
"purpose": "Force-load Elementor fonts.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "theme",
"status": "drop",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Dropped together with Elementor." }] }]
}
},
{
"slug": "remove-theme-ads",
"data": {
"title": "remove-theme-ads (mu-plugin)",
"purpose": "Strip upsell ads from the Cafe Eatery theme.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "theme",
"status": "drop",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Dropped together with the Cafe Eatery theme." }] }]
}
},
{
"slug": "security-hardening",
"data": {
"title": "security-hardening (mu-plugin)",
"purpose": "Response headers + login lockdown.",
"source_cms": "WordPress",
"target_cms": "Emdash",
"category": "security",
"status": "port",
"notes": [{ "_type": "block", "style": "normal", "children": [{ "_type": "span", "text": "Cloudflare WAF rules cover the WAF half; Astro middleware sets response headers for the rest." }] }]
}
}
]
}
}