* fix(core): add IF NOT EXISTS to migration 033 index creation The schema registry's createContentTable() creates composite indexes on content tables at creation time. When migration 033 runs on a database where tables were created after the registry added these indexes, it fails with "index already exists". Adding IF NOT EXISTS makes the migration idempotent. * refactor(smoke): trim site matrix to templates + playground, remove typechecks The smoke test matrix included every demo and template, plus typecheck cases. This was slow and redundant — typechecks are already covered by pnpm typecheck, and demos are dev targets not release artifacts. Trim to templates + playground only, and replace the sequential per-site astro build with a single recursive pnpm build. Remove the TypecheckSiteCase type and handling since smoke tests should only verify runtime behavior. * Update env * chore: add changeset for migration 033 fix
emdash
The core EmDash CMS package - an Astro-native, agent-portable reimplementation of WordPress.
Installation
npm install emdash
Features
- Content Management - Collections, fields, Live Collections integration
- Media Library - Upload via signed URLs, S3-compatible storage
- Full-Text Search - FTS5 with Porter stemming, per-collection config
- Navigation Menus - Hierarchical menus with URL resolution
- Taxonomies - Categories, tags, custom taxonomies
- Widget Areas - Content, menu, and component widgets
- Sections - Reusable content blocks
- Plugin System - Hooks, storage, settings, admin pages
- WordPress Import - WXR, REST API, WordPress.com
Quick Start
// astro.config.mjs
import { defineConfig } from "astro/config";
import emdash, { local } from "emdash/astro";
import { sqlite } from "emdash/db";
export default defineConfig({
integrations: [
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
}),
],
});
// src/live.config.ts
import { defineLiveCollection } from "astro:content";
import { emdashLoader } from "emdash/runtime";
export const collections = {
_emdash: defineLiveCollection({ loader: emdashLoader() }),
};
API
import {
getEmDashCollection,
getEmDashEntry,
getSiteSettings,
getMenu,
getTaxonomyTerms,
getWidgetArea,
search,
} from "emdash";
// Content
const { entries } = await getEmDashCollection("posts");
const { entry } = await getEmDashEntry("posts", "hello-world");
// Site settings
const settings = await getSiteSettings();
// Navigation
const menu = await getMenu("primary");
// Taxonomies
const categories = await getTaxonomyTerms("categories");
// Widgets
const sidebar = await getWidgetArea("sidebar");
// Search
const results = await search("hello world", { collections: ["posts"] });
Documentation
See the documentation site for guides, API reference, and plugin development.