dodopayments/dualmark
Open-source AEO (Answer Engine Optimization) infrastructure — every page, dual-marked. Markdown twins for AI agents alongside HTML for humans, picked by HTTP content negotiation.
✨ New: Netlify adapter — `@dualmark/netlify@0.10.0`
- Run Dualmark on Netlify Edge Functions (Deno runtime). Serves clean markdown twins to AI bots at the edge via content negotiation.
- ```bash
- bun add @dualmark/netlify @dualmark/core
- ```
- See [`examples/netlify-edge`](https://github.com/dodopayments/dualmark/tree/main/examples/netlify-edge).
✨ New: Nuxt integration — `@dualmark/nuxt@0.10.0`
- ```bash
- bun add @dualmark/nuxt @dualmark/core @dualmark/converters
- ```
✨ New: OpenAPI-aware `api-reference` converter — `@dualmark/converters@0.10.0`
- A new `api-reference` converter with a `fromOpenAPI` helper turns your OpenAPI spec into clean, AI-readable markdown API reference pages. Available through the Astro, Next.js, and SvelteKit adapters.
✨ New: Pluggable token estimator — `@dualmark/core@0.10.0`
- Bring your own tokenizer for accurate `X-Markdown-Tokens` counts:
- `estimateTokens(text, { tokenizer })` accepts an inline override function
- New exports from core: `TokenEstimator` type, `setTokenEstimator`, `resetTokenEstimator`
- A `tokenizer` option is now wired into every adapter config: Astro, Cloudflare, Deno, Next.js, SvelteKit, Vercel
- The Astro adapter also accepts module-path strings (e.g. `"./src/aeo-tokenizer.ts"`) for tokenizers that close over external state like `js-tiktoken`
📋 Changes by package
- | Package | Version | Type | Change |
- |---|---|---|---|
- | `@dualmark/netlify` | `0.10.0` | minor | New Netlify Edge Functions adapter |
- | `@dualmark/nuxt` | `0.10.0` | minor | New Nuxt integration |
- | `@dualmark/converters` | `0.10.0` | minor | New OpenAPI-aware `api-reference` converter (`fromOpenAPI`) |
- | `@dualmark/core` | `0.10.0` | minor | Pluggable token estimator (`tokenizer` option) |
- | `@dualmark/astro` | `0.10.0` | minor | `api-reference` converter + pluggable tokenizer (function or module-path) |
- | `@dualmark/nextjs` | `0.10.0` | minor | `api-reference` converter + pluggable tokenizer |
- + 6 more
✨ New: SvelteKit adapter — `@dualmark/sveltekit@0.9.0`
- ```bash
- bun add @dualmark/sveltekit @dualmark/core @dualmark/converters
- ```
- Verified at 125/125 conformance under `vite dev`. See [`examples/sveltekit-blog`](https://github.com/dodopayments/dualmark/tree/main/examples/sveltekit-blog).
✨ New: Vercel Edge adapter — `@dualmark/vercel@0.9.0`
- ```bash
- bun add @dualmark/vercel @dualmark/core
- ```
- Verified at 120/125 under `next dev`. See [`examples/vercel-edge-full`](https://github.com/dodopayments/dualmark/tree/main/examples/vercel-edge-full).
📦 Improved: Astro config diagnostics — `@dualmark/astro@0.9.0`
- Config validation errors now include the offending file path (e.g. `[astro.config.mjs] Dualmark config error: siteUrl is required`), so you know exactly which file to fix.
📋 Changes by package
- | Package | Version | Type | Change |
- |---|---|---|---|
- | `@dualmark/sveltekit` | `0.9.0` | minor | New SvelteKit adapter (#32) |
- | `@dualmark/vercel` | `0.9.0` | minor | New Vercel Edge adapter (closes #8) |
- | `@dualmark/astro` | `0.9.0` | patch | File paths in config validation errors (#50) |
- Six end-to-end adapters now ship: Astro, Next.js, SvelteKit, Cloudflare, Deno, Vercel.
- Full Changelog: https://github.com/dodopayments/dualmark/compare/v0.8.0...v0.9.0
📦 Highlights
- Three things land in this release:
- New package: `@dualmark/deno` — a Deno Deploy edge adapter that wraps any Deno `fetch` handler. AI bots get the markdown twin at the edge; lifecycle hooks (analytics/telemetry) are scheduled on `info.completed`. `examples/deno-deploy` scores a perfect 125/125 under `deno run`.
- New converter: `status-page` — a built-in converter for public uptime/status pages (component health + incidents). Drop `converter: "status-page"` into an Astro or Next.js collection and status pages get the same battle-tested markdown layout as the rest.
- Stable `dualmark verify --json` — `@dualmark/cli` now emits the public AEO Spec v1.0 JSON contract instead of the internal report shape. See the migration note below.
- No breaking API changes for the framework adapters. Drop-in upgrade from `0.7.x`. The whole `@dualmark/*` family moves to `0.8.0` together (linked versioning).
✨ `@dualmark/deno@0.8.0` (new)
- Deno Deploy edge adapter ([`6a6bf8a`](https://github.com/dodopayments/dualmark/commit/6a6bf8a)) — wraps any upstream Deno fetch handler, serves markdown to known AI bots at the edge, and schedules lifecycle hooks on `info.completed`.
- 23 tests pass. Integration docs included.
📦 `@dualmark/converters@0.8.0`
- New: `statusPageConverter` ([`dd0512c`](https://github.com/dodopayments/dualmark/commit/dd0512c), closes #12) for uptime/status pages — public component health plus incident history, with the standard brand-footer + breadcrumb conventions.
- Registered as the built-in `status-page` resolver in `@dualmark/astro` and `@dualmark/nextjs` — no config beyond `converter: "status-page"`.
- Separators in the status converter now render conditionally ([`b2d925e`](https://github.com/dodopayments/dualmark/commit/b2d925e)).
📦 `@dualmark/cli@0.8.0`
- `verify --json` now emits the AEO Spec v1.0 JSON contract ([`65ab17e`](https://github.com/dodopayments/dualmark/commit/65ab17e)) and enforces `--json` mutual exclusivity with `--quiet`/`--color`. Required-check failures still exit non-zero.
📦 `@dualmark/core@0.8.0`, `@dualmark/astro@0.8.0`, `@dualmark/nextjs@0.8.0`, `@dualmark/cloudflare@0.8.0`
- Version bumps to keep the linked `@dualmark/*` family in lockstep (and to register the `status-page` resolver in `astro` / `nextjs`). No API changes.
📦 Upgrade
- ```bash
- bun add @dualmark/astro@^0.8.0
- bun add @dualmark/nextjs@^0.8.0
- bun add @dualmark/cloudflare@^0.8.0
- bun add @dualmark/deno@^0.8.0
- bun add -g @dualmark/cli@^0.8.0
- ```
- To use the new `status-page` converter:
- + 9 more
📦 Verified
- ✅ All package tests pass across `@dualmark/*` (build 7/7, test 7/7, typecheck 7/7)
- ✅ Conformance E2E: `examples/deno-deploy` 125/125, `examples/astro-cloudflare-full` 125/125, `examples/nextjs-app-router` 120/125
📦 Highlights
- Two features land together in this release:
- Broader AI bot coverage — the crawler registry now detects DeepSeek, Anthropic's new Claude-SearchBot and Claude-User, Meta's ExternalFetcher, and Perplexity-User. If any of these hit your site, they now get the markdown twin instead of HTML soup.
- `integrationConverter` — a new built-in converter for marketplace-style "Connect X to Y" pages (vendor, categories, capabilities, optional setup, pricing, requirements). Drop `converter: "integration"` into an Astro or Next.js collection and integration pages get the same battle-tested markdown layout as blog posts.
- No breaking changes. Drop-in upgrade from `0.6.x`.
📦 `@dualmark/core@0.7.0`
- Extend the AI Agent Registry with 5 new bots ([`6155878`](https://github.com/dodopayments/dualmark/commit/6155878)):
- `DeepSeekBot` (DeepSeek)
- `Claude-SearchBot` (Anthropic — search-time fetcher)
- `Claude-User` (Anthropic — claude.ai on-demand fetch)
- `Meta-ExternalFetcher` (Meta — user-action fetch from Meta AI)
- `Perplexity-User` (Perplexity — user-action fetch)
- Tighten the `Meta-ExternalFetcher` UA pattern to avoid false positives ([`0377a0e`](https://github.com/dodopayments/dualmark/commit/0377a0e)) and classify its `purpose` as `user-action` rather than `training` ([`951f373`](https://github.com/dodopayments/dualmark/commit/951f373)) — matches Meta's published bot semantics.
- AEO spec AI Agent Registry table is synced with the new entries.
📦 `@dualmark/converters@0.7.0`
- New: `integrationConverter` ([`dbd8ef4`](https://github.com/dodopayments/dualmark/commit/dbd8ef4)) for marketplace integration pages. Handles:
- Vendor and integration metadata
- Categories + capabilities
- Optional setup steps, pricing, and requirements blocks
- Same brand-footer + breadcrumb conventions as the other converters
- Registered as the built-in `integration` resolver in both `@dualmark/astro` and `@dualmark/nextjs` — no config beyond `converter: "integration"`.
- Refactor: `integration` categories are now a structured field with a brandFooter test ([`42cc5f8`](https://github.com/dodopayments/dualmark/commit/42cc5f8)).
📦 `@dualmark/astro@0.7.0`, `@dualmark/nextjs@0.7.0`, `@dualmark/cli@0.7.0`, `@dualmark/cloudflare@0.7.0`
- Version bumps to pick up the new `core` + `converters` (and the `integration` resolver registration in `astro` / `nextjs`). No API changes.
📦 Upgrade
- ```bash
- bun add @dualmark/astro@^0.7.0
- bun add @dualmark/nextjs@^0.7.0
- bun add @dualmark/cloudflare@^0.7.0
- bun add -g @dualmark/cli@^0.7.0
- ```
- To use the new `integration` converter:
- ```ts
- + 8 more
📦 Verified
- ✅ All 313 tests pass across `@dualmark/*` packages
- ✅ Typecheck clean
- ✅ Conformance E2E: `examples/astro-cloudflare-full` still 125/125, `examples/nextjs-app-router` 120/125
📋 Full changelogs
- [@dualmark/core](https://github.com/dodopayments/dualmark/blob/main/packages/core/CHANGELOG.md)
- [@dualmark/converters](https://github.com/dodopayments/dualmark/blob/main/packages/converters/CHANGELOG.md)
- [@dualmark/astro](https://github.com/dodopayments/dualmark/blob/main/packages/astro/CHANGELOG.md)
- [@dualmark/nextjs](https://github.com/dodopayments/dualmark/blob/main/packages/nextjs/CHANGELOG.md)
- [@dualmark/cloudflare](https://github.com/dodopayments/dualmark/blob/main/packages/cloudflare/CHANGELOG.md)
- [@dualmark/cli](https://github.com/dodopayments/dualmark/blob/main/packages/cli/CHANGELOG.md)
- Full diff: [v0.6.0...v0.7.0](https://github.com/dodopayments/dualmark/compare/v0.6.0...v0.7.0)
📦 Highlights
- Security release. Bumps the \`astro\` peer dependency to \`^6.1.10\` to resolve two upstream advisories that were never backported to Astro 5:
- 🔐 [GHSA-j687-52p2-xcff](https://github.com/withastro/astro/security/advisories/GHSA-j687-52p2-xcff) ([CVE-2026-41067](https://nvd.nist.gov/vuln/detail/CVE-2026-41067), moderate) — XSS in \`define:vars\` via incomplete \`</script>\` tag sanitization. Patched in Astro 6.1.6.
- 🔐 [GHSA-xr5h-phrj-8vxv](https://github.com/withastro/astro/security/advisories/GHSA-xr5h-phrj-8vxv) ([CVE-2026-45028](https://github.com/withastro/astro/security/advisories/GHSA-xr5h-phrj-8vxv), low) — Server island encrypted parameters vulnerable to cross-component replay. Patched in Astro 6.1.10.
- If you ship \`@dualmark/astro\` on a public site, upgrade.
💥 Breaking changes
- \`@dualmark/astro\` now requires \`astro@^6.1.10\`. Astro 5 is no longer a supported peer. The integration uses only stable hooks (\`astro:config:setup\`, \`injectRoute\`, \`addMiddleware\`) and the Content Layer API — there are no source changes inside \`@dualmark/astro\` itself, but you'll need to run [Astro's v5 → v6 migration guide](https://docs.astro.build/en/guides/upgrade-to/v6/) on your own site.
- \`engines.node\` is now \`>=22.12.0\` across every published \`@dualmark/*\` package, matching Astro 6's hard Node 22 requirement.
📦 Upgrade
- \`\`\`bash
- node --version # → v22.x.x
- bun add @dualmark/astro@^0.6.0 astro@^6.1.10
- \`\`\`
📦 Verified end-to-end
- The conformance E2E suite (\`.github/workflows/conformance.yml\`) ran clean against Astro 6 on every push since the upgrade landed:
- ✅ \`examples/astro-blog\` — boots under \`astro dev\`, \`dualmark verify\` passes
- ✅ \`examples/astro-cloudflare-full\` — boots under \`wrangler dev\`, full 125/125 conformance
- ✅ All 313 unit/integration tests across \`@dualmark/*\` pass on Astro 6.3.1 (resolved from \`^6.1.10\`)
📋 Full changelogs
- [@dualmark/astro](https://github.com/dodopayments/dualmark/blob/main/packages/astro/CHANGELOG.md)
- [@dualmark/core](https://github.com/dodopayments/dualmark/blob/main/packages/core/CHANGELOG.md) (unchanged)
- [@dualmark/converters](https://github.com/dodopayments/dualmark/blob/main/packages/converters/CHANGELOG.md) (unchanged)
- [@dualmark/nextjs](https://github.com/dodopayments/dualmark/blob/main/packages/nextjs/CHANGELOG.md) (unchanged)
- [@dualmark/cloudflare](https://github.com/dodopayments/dualmark/blob/main/packages/cloudflare/CHANGELOG.md) (unchanged)
- [@dualmark/cli](https://github.com/dodopayments/dualmark/blob/main/packages/cli/CHANGELOG.md) (unchanged)
📦 Highlights
- \`\`\`bash
- npm audit signatures
- \`\`\`
- No API changes inside any package — this is a release-pipeline upgrade.
📦 \`@dualmark/astro\` 0.5.2
- ✨ Added \`seo\`, \`performance\`, \`optimization\` keywords to enable auto-discovery by the [Astro Integrations catalog](https://astro.build/integrations/). \`@dualmark/astro\` will appear under "Performance + SEO" on the next weekly catalog sync (no runtime change).
📦 All \`@dualmark/*\` packages 0.5.2
- 🔐 Release pipeline switched from \`bun publish\` to \`bun pm pack\` + \`npm publish --provenance\` (because bun 1.3.5 doesn't yet support \`--provenance\` — see [oven-sh/bun#15601](https://github.com/oven-sh/bun/issues/15601)).
- 📝 \`CONTRIBUTING.md\` updated with the new release flow + how to verify provenance.
📋 Full changelogs
- [@dualmark/core](https://github.com/dodopayments/dualmark/blob/main/packages/core/CHANGELOG.md)
- [@dualmark/converters](https://github.com/dodopayments/dualmark/blob/main/packages/converters/CHANGELOG.md)
- [@dualmark/astro](https://github.com/dodopayments/dualmark/blob/main/packages/astro/CHANGELOG.md)
- [@dualmark/nextjs](https://github.com/dodopayments/dualmark/blob/main/packages/nextjs/CHANGELOG.md)
- [@dualmark/cloudflare](https://github.com/dodopayments/dualmark/blob/main/packages/cloudflare/CHANGELOG.md)
- [@dualmark/cli](https://github.com/dodopayments/dualmark/blob/main/packages/cli/CHANGELOG.md)
📋 Patch Changes
- `fix(nextjs)`: `withDualmark()` rejecting typed `NextConfig` from `next.config.ts` ([#26](https://github.com/dodopayments/dualmark/pull/26)).
- The internal `NextConfigShape` constraint had an `[key: string]: unknown` index
- signature, which TypeScript treats as a structural demand on the input. Next.js's
- `NextConfig` is a closed interface with no top-level index signature, so any
- caller passing a typed `next.config.ts` hit:
- ```
- Type 'NextConfig' is not assignable to type 'NextConfigShape'.
- Index signature for type 'string' is missing in type 'NextConfig'.
- + 15 more
📦 Other packages
- `@dualmark/core`, `@dualmark/converters`, `@dualmark/astro`, `@dualmark/cloudflare`, `@dualmark/cli` are unchanged at `0.5.0` (no changesets touched them this cycle).
- Full Changelog: https://github.com/dodopayments/dualmark/compare/v0.5.0...v0.5.1
✨ New: \`@dualmark/nextjs\` — first-class Next.js 15 App Router adapter
- Closes #4. Same one-line install as \`@dualmark/astro\`, with a small surface area:
- \`withDualmark(nextConfig, options)\` — wraps \`next.config.mjs\`
- \`createDualmarkMiddleware(options)\` — drop-in \`middleware.ts\`
- \`createDualmarkRouteHandler(options)\` — catch-all markdown twin route handler with \`generateStaticParams\`
- \`createLlmsTxtHandler(options)\` — \`/llms.txt\` route handler
📦 Install
- \`\`\`bash
- bun add @dualmark/nextjs @dualmark/core @dualmark/converters
- \`\`\`
📦 Minimal setup
- \`\`\`ts
- // middleware.ts
- import { createDualmarkMiddleware } from \"@dualmark/nextjs\";
- export default createDualmarkMiddleware({ siteUrl: \"https://example.com\" });
- export const config = {
- matcher: [
- {
- source: \"/((?!_next/|favicon.ico|md/).*)\",
- + 20 more
📦 Migration from manual \`@dualmark/core\` setup
- If you wired \`@dualmark/core\` into Next.js by hand before this release, the migration is mechanical:
- | Before (\`@dualmark/core\` only) | After (\`@dualmark/nextjs\`) |
- |---|---|
- | Hand-rolled \`middleware.ts\` with \`detectAIBot\` + \`negotiateFormat\` + manual rewrite | \`createDualmarkMiddleware({ siteUrl })\` |
- | Hand-rolled \`app/md/[...path]/route.ts\` with \`if\`-chains | \`createDualmarkRouteHandler({ siteUrl, collections, staticPages, parameterizedRoutes })\` |
- | Hand-rolled \`app/llms.txt/route.ts\` calling \`renderLlmsTxt\` | \`createLlmsTxtHandler({ brandName, sections })\` |
- | Manual \`transpilePackages: [...]\` | \`withDualmark(nextConfig, options)\` |
- The internal namespace, response headers, and conformance score are unchanged. Full guide: [docs.dualmark.dev/docs/integrations/nextjs](https://docs.dualmark.dev/docs/integrations/nextjs).
📦 Coordinated patch bumps
- The linked \`@dualmark/*\` changeset group means every package gets a coordinated version bump:
- \`@dualmark/nextjs\` 0.5.0 (new)
- \`@dualmark/core\` 0.3.1 → 0.5.0
- \`@dualmark/converters\` 0.3.1 → 0.5.0
- \`@dualmark/astro\` 0.3.1 → 0.5.0
- \`@dualmark/cloudflare\` 0.3.1 → 0.5.0
- \`@dualmark/cli\` 0.3.1 → 0.5.0
- No source-level changes to the other five packages — just version metadata bumps so internal \`workspace:*\` deps resolve cleanly when consumers install \`@dualmark/nextjs\`.
📦 Verified
- Full monorepo: 313 tests across 6 packages, build + test + typecheck green on CI
- \`examples/nextjs-app-router\` E2E in CI: \`next dev\` + \`dualmark verify\` → 120/125
- Local verification: \`next dev\` and \`next start\` both score 120/125
- Docs site dogfood (\`apps/docs\`): every doc page ≥ 105/125
- [Full PR](https://github.com/dodopayments/dualmark/pull/24) · [Issue #4](https://github.com/dodopayments/dualmark/issues/4)
🐛 v0.3.1 — Hotfix: workspace dep resolution + landing visual polish
- Patch release fixing one critical packaging bug introduced upstream by `bun publish` and one set of landing-page visual inconsistencies.
- > Strongly recommended upgrade for anyone on 0.3.0 — fresh installs of 0.3.0 resolve mismatched workspace versions due to a `bun publish` lockfile-metadata bug.
- ---
📦 Critical: stale `@dualmark/core` pin in 0.3.0 tarballs
- Two-layer fix (defense in depth):
- 1. The `version-packages` script now chains `bun install --lockfile-only` after `changeset version`, so the version PR commits a refreshed lockfile.
- 2. `release.yml` runs the same command after checkout/setup as a self-healing safety net for tagged releases.
- Verification: `bun pm pack` on `packages/cli` with the refreshed lockfile correctly emits `"@dualmark/core": "0.3.1"` in the packed `package.json`.
- ---
📦 Landing-page visual polish
- Hero: removed full-viewport `border-b` that produced a stray horizontal hairline below the terminal demo.
- Page rails: promoted z-index from `0` to `10` so rails render above the hero `BeamsBackground` gradients (previously the bottom radial fade obscured rails inside the hero).
- Navbar: scoped the bottom border to its inner `max-w-7xl` column so it terminates at the rails instead of running full-viewport.
- Section dividers: shared `<Section>` component now renders a top hairline between the rails (via new `divider` prop, default `true`). Every landing-page section transition has a clean ┬ intersection at both rail crossings, giving the page consistent vertical rhythm.
- No package source-code changes; landing fixes affect `apps/docs/` only.
- ---
📦 Commits in this release
- [`fix(landing): rails framing — z-index, scoped borders, section dividers`](https://github.com/dodopayments/dualmark/commit/e5c0d10)
- [`fix(release): refresh bun.lock workspace metadata before publish`](https://github.com/dodopayments/dualmark/commit/1c3f318)
- [`chore: refresh bun.lock workspace metadata to 0.3.0`](https://github.com/dodopayments/dualmark/commit/f6c0d1e)
- [`chore: changeset for 0.3.1 — workspace dep resolution hotfix + landing polish`](https://github.com/dodopayments/dualmark/commit/fbc7b17)
- [`chore: version packages (#3)`](https://github.com/dodopayments/dualmark/commit/bd68f5e)
- ---
📦 Migration
- From 0.3.0: `bun update @dualmark/*` (or your equivalent). No code changes required. Strongly recommended.
- From 0.2.x: see the [v0.3.0 changelog](https://github.com/dodopayments/dualmark/releases/tag/v0.3.0) for the relicense + identity changes; this 0.3.1 release rolls those forward with the dep fix.
📦 Verified
- 266 tests pass across 5 packages
- typecheck 10/10 green
- All 5 packages publish at `0.3.1` with correctly resolved cross-package dependencies (`"@dualmark/core": "0.3.1"`).
- ---
📦 License
- Apache 2.0. See `LICENSE` and `NOTICE`.
📦 v0.3.0 — Landing rewrite, Apache 2.0 relicense, /play polish
- If you're already on 0.2.1 and don't care about the relicense announcement, you can skip this version with no functional impact. The published tarballs are functionally byte-equivalent to 0.2.1.
📦 Highlights
- Apache 2.0 includes an explicit patent grant that matters for infrastructure libraries touching standard-tracking work (content negotiation, AI bot UA detection, llms.txt).
- Existing 0.2.x installs are unaffected. Downstream redistributors and forks should now reference Apache 2.0 + the new `NOTICE` file.
- New tagline: "ChatGPT cites your competitor — that's an infrastructure problem."
- 7-section narrative: Hero → PlaygroundTeaser → Transform → CaseStudy → ConformanceDemo → Adapters → CTA.
- New Dodo Payments case study with a real customer proof point: 5× lift in AI agent traffic over 2 months.
- New page rails — Vercel-style vertical hairlines framing the content column on every page.
- Cut three weak sections (TrustStrip, Architecture diagram, standalone Converters page) and folded Converters into Adapters as an inline chip strip.
- Promoted the playground teaser to second-position so visitors can score their own site immediately.
- + 15 more
📦 Migration
- Code: none required.
- License notices: redistributors should update `LICENSE` references from MIT to Apache 2.0 and include the `NOTICE` file.
- CLI: prefer `bunx @dualmark/cli verify <url>` for consistency. `npx @dualmark/cli verify <url>` still works.
📦 Verified
- 266 tests pass across 5 packages
- `bun run typecheck` 10/10
- Build green; landing page zero horizontal overflow at 1440 / 768 / 390 px
- Playground layout parity verified at all three widths
📦 Atomic commit history (this release window)
- ```
- 76b65c3 chore: version packages (#2)
- f1a0eb0 chore: changeset for 0.3.0 — landing rewrite, Apache 2.0, /play polish
- 1433a41 docs: fix stale claims, version drift, and unify CLI invocation on bunx
- 3eeead7 fix(seo): align metadata with problem-first positioning
- 621063c feat(play): align layout with new landing — rails, contained background, max-w-7xl
- ba9603a refactor(landing): tighten narrative, add page rails
- 5d37806 feat(landing): add Dodo Payments case study and playground teaser
- + 5 more
📦 What was broken in 0.2.0
- ```
- bun add @dualmark/cli
- npm install @dualmark/cli
- ```
🐛 Fix
- Switched the release workflow from `changeset publish` to a per-package loop using `bun publish`. Bun correctly rewrites `workspace:*` → the actual pinned version at pack time. Verified:
- | Package | 0.2.0 (broken) | 0.2.1 (fixed) |
- |---|---|---|
- | `@dualmark/cli` | `"@dualmark/core": "workspace:*"` | `"@dualmark/core": "0.2.1"` |
- | `@dualmark/astro` | `"@dualmark/core": "workspace:*", "@dualmark/converters": "workspace:*"` | `"@dualmark/core": "0.2.1", "@dualmark/converters": "0.2.1"` |
- | `@dualmark/cloudflare` | `"@dualmark/core": "workspace:*"` | `"@dualmark/core": "0.2.1"` |
📦 Migration
- Just upgrade. There are no API or behavioral changes from 0.2.0 to 0.2.1 — only the dependency declarations were broken.
- ```bash
- bun add @dualmark/astro@0.2.1 @dualmark/core@0.2.1 @dualmark/converters@0.2.1
- ```
- Or for a fresh install, just install latest:
- ```bash
- bun add @dualmark/astro
- ```
📦 Packages republished at 0.2.1
- | Package | npm |
- |---|---|
- | `@dualmark/core` | `npm i @dualmark/core` |
- | `@dualmark/converters` | `npm i @dualmark/converters` |
- | `@dualmark/astro` | `npm i @dualmark/astro` |
- | `@dualmark/cloudflare` | `npm i @dualmark/cloudflare` |
- | `@dualmark/cli` | `npm i -g @dualmark/cli` |
- The 0.2.0 versions will be marked `npm deprecate` after this release lands.
📦 Links
- [Docs](https://dualmark.dev/docs)
- [AEO Spec v1.0](https://dualmark.dev/docs/spec/overview)
- [Score your site](https://dualmark.dev/play)
📦 What ships
- | Package | Version | npm |
- |---|---|---|
- | `@dualmark/core` | 0.2.0 | `npm i @dualmark/core` |
- | `@dualmark/converters` | 0.2.0 | `npm i @dualmark/converters` |
- | `@dualmark/astro` | 0.2.0 | `npm i @dualmark/astro` |
- | `@dualmark/cloudflare` | 0.2.0 | `npm i @dualmark/cloudflare` |
- | `@dualmark/cli` | 0.2.0 | `npm i -g @dualmark/cli` |
- All published with [npm provenance](https://docs.npmjs.com/generating-provenance-statements).
📦 `@dualmark/converters` — 12 generic converters
- Replaces the original fintech-specific factories. Now ships with general-purpose converters for any marketing site:
- `featureConverter` — feature/product pages with siblings, FAQ, problem/solution
- `pseoConverter` — programmatic SEO (calculator pages, location pages, etc.)
- `pricingConverter` — tier comparison with recommended badge + CTAs
- `compareConverter` — "us vs. competitor" / "alternatives" pages
- `caseStudyConverter` — customer wins with optional pull-quote
- `changelogConverter` — release notes (Keep-a-Changelog style)
- `docsConverter` — documentation pages with section grouping
- + 1 more
📦 `@dualmark/cli` — `dualmark verify <url>`
- `dualmark verify --help` and `dualmark verify -h` now work as expected (print help, exit 0). Internal: `cli.ts` is a thin shim over `main.ts` to eliminate duplicate parsing logic.
📦 `@dualmark/core` — API consolidation
- Path utilities and analytics types consolidated. Public primitives (`detectAIBot`, `negotiateFormat`, `buildMarkdownResponse`, `renderLlmsTxt`) unchanged.
📦 Quick start
- ```bash
- bun add @dualmark/astro @dualmark/core @dualmark/converters
- ```
- ```ts
- // astro.config.mjs
- import dualmark from "@dualmark/astro";
- export default defineConfig({
- site: "https://yourcompany.com",
- + 13 more
📦 Verify any site
- ```bash
- bunx @dualmark/cli verify https://yourcompany.com/pricing
- ```
- The same engine powers [dualmark.dev/play](https://dualmark.dev/play).
📦 Migration from a previous local install
- If you'd installed pre-release builds from this repo:
- ```diff
- import { productConverter, taxConverter, countryConverter } from "@dualmark/converters";
- + import { featureConverter, pseoConverter } from "@dualmark/converters";
- ```
- Removed: `productConverter`, `taxConverter`, `countryConverter`, `currencyConverter`, `paymentMethodConverter`, `caseStudyConverter.paymentProvider`.
- Use `featureConverter` for product/feature pages and `pseoConverter` for programmatic SEO. See per-package CHANGELOGs for full details:
- [packages/core/CHANGELOG.md](https://github.com/dodopayments/dualmark/blob/v0.2.0/packages/core/CHANGELOG.md)
- + 4 more
📦 Links
- [Docs](https://dualmark.dev/docs)
- [AEO Spec v1.0](https://dualmark.dev/docs/spec/overview)
- [Score your site](https://dualmark.dev/play)
- [GitHub](https://github.com/dodopayments/dualmark)
