116 Commits

Author SHA1 Message Date
MoreminiMore
69c4ba6bbe feat: add contact SMTP API, pricing section, and nodemailer
Some checks failed
PR Sweep / Sweep Open PRs (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Tests (push) Has been cancelled
CI / Validate Plugins (push) Has been cancelled
CI / Smoke Tests (push) Has been cancelled
CI / Integration Tests (push) Has been cancelled
CI / Browser Tests (push) Has been cancelled
CI / E2E tests (1/8) (push) Has been cancelled
CI / E2E tests (2/8) (push) Has been cancelled
CI / E2E tests (3/8) (push) Has been cancelled
CI / E2E tests (4/8) (push) Has been cancelled
CI / E2E tests (5/8) (push) Has been cancelled
CI / E2E tests (6/8) (push) Has been cancelled
CI / E2E tests (7/8) (push) Has been cancelled
CI / E2E tests (8/8) (push) Has been cancelled
Seed Marketplace Plugins / Seed Plugins (push) Has been cancelled
Format / Format (push) Has been cancelled
Preview Releases / Publish Preview (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
- Replace contact form with AJAX fetch + /api/contact endpoint
- Add nodemailer SMTP integration for email sending
- Add pricing cards section to web-development.astro
- Fix package.json nodemailer catalog entry
2026-04-08 08:30:55 +07:00
Joost de Valk
12d73ff456 Add OG Image field to content editor (#328)
* Add OG Image field to content editor

The `_emdash_seo` table and content API already support `seo_image`, but
the admin UI had no way to set it. This adds:

- `SeoImageField` component using the existing `MediaPickerModal`
- 2-column grid layout placing the OG Image next to the Featured Image
- `description` prop on `ImageFieldRenderer` for helper text below images
- Preserve `seo.image` in `SeoPanel.emitChange` so sidebar edits don't
  clear the image

Closes #327

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* style: format

* Add changeset and fix stale seo.image in SeoPanel

- Add changeset for @emdash-cms/admin patch release
- Remove image from SeoPanel.emitChange to avoid overwriting
  a freshly-selected OG image with a stale prop value

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Address review feedback on OG Image field

- Fix #1: Use @phosphor-icons/react instead of lucide-react
- Fix #2: Send minimal patch { image } instead of spreading stale seo props
- Fix #3: Only show OG Image next to the featured_image field, not all image fields
- Fix #4: Only add description text for the featured_image field
- Fix #5: Add responsive breakpoint (grid-cols-1 md:grid-cols-2)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* style: format

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com>
Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-07 23:14:54 +01:00
Matt Kane
d6cfc437f2 fix: migration 033 idempotency & smoke test cleanup (#365)
* 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
2026-04-07 22:00:54 +00:00
Benjamin Price
f112ac4819 fix: use stable site hash for install telemetry deduplication (#298)
* fix: use stable site hash for install telemetry deduplication (#297)

generateSiteHash() used Date.now() as the hash seed, producing a different
hash on every call. Since the installs table uses PRIMARY KEY (plugin_id,
site_hash), the same site could insert unlimited rows, inflating install
counts and making "Most Popular" sorting meaningless.

Fix: use the site's request origin as a stable hash seed. The same origin
always produces the same hash, so the marketplace deduplicates correctly.

Also denormalizes install_count on the plugins table to avoid a COUNT(*)
subquery per row in searchPlugins(). The count is recalculated atomically
on each upsertInstall() call.

Fixes #297

* chore: add changeset for install telemetry fix

* fix: address review feedback on install telemetry

- Replace crypto.subtle fallback with FNV-1a hash to avoid origin
  leakage and collisions from truncated seed strings
- Remove duplicate p.install_count from SELECT (p.* already includes it)
- Use explicit p.install_count in ORDER BY clause
- Use db.batch() for atomic upsert + count recomputation instead of
  separate statements with misleading meta.changes check
2026-04-07 22:37:00 +01:00
Matt Kane
91e31fb2ca fix: validate sandbox plugin exports and fix plugin packaging (#363)
* fix(webhook-notifier): add build step and export built files

The webhook-notifier plugin exported raw TypeScript source from its
package.json exports (./sandbox pointed to src/sandbox-entry.ts).
When the Vite plugin resolved this at site build time, it embedded
unbuilt TypeScript into the sandbox module, causing "Unexpected token
'{'" errors at runtime.

Add a tsdown build step (matching sandboxed-test's pattern) and update
the exports map to point to dist/*.mjs.

Fixes #150

* fix(core): reject unbuilt source in sandbox module generator and bundle validator

Add two validation checks to prevent plugins with misconfigured exports
from silently breaking site builds:

1. generateSandboxedPluginsModule() now throws a clear error if a
   sandbox entrypoint resolves to a TypeScript/JSX source file instead
   of pre-built JavaScript. This catches the problem at site build time
   with an actionable message.

2. The `emdash bundle` command now validates that all package.json
   exports point to built files (.js/.mjs), not source (.ts/.tsx/.jsx).
   This catches the misconfiguration at plugin publish time, before
   consumers are affected.

Fixes #150

* chore: add changeset for sandbox source validation

* fix: use slash syntax for e18e rule override in oxlintrc

The test file override for e18e/prefer-static-regex used parenthesis
syntax ("e18e(prefer-static-regex)") which is the diagnostic display
format, not the config format. Changed to slash syntax to match the
top-level rule declarations so the override actually takes effect.

* test: add tests for sandbox source validation

Add tests for both validation checks:

- generateSandboxedPluginsModule: verifies it embeds pre-built JS,
  rejects .ts/.tsx/.mts source files, and includes the plugin ID in
  error messages.

- findSourceExports: verifies it flags .ts/.tsx/.mts/.cts/.jsx exports,
  accepts .mjs/.js exports, and handles conditional export maps.

Also extracts findSourceExports() from the inline bundle.ts validation
into bundle-utils.ts so it can be tested without the CLI harness.

* fix(atproto, audit-log): add build step and export built files

Same issue as webhook-notifier — both plugins exported raw TypeScript
source from their package.json sandbox exports. Add tsdown build steps
and update exports to point to dist/*.mjs.

* refactor(smoke): replace sequential per-site astro builds with recursive pnpm build

The build verification section was running `astro build` individually
and sequentially for every demo and template (~12 sites). Replace with
a single `pnpm run --recursive --filter {./demos/*} --filter
{./templates/*} build` which pnpm parallelizes automatically.
2026-04-07 22:34:35 +01:00
Matt Kane
885df3b3a8 test(smoke): add astro build verification for all demos and templates (#361)
Smoke tests only ran astro dev, which uses Vite's on-demand compilation
and never invokes the adapter build pipeline. Build failures in
cloudflare/playground demos (or any adapter-dependent site) passed CI
undetected. Add a build verification suite that runs astro build for
every site in the matrix before the existing runtime tests.

Bumps smoke test CI timeout from 15 to 30 minutes to accommodate.
2026-04-07 19:07:07 +00:00
Matt ‘TK’ Taylor
5b3e33c26b fix: adds optimize indexes (33) to migration runner (#330)
* fix: adds optimize indexes (33) to migration runner

* chore: add changeset for migration 033 runner registration fix

* test: update migration count assertions for 033_optimize_content_indexes
2026-04-07 11:52:55 +01:00
James Garbutt
a996387de4 test(gutenberg-to-portable-text): add transform tests (#332)
* test(gutenberg-to-portable-text): add transform tests

This adds a bunch of tests, mostly for the transformers but also some
minor edge cases in the inline parser, too.

It also enables `noUnusedLocals` in `tsconfig.json` which caught a
couple of unused things.

* chore: add domain to each

* style: format

* chore: remove some figures

---------

Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com>
2026-04-07 07:36:14 +01:00
Hasan Smadi
dbaf8c6f85 fix(visual-editing): don’t open admin for portableText; simplify starter PT markup (#40)
* fix(visual-editing): PT inline editing; align starter templates

* chore(admin): format router.tsx

---------

Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-06 20:10:09 +00:00
Sarah Dayan
ec1e71ec2f fix: adjust user menu button height for avatar content (#77)
Override the fixed h-6.5 from Kumo's sm size with h-auto and py-1 so
the button sizes naturally around the avatar. The sm size is still used
for text size, gap, and border-radius — only the height is overridden,
since this is a usage-specific concern (tall content inside a small
button) rather than a design system issue.

Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-06 21:09:12 +01:00
Delowar Hossain
fe74f8a33e Hide preview button unless collection supports preview and content is published (#70)
* Hide preview button unless collection supports preview and content is published

* Remove isPublished check

---------

Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-06 21:07:50 +01:00
Doğu Abaris
ab21f29f71 fix(admin): avoid locally caught exception in PasskeyLogin (#268)
* fix(admin): avoid locally caught exception in PasskeyLogin

Why:

The passkey login flow threw an error when navigator.credentials.get()
returned no credential, but that exception was immediately caught by the
local catch block in the same function. This triggered a
"throw of exception caught locally" warning and made the failure path
less direct.

What:

- Handle the missing credential case inline instead of throwing locally
- Preserve the existing error message shown to the user
- Keep the onError callback behavior unchanged

* Add changeset

---------

Co-authored-by: Matt Kane <m@mk.gg>
Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-06 20:05:16 +00:00
Matt Van Horn
b297fdd88d fix: allow public access to search API for frontend LiveSearch (#107)
* fix: allow public access to search and suggest API endpoints

The search and suggest endpoints required search:read permission,
blocking unauthenticated visitors from using the LiveSearch component.
This is safe because the search query layer defaults to status=published,
so public users only see published content.

Fixes #104

* fix: add changeset for public search API access

Patch bump for emdash - allows public access to search API endpoints.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Matt Kane <mkane@cloudflare.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 20:01:28 +00:00
jul
71744fb8b2 align back button position in API Tokens section (#306)
* replace link with button for back navigation

* changeset
2026-04-06 20:43:38 +01:00
Bryan Robinson
660eed2b76 Adds emdashbot to allowlist for CLA (#311) 2026-04-06 18:16:38 +01:00
Flynsarmy
5f448d1035 Add Back navigation to Security and Domain settings pages (#45)
* Add Back navigation to Security and Domain settings pages

* changeset

---------

Co-authored-by: Matt Kane <mkane@cloudflare.com>
Co-authored-by: Matt Kane <m@mk.gg>
2026-04-06 10:46:22 +00:00
Jonah Foster
de251fc039 Fix drag-and-drop reordering for custom fields in content type editor (#108)
Wire up @dnd-kit sortable integration in ContentTypeEditor and connect the existing reorderFields API. The grab handle icon was visual-only with no drag functionality attached.

Closes #43

Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-06 07:26:41 +00:00
Benjamin Price
8c693b582d fix: prevent media upload OOM on Workers for large images (#262)
* fix: prevent media upload OOM on Workers via client thumbnails + server safety net

Large image uploads (5MB+) crash Cloudflare Workers (128MB limit) because
generatePlaceholder() decodes entire images to raw RGBA pixels. A 4000x3000
JPEG becomes ~48MB RGBA, exceeding the isolate memory budget.

Two-layer fix:
- Client-side: browser generates a 64px canvas thumbnail for oversized images
  and sends it alongside the upload. Server generates blurhash from the
  thumbnail (~16KB RGBA) instead of decoding the full image.
- Server-side: reads dimensions from image headers via image-size and skips
  placeholder generation when estimated decoded size exceeds 32MB. This covers
  API/CLI uploads that don't provide thumbnails.

* chore: add changeset for media upload OOM fix

* fix: clamp upload thumbnail to 64x64 box for extreme aspect ratios

Naive sizing (thumbW=64, thumbH=(h/w)*64) could produce an enormous canvas
for very tall or very wide images — e.g. a 100x840000 image would allocate
a 64x537600 canvas client-side, reintroducing the memory blowup this feature
exists to prevent.

Extract computeThumbnailSize() that fits the image within a 64x64 box by
scaling against max(width, height), wrap canvas allocation and drawImage
in try/catch with a no-thumbnail fallback, and add unit tests covering
extreme aspect ratios.

---------

Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-06 07:14:39 +00:00
all3f0r1
73b71b4e59 fix(admin): apply data-mode attribute for system theme preference (#97)
When theme is "system", ThemeProvider removed the data-mode attribute
from <html>, expecting color-scheme: light dark to handle dark mode.
However, Tailwind dark: utilities are mapped to [data-mode="dark"] via
@custom-variant and do not respond to color-scheme, so dark mode never
activated for system preference users.

Decouple DOM synchronization from the theme preference by syncing
data-mode with resolvedTheme instead. This ensures data-mode is always
set to "light" or "dark" regardless of whether the user chose explicitly
or follows system preference.

Fixes #96

Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-06 06:54:37 +00:00
seslly
d2114523a5 fix: passkeys behind TLS reverse proxy (#225)
* fix: passkeys behind TLS reverse proxy

Add passkeyPublicOrigin and wire it through passkey routes so origin/rpId match
the browser when dev runs behind nginx. Expose dev-only /_emdash/api/dev/passkey-url,
add admin messaging for insecure WebAuthn contexts, nginx repro under demos/simple,
and direct kysely dependency for the simple demo Node adapter bundle.

Made-with: Cursor

* docs: add passkeyPublicOrigin to configuration reference

Adds the new passkeyPublicOrigin option and reverse proxy guidance
to the public-facing configuration docs as requested in PR review.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* update tests and more docs

* fix: add missing refresh-server-pat fixture and restore docs heading

---------

Co-authored-by: Joseph Eftekhari <jdeftekhari@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 07:41:07 +01:00
Sarah Dayan
28f98fda4f Fix header user menu button shifting on open (#74)
Base UI's PopoverTrigger injects invisible focus guard <span> elements
as siblings when the popover opens. The space-x-2 utility (which uses
> * + *) applied margin to these spans, causing the button to shift.

Replace space-x-2 with gap-2 which is unaffected by DOM changes.

Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-06 07:32:33 +01:00
Matt Kane
f5d0e8dd17 fix(ci): query check runs instead of commit statuses for CLA labels (#289)
* fix(ci): query check runs instead of commit statuses for CLA labels

The CLA Assistant action (contributor-assistant/github-action) reports
results as check runs, not commit statuses. The labeling step was
querying listCommitStatusesForRef which always returned an empty array,
so CLA labels were never applied to PRs.

Switch to checks.listForRef and match on the CLAssistant check run name
and conclusion. Add checks: read permission.

* fix(ci): split CLA labeling into separate job to avoid race condition

The label step was in the same job as the CLA check, so the CLAssistant
check run was still in_progress when queried — labels were never applied.
Move labeling to a separate job with needs: CLAssistant so the check run
is completed before we read its conclusion.

Also add issues: write permission for creating repo-level labels.
2026-04-06 07:29:55 +01:00
Matt Kane
5beb0ddc33 refactor: split smoke and integration test configs into separate CI jobs (#264)
* refactor: split smoke and integration test configs into separate CI jobs

* fix: move CLA labeling from triage to CLA workflow

* fix: install formatters in temp dir to avoid catalog: protocol error

* fix: handle 404 when removing labels that don't exist on the PR
2026-04-05 08:22:17 +01:00
Matt Kane
c4977e1fd1 chore: add PR automation workflows for triage, formatting, staleness, and overlap detection (#263) 2026-04-05 07:03:06 +00:00
Filip Ilić
9d10d2791f fix(admin): use collection urlPattern for preview button fallback URL (#181)
* fix(admin): use collection urlPattern for preview button fallback URL

The preview button hardcoded fallback URLs as /${collection}/${slug},
ignoring the collection's urlPattern setting. Collections with custom
URL patterns (e.g. urlPattern: "/biljke/{slug}" on a "biljka" collection)
would open a 404 instead of the correct page.

Thread urlPattern through the manifest and use it in the ContentEditor
preview fallback.

Fixes #167

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Signed-off-by: Filip Ilic <ilic.filip@gmail.com>

* chore: add changeset for preview URL pattern fix

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Signed-off-by: Filip Ilic <ilic.filip@gmail.com>

---------

Signed-off-by: Filip Ilic <ilic.filip@gmail.com>
Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-04 19:00:28 +00:00
Matt Kane
3674d4857a docs: upgrade docs site to Astro 6 and update Node.js prerequisites (#244)
Upgrades the docs site from Astro 5/Starlight 0.37 to Astro 6/Starlight 0.38.
Adds Cloudflare adapter for deployment. Updates Node.js prerequisites
across all docs to match Astro 6's requirement of v22.12.0+.
Bumps catalog versions for @astrojs/cloudflare and wrangler.
2026-04-04 19:59:00 +01:00
Justin White
9269759674 fix: magic links missing root prefix (#133)
* Fix magic links

* Include changeset

---------

Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-04 19:47:05 +01:00
Matt Kane
8fb4173036 fix: format router.tsx to pass oxfmt check 2026-04-04 16:00:27 +01:00
jul
66beb4da1f fix DOM XSS via unvalidated form redirects (#120)
* implement safe url validation for redirects

added validation for safe redirect urls to prevent xss attacks

* add changeset: fix dom xss in form redirects
(marked as patch version bump for @emdash-cms/plugin-forms)

---------

Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-04 15:51:36 +01:00
Matt Kane
9ebc8b1f3f docs: audit and fix documentation for release (#230)
* docs: fix critical errors in import paths, types, and API references

- Fix Cloudflare adapter imports: d1/r2 come from @emdash-cms/cloudflare, not emdash/db or emdash/astro
- Fix PortableText import path: emdash/ui, not emdash/astro
- Replace set:html with PortableText component for Portable Text content
- Fix CLI binary alias: em, not ec
- Fix media upload API: POST multipart to /api/media, not JSON to /api/media/upload
- Fix MediaValue type: src not url, provider is optional, add previewUrl
- Fix EmDashMedia to Image component (actual export name)
- Fix Cloudflare Access auth config: use access() function, not nested object
- Fix REST API methods: content/media update is PUT not PATCH, settings is POST not PUT
- Fix contributing docs: Node.js 22+, pnpm 10+, correct E2E test command
- Fix WordPress migration: remove undocumented CLI import command

* docs: fix high-priority technical errors across docs

- Fix hook names: beforeSave/afterSave, not beforeCreate/afterCreate
- Fix status values: draft/published/scheduled, not archived
- Fix field type count: 14, not 15
- Fix MCP tool count: 33, not 28
- Fix Section.previewUrl type: string, not object
- Fix getSections examples to show { items } destructuring
- Add missing CollectionSupport values: search, seo
- Update reserved field slugs to match actual code
- Add MCP server enablement note (mcp: true required)
- Clarify getStaticPaths guidance: themes must be SSR, other sites can use static
- Delete orphaned duplicate migration/plugin-porting.mdx

* docs: fix medium-priority issues across docs

- Fix broken internal links: /guides/media/ -> /guides/media-library/, /guides/seeding/ -> /themes/seed-files/
- Standardize env var to EMDASH_PREVIEW_SECRET throughout preview guide
- Fix featuredImage -> featured_image in widgets guide
- Remove Discord social link (no Discord server exists)
- Fix formatting config reference: .oxfmtrc.json, not .prettierrc
- Add audienceEnvVar to Cloudflare Access config options
- Fix content model type declarations to show actual return types

* docs: document missing plugin hooks, capabilities, and context properties

- Add 10 missing hooks to reference: cron, email (beforeSend, deliver, afterSend),
  comment (beforeCreate, moderate, afterCreate, afterModerate), page (metadata, fragments)
- Document all hook event types, handler signatures, and return values
- Add exclusive hook option to configuration tables
- Add 6 missing capabilities: network:fetch:any, read:users, email:send/provide/intercept, page:inject
- Add 6 missing context properties: ctx.site, ctx.url(), ctx.users, ctx.cron, ctx.email
- Update hooks reference tables in both plugins/hooks.mdx and reference/hooks.mdx

* Format
2026-04-04 09:17:00 +01:00
Mason Hall
036e0fc23a fix(x402): add tsdown config to build middleware entry point (#48)
* fix(x402): add tsdown config to build middleware entry point

* adds optimizeDeps.exclude and ssr.optimizeDeps.exclude for @emdash-cms/x402 in the integration's Vite config

* fix CI typecheck

---------

Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-04 09:03:41 +01:00
Foysal Zihak
018be7f1c3 fix(admin): use infinite scroll for content list to support large dat… (#135)
* fix(admin): use infinite scroll for content list to support large datasets

* chore: apply copilot review suggestions and add changeset
2026-04-04 09:02:57 +01:00
saram ali
e9a6f7ac3c perf(db): optimize D1 indexes to eliminate full table scans (#214)
* perf(db): optimize D1 indexes to eliminate full table scans

- Add composite indexes to ec_* tables for common query patterns
- Replace single-column indexes with (deleted_at, updated_at, id) composite
- Add (deleted_at, status) index for count queries
- Add (deleted_at, created_at, id) index for chronological ordering
- Optimize comment counting with partial indexes per status
- Rewrite countByStatus() to use parallel WHERE queries instead of GROUP BY

Fixes #131

* chore: add changeset for D1 index optimization

* style: wrap changeset description for formatting compliance
2026-04-04 08:17:56 +01:00
Matt Kane
5b29819caf feat(docs): replace placeholder logos and favicon with brand assets (#224)
- Logo lockup SVGs (light/dark) replace dizzy emoji + text logos
- Favicon SVG replaces sparkle icon with gradient icon mark
2026-04-04 06:49:10 +00:00
Erez Rokah
85b3d1aacd chore: Tighten /format command trigger conditions (#201)
Use exact match and add author_association check for the /format
comment command workflow.
2026-04-03 22:02:11 +00:00
Matt Kane
12e0aa71bc feat(cloudflare): add logo branding to playground and preview pages (#202)
- Playground loading: replace "Em<span>Dash</span>" text with inline
  SVG icon mark + "EmDash" wordmark, add favicon
- Preview loading: add favicon
2026-04-03 21:48:13 +00:00
Will (liruifengv)
e4a44eca62 docs: fix repo links and update command for create project (#164)
Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-03 22:42:07 +01:00
Matt Kane
0aae9d806b docs: add changeset guidelines for contributors and agents (#198)
* docs: add changeset guidelines to contributing docs

Contributors and agents need to know when and how to add changesets.
Without one, changes to published packages won't trigger a release.

- CONTRIBUTING.md: full Changesets section with when/when-not, how to
  add, writing descriptions, examples for patch/minor/major
- AGENTS.md: concise changeset subsection using --empty for
  non-interactive use, added as step in PR flow
- PR template: changeset checkbox in checklist

* docs: note that multiple changes need separate changesets
2026-04-03 22:36:37 +01:00
Matt Kane
422018aeb2 feat(admin): add proper EmDash logo branding to admin UI (#200)
Replace placeholder text branding ("— EmDash") with actual logo SVGs
from the brand assets. Adds Logo.tsx with LogoIcon (icon mark) and
LogoLockup (icon + wordmark) components.

- Sidebar: gradient icon mark replaces em dash text character
- Login, Signup, Setup: full lockup SVG with currentColor wordmark
- Welcome modal: logo icon replaces Sparkle placeholder
- Favicon: real gradient icon SVG replaces emoji
2026-04-03 22:23:02 +01:00
Charlie Gleason
3089e3fa55 Update template display and detail on README.md (#44)
* Reposition template image links in README

* Fix formatting in README

---------

Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-03 19:28:00 +00:00
Cotton Hou
4f92c63702 fix(auth): secureCompare to reuse constantTimeEqual from @oslojs/crypto (#180) 2026-04-03 20:00:51 +01:00
Matt Kane
d3cf93f171 ci: add /format comment command for PRs (#195) 2026-04-03 19:45:21 +01:00
Matt Kane
73b5a787b8 fix: use Node 24 for release workflow to get npm OIDC support (#165)
Node 22 ships npm 10.x which doesn't support trusted publishing via
OIDC (requires npm 11.5.1+). Node 24 bundles it natively, removing the
need for the `npm install -g npm@latest` step which was failing with a
`Cannot find module 'promise-retry'` error due to npm corrupting itself
during self-upgrade.
2026-04-03 09:14:45 +01:00
Casey Grzecka
403f728222 renames the Why EmDash content page to match the slug used in the astro config (#123)
Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-04-02 21:46:15 +01:00
Matt Kane
fd8f44cd24 chore: add E2E rollup job and exempt emdashbot from PR compliance (#132)
Add a rollup job that gates on all 8 E2E shards so it can be a single
required check. Exempt emdashbot from PR template validation alongside
dependabot and renovate.
2026-04-02 20:23:10 +00:00
Matt Kane
b82a5fe7d6 fix: use GitHub App token for release workflow (#130)
GITHUB_TOKEN can't trigger CI on PRs it creates, so the changesets
release PR could never pass required checks. Use a GitHub App token
instead, which triggers workflows normally.

Also pins all actions to commit SHAs and uses frozen lockfile.
2026-04-02 21:10:51 +01:00
Matt Kane
ed5df8e453 Add PR template, issue templates, and contribution policy (#126)
* chore: add PR template, issue templates, and contribution policy

Drive-by feature PRs are becoming a problem. This adds guardrails:

- PR template with type selection, checklist, and AI disclosure
- Bug report issue template (structured YAML form)
- Issue config that redirects features to Discussions and disables blank issues
- PR compliance workflow that enforces template completion and requires
  a Discussion link for feature PRs
- Contribution policy in CONTRIBUTING.md (acceptance tiers, AI PR rules)
- Agent-facing rules in AGENTS.md (follow the template, no bulk changes)

* fornat
2026-04-02 21:02:10 +01:00
Matt Kane
953815969a fix(tests): use global hookTimeout for integration test beforeAll hooks (#125)
* fix(tests): remove explicit beforeAll timeouts that override global hookTimeout

Integration tests passed 60s timeouts to beforeAll, overriding the
120s hookTimeout in vitest.smoke.config.ts. On CI the dev server
startup can consume the full 60s, leaving no time for setup + seeding.

Also bumps createTestServer's default waitForServer timeout from 60s
to 90s, leaving 30s margin within the 120s hook budget.

* fix(tests): don't remove shared node_modules symlink during cleanup

Multiple integration test suites run concurrently and share the
fixture/node_modules symlink. When the suite that created it finishes
first, its cleanup deletes the symlink, causing other suites to fail
with MODULE_NOT_FOUND when their server process tries to resolve astro.

The symlink is gitignored so it's safe to leave in place.
2026-04-02 20:33:07 +01:00
Matt Kane
7924d54072 Playground interstitial (#16) 2026-04-02 18:32:52 +01:00
Matt Kane
61b73aeb01 fix: add explicit permissions to CLA workflow, drop PAT (#121) 2026-04-02 18:07:59 +01:00