WooCommerce-class commerce for EmDash CMS — the Astro-native, Cloudflare-powered WordPress successor.
Full-featured ecommerce in one plugin: products, cart, checkout, orders, subscriptions, multi-vendor marketplace, and more. Runs on Cloudflare Workers or Node.js (Railway, Render, etc.). Typed end-to-end. MIT licensed.
npm create @dashcommerce@latestScaffolds a complete storefront with EmDash + DashCommerce, demo products, and Stripe test mode ready to go.
🎯 Live Demo: demo.dashcommerce.dev
📘 Docs: dashcommerce.dev/docs
💬 Issues: github.com/emdashCommerce/dashcommerce/issues
v0.3.2 on npm, peer EmDash >=0.37.0 <0.38.0 || >=1.1.0 <1.4.0. 0.37.x installs stay valid; EmDash 1.1 to 1.3 installs pass peer checks. Skip emdash@1.0.0 (wrong codebase on npm) and untested 0.38 to 0.42 until peers widen.
| Package | Version | EmDash Compatibility |
|---|---|---|
@dashcommerce/core |
0.3.2 | EmDash 0.37.x or 1.1+ |
DashCommerce Lite (dashcommerce-lite, EmDash plugin registry) |
0.2.0 | EmDash 1.3+ |
@dashcommerce/create |
track latest | Scaffolds from emdashCommerce/starter |
Stay on 0.1.x if you need EmDash 0.28.x — that line remains on npm and is not bricked by 0.2.x.
The v1.0 feature roadmap is code-complete. SemVer: 0.x may include minor breaking changes until 1.0.0 — see CHANGELOG.md.
EmDash's default plugin discovery is the Atmosphere registry (plugins.emdashcms.com). There are two ways to run DashCommerce:
- DashCommerce Lite is in the registry as
dashcommerce-lite. It is a sandboxed plugin you install from the EmDash admin, with no npm step: simple products from your content, a cart, Stripe hosted Checkout, stock tracking, refunds, and pages for orders, stock and settings. On Cloudflare it needs the Workers Paid plan, because EmDash runs sandboxed plugins in Worker Loaders. Source and setup:packages/lite. - Full DashCommerce is
@dashcommerce/coreon npm, a native plugin (too large for the registry's 256 KB sandbox cap) with subscriptions, variable products, Connect marketplaces and the full admin. Start withnpm create @dashcommerce@latest. The DashCommerce Setup registry listing shows these install steps inside your admin.
Do not install Lite alongside @dashcommerce/core. Each runs its own cart, checkout, orders and Stripe webhook. Pick one.
No. DashCommerce (@dashcommerce/core) is a Stripe-native commerce plugin: products, cart, checkout, subscriptions, Connect marketplace, and a 12-page admin inside EmDash.
Urumi’s dash-commerce focuses on WooCommerce REST v3 + Store API compatibility so existing Woo clients can talk to EmDash.
If you want a full store on Astro + EmDash with Stripe, use DashCommerce. If you need drop-in Woo API paths for legacy clients, evaluate Urumi.
- Deploy Anywhere: Cloudflare Workers (edge) or Node.js (Railway, Render, your VPS)
- Modern Auth: Passkey support via EmDash's built-in auth system
- Stripe Native: Hosted Checkout, Payment Element, Subscriptions, Connect for multi-vendor
- Type-Safe: End-to-end TypeScript, from admin UI to storefront islands
- Sandboxed option: DashCommerce Lite runs in EmDash's plugin sandbox and installs from the plugin registry
- Open Source: MIT core; extensible plugin architecture
Every feature category WooCommerce ships, in one plugin:
Core Commerce: Products (simple, variable, subscription, digital), multi-currency, cart, hosted Stripe checkout, orders with refunds, customer portal
Growth Tools: Coupons, shipping zones, tax automation (Stripe Tax optional), inventory management, reviews
Advanced: Subscriptions with trials & dunning, multi-vendor marketplace (Stripe Connect), abandoned cart recovery, transactional email
Admin: React-based dashboard with 12 pages, revenue reports, top products/customers, MRR tracking
See What's in the box below for the complete feature breakdown.
DashCommerce 0.2.x requires EmDash 0.37+. If you're on 0.1.x (EmDash 0.28.x), follow the migration guide below.
Prerequisites: Backup your database and verify your local dev environment works before upgrading production.
Step 1: Update all dependencies together
# Recommended: EmDash 1.x + DashCommerce 0.2.x
npm install emdash@^1.1.0 @emdash-cms/admin@^1.1.0 @dashcommerce/core@^0.2.0
# For Cloudflare deployments, also update:
npm install @emdash-cms/cloudflare@^1.1.0
# Or stay on EmDash 0.37.x:
npm install emdash@^0.37.0 @emdash-cms/admin@^0.37.0 @dashcommerce/core@^0.2.0Step 2: Apply EmDash patch (required)
DashCommerce requires a small patch to EmDash for webhook handling and response passthrough. Matching 0.37.0, 1.2.0, 1.3.0 and 1.3.1 patches ship alongside it. Patches are version-exact (hashed dist files); npm and yarn users must copy the file that matches the resolved emdash version into the app root. See packages/core/patches/README.md.
# Using Bun (recommended) - add to package.json (use the key that matches your resolved emdash version):
{
"patchedDependencies": {
"emdash@0.37.0": "node_modules/@dashcommerce/core/patches/emdash@0.37.0.patch",
"emdash@1.1.0": "node_modules/@dashcommerce/core/patches/emdash@1.1.0.patch",
"emdash@1.2.0": "node_modules/@dashcommerce/core/patches/emdash@1.2.0.patch",
"emdash@1.3.0": "node_modules/@dashcommerce/core/patches/emdash@1.3.0.patch",
"emdash@1.3.1": "node_modules/@dashcommerce/core/patches/emdash@1.3.1.patch"
}
}
# Then reinstall:
bun installSee patches/README.md for pnpm/npm/yarn instructions.
Step 3: Update Astro config (if using Cloudflare Workers)
EmDash 0.37 imports cloudflare:* runtime modules that must be externalized for Node.js builds:
// astro.config.mjs
export default defineConfig({
// ... existing config
vite: {
build: {
rollupOptions: {
external: target === "node" ? [/^cloudflare:/] : [],
},
},
},
});Step 4: Test checkout and webhooks
- Place a test order using Stripe test cards
- Verify webhook signature verification works
- Check that Stripe webhooks return HTTP 200 (not
{}) - Test subscription creation/renewal if using subscriptions
Step 5: Deploy to production
After verifying everything works locally, deploy to your hosting environment and monitor for any compatibility warnings in logs.
If you're not ready to upgrade to EmDash 0.37:
# Pin to the latest 0.1.x release
npm install @dashcommerce/core@^0.1.5
# Keep EmDash on 0.28.x
npm install emdash@^0.28.0 @emdash-cms/admin@^0.28.0The 0.1.x line remains on npm and will continue working with EmDash 0.28.x. However, new features and non-security fixes will only land in 0.2.x+.
- Minimum EmDash version: Now
0.37.0(was0.28.0). Current peer also admits EmDash>=1.1.0 <1.4.0. - Patch required: Apply the patch that matches your resolved EmDash version (
emdash@0.37.0,emdash@1.1.0,emdash@1.2.0,emdash@1.3.0, oremdash@1.3.1) for webhooks and raw Response passthrough.patchedDependenciesonly applies in the consumer's root, so npm/yarn installs must copy the matching file from@dashcommerce/core/patches. - Node.js builds: Must externalize
cloudflare:*modules in Vite config - Runtime version check: Plugin will throw on incompatible EmDash versions (fail-closed for safety)
See CHANGELOG.md for full release notes.
| Area | What ships |
|---|---|
| Products | Simple, variable (size/color/etc), grouped, external/affiliate, subscription, digital-download — one collection, one type switch |
| Multi-currency | Per-product price maps, customer-selected currency at cart, per-currency minor-units handling |
| Cart & Checkout | Hosted Stripe Checkout (default) + embedded Payment Element fallback; Apple/Google Pay; guest + logged-in |
| Orders | Admin dashboard with refund / partial-refund UI, order timeline, draft-to-paid pipeline |
| Customers | Address book, order history, self-service portal (email-link, no password needed for first access) |
| Coupons | Fixed/percent × cart/product, free-shipping, exclusions, usage limits, per-customer caps |
| Shipping | Multi-zone, flat-rate / free / local-pickup / weight-based; per-product shipping classes |
| Tax | Flat-rate, rate-table (by country/region), or Stripe Tax (automatic); tax on shipping toggle |
| Inventory | Soft-locks during checkout prevent overselling; low-stock alerts; backorder policy per product |
| Subscriptions | Stripe Subscriptions, trials, upgrade/downgrade, pause/resume, dunning, customer portal |
| Digital downloads | Signed-URL token downloads, TTL + max-use enforcement, per-order grants |
| Reviews | Moderation queue, verified-purchase badge, review aggregates on product pages |
| Multi-vendor | Stripe Connect Express onboarding, single-vendor-per-order splits, platform fee, vendor payouts |
| Abandoned cart | Cron-driven reminder emails with signed restore links |
| Transactional email | Receipt, refund, subscription renewal, dunning, abandoned cart, review request, vendor invite/activation/payout — HTML + plain text |
| Reports | Revenue / top products / top customers / MRR inside the admin dashboard |
| Admin UI | 12 React pages + 5 dashboard widgets + 2 field widgets + 3 Portable Text blocks |
| Package | Description |
|---|---|
@dashcommerce/core |
The plugin — hooks, routes, admin UI, storefront islands |
@dashcommerce/starter |
Reference EmDash storefront that exercises every feature |
The marketing / docs site source also lives in this monorepo under site/ and serves https://dashcommerce.dev.
bun add @dashcommerce/coreRegister the plugin in astro.config.mjs:
import { dashcommerce } from "@dashcommerce/core";
emdash({ plugins: [dashcommerce()] });Merge the products collection + taxonomies into your seed file and re-apply:
bunx dashcommerce-merge-seed
bun emdash seed --on-conflict=updateOpen /_emdash/admin/plugins/dashcommerce/settings and paste your Stripe test keys.
Want sample data to play with? Add --with-demo-catalog to seed six example products (one per type) plus curated category/tag terms:
bunx dashcommerce-merge-seed --with-demo-catalog
bun emdash seed --on-conflict=updateThe merge step is idempotent — it only replaces DashCommerce's own entries (the products collection, product_category / product_tag taxonomies) and, with --with-demo-catalog, only appends demo products whose ids aren't already in your seed. Everything else is preserved. If you prefer to assemble the seed in code, import mergeDashCommerceSeed(seed, { withDemoCatalog }) from @dashcommerce/core.
Use the scaffold command from the top of this README:
npm create @dashcommerce@latestThis clones @dashcommerce/starter with a fully-wired storefront, demo catalog, and Stripe test mode ready.
Or wire it manually:
// astro.config.mjs
import { defineConfig } from "astro/config";
import emdash from "emdash/astro";
import { sqlite } from "emdash/db";
import { local } from "emdash/storage/local";
import { dashcommerce } from "@dashcommerce/core";
export default defineConfig({
integrations: [
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({ directory: "./uploads", baseUrl: "/_emdash/api/media/file" }),
plugins: [dashcommerce()],
}),
],
});bun emdash init
bunx dashcommerce-merge-seed
bun emdash seed --on-conflict=update
bun devFull walkthrough: Getting started · Stripe setup.
astro.config.mjs
└─ emdash({ plugins: [dashcommerce()] })
│
├─ Vite build ──► packages/core/src/index.ts # descriptor only, side-effect-free
│
└─ Runtime ──► packages/core/src/sandbox-entry.ts # hooks + routes
│
├─ routes/cart.ts (public)
├─ routes/checkout.ts (public)
├─ routes/webhook.ts (public; Stripe-signed)
├─ routes/admin-api.ts (admin-gated)
└─ …12 more
Hard rules the sandbox entry and everything it imports obey:
- No Node built-ins (
fs,crypto,node:*) — crypto viacrypto.subtle, HTTP viactx.http.fetch - All money as integer minor units (
Money = { currency, amount }), ISO 4217; mixed-currency ops throw - Every Stripe webhook is idempotent via unique-indexed Stripe IDs; duplicates return HTTP 200
- Webhook signature verification happens before any side effect
- Cart re-prices server-side on every mutation and on every read — no client-sent prices trusted
bun install
bun run typecheck
bun run build
bun test # 66 tests across money / cart / coupons / webhook / tokens / splitPer-package loop:
cd packages/core && bun run dev # tsdown --watch
cd packages/starter && bun run dev # Astro on :4321Stripe webhook forwarding for local dev:
stripe listen --forward-to localhost:4321/_emdash/api/plugins/dashcommerce/checkout/webhookPre-release, so the surface is still shifting. Small PRs welcome; large new features please open an issue first so we can align with the roadmap in CHANGELOG.md.
MIT