Changelog

Every change to Krexel.

Features, fixes, breaking changes, deprecations. Newest first.

Released: 2026-07-17

The biggest dashboard change since v14. Sites — every site your AI has shipped — moves from being a list inside /deploys to a first-class resource at /sites. Plus a top-to-bottom typography pass that makes the dashboard look and read like a modern SaaS product instead of a dev tool.

Sites as a first-class resource

  • New /sites page — a grid of cards, one per site. Click a card to drill into deploys, domain, files, and settings for that site. Empty state is a full dropzone — drop a folder, the AI ships it.
  • New /sites/[id] site detail with four tabs:
    • Deploys — every deploy for this site, with status + live stream
    • Domain — the custom domain or *.krexel.com subdomain attached to this site (M2)
    • Files — the tree of files in the latest deploy (M3)
    • Settings — site-level controls: rename, change framework, danger zone (M4)
  • /deploys is gone — replaced by /sites plus the new site-detail view. Old URLs redirect (308) so any bookmarks you have still work.
  • Sidebar swap — "My sites" → "Sites", "My URLs" removed. The new nav: Home, Sites, Integrations, API keys, Plan & billing, Settings, Team, Webhooks.

Dashboard typography pass

The audit called out the same thing on every page: too much font-mono + uppercase + tracking on labels, buttons, and pills. It read as "developer tool" not "your workspace."

  • ~100+ mono-uppercase instances killed across every dashboard page and component. Buttons read as "Save changes" not "SAVE CHANGES". Form labels read as "Email" not "EMAIL". Section eyebrows read as "Workspace" not "WORKSPACE".
  • Sidebar group label — "Workspace" / "Account" eyebrow now uses the modern sans + sentence-case style.
  • TopBar breadcrumb — the redundant eyebrow above the breadcrumb is gone. The breadcrumb alone tells you where you are.
  • StatusPill — was mono-uppercase, now sans + sentence case. "DRAFT" → "Draft", "MANAGED BY US" → "Managed by us".
  • PageHeader — the "Workspace" / "Account" eyebrow is removed entirely. The page title alone is the heading now.

The marketing site is unchanged — its mono-uppercase micro-labels (e.g. "60s · ship", "PRO TIP") are part of the design language. Only the dashboard got swept.

Real <Table> component

The keys, deploys, and domains pages were using a CSS grid as a fake table. That's the textbook "vibe-coded" tell.

  • New semantic <Table> component with proper <thead>, <tbody>, <tr>, <th>, <td>. Supports column alignment, hover state, empty state, monospace cells for code identifiers.
  • /keys, /deploys, /domains now use the real table. The CSS-Grid-as-table is gone.

Settings gets a sub-nav

Settings was a 240-line single page with 4 sections stacked. Now it has a horizontal pill sub-nav at the top: Account | Team | Webhooks. Each pill is a real route (/settings, /settings/team, /settings/webhooks).

The sub-nav also fixed a copy-paste bug from earlier: /settings/webhooks was rendering h1="Notifications" with eyebrow="Account · Notifications" — a leftover from when it was the notifications page. Now it's h1="Webhooks".

/integrations collapse

The page was 6 stacked blocks: a walkthrough, an MCP card, an amber notice, a row of 2 tiles (Custom domains + GitHub), and a Stripe "coming soon" tile. Five of those were just placeholders for features that don't exist yet.

  • The GitHub and Stripe "coming soon" tiles are gone (−75 lines).
  • Page is now: Walkthrough + MCP card + CustomDomainsTile. The 3 things you actually came here to do.

Icon stroke widths standardised

Icons had a mix of 1.5 / 1.6 / 1.75 / 2 stroke widths across the dashboard. Now standardised to 1.75 for every standard icon. Brand wordmarks (Google, ClaudeCode, ChatGPT) are left at their own weights — those are designed glyphs, not stroke icons.

Performance

  • /dashboard warm load still 700-900ms. The 4-5s cold start on first nav is mostly Vercel Function boot, not the page code. Fix in this release: Vercel Cron warmup at /api/internal/warmup pings the bootstrap every 5 minutes so the function graph stays JITed. Subsequent user loads after a warmup should be near-instant.
  • Shared JS bundle stayed at 102 kB. All the work above shipped within the v14 bundle budget.

What stayed the same

  • The marketing site (krexel.com, /pricing, /blog) is untouched.
  • The worker endpoints, KV/Postgres schema, and Supabase auth flow are unchanged.
  • The topbar (search, + New menu, breadcrumbs, avatar) is the v14 version, with one fix: the + New menu's "Drop a new site" entry points at the new /sites dropzone.
  • Cmd+K command palette (already in v14) still works.

Sites v15 worker surface (M1)

The dashboard's /sites page reads from the worker's new Sites API. The worker is the only writer to public.sites; the dashboard calls it via Bearer auth.

  • 6 new CRUD endpoints at /api/v1/sites/* — list, create, get, patch, soft-delete, list-deploys-for-site.
  • POST /api/v1/admin/backfill-sites — idempotent one-shot backfill. Walks every customer, creates one site per (email, project_name) pair, skips anything that already has a site. ?dry_run=1 previews without writing. Action item: run this once so existing customers' deploys show up in their /sites grid:
    curl -X POST "https://api.krexel.com/api/v1/admin/backfill-sites" \
      -H "Authorization: Bearer ***"
    
  • Site IDs are site_<16-char> (~83 bits of randomness). Cloudflare Pages project names are auto-derived as krx-<slug>-<6-char-discriminator> so two customers with the same slug never collide in our shared CF account.
  • Slugs are 3-40 chars, [a-z0-9-]. The DB has UNIQUE (email, slug) as a backstop; the route pre-checks for a clean 409.
  • Non-owners get 404 (not 403) on GET /sites/:id so site existence doesn't leak across customers.
  • Soft-delete sets status='deleted'. The CF Pages project is preserved for 30 days so a restore is a support op, not a re-deploy. A future cron sweep purges orphaned projects.
  • Storage: production reads + writes go through Postgres (public.sites); KV is a fallback for local dev + tests. Both stores implement the same Store interface so the route handlers don't know which one is in use.
  • Tests: 20 cases in worker/test/sites.test.ts — all passing. Covers happy paths, validation, authz (404 to non-owners), soft-delete, the ?dry_run=1 backfill path, and the 403-for-non-admin guard on the backfill.

The next milestones wire the deploy flow into the new model: POST /deploy will accept a siteId and atomically update the site row, the Domains tab and Files tab fill in M2 and M3.

Permalink & structured data →

Released: 2026-07-14

A batch of polish that lands across the whole product — measured dashboard speedups, a real status feed for aggregators, social previews on every shared link, and two new legal pages for B2B buyers.

Performance

  • /dashboard: warm load 708 ms (was 1011 ms — −30 %). Cache-key rework kept the cross-render hit; the regression we hit in P3 is now patched with a 5-min cache on resolveCustomerId.
  • /deploys: warm load 815 ms (was 1526 ms — −47 %). First page now reads from loadDashboardBootstrap() and falls through to a fresh worker fetch only when filters change.
  • /keys: warm load 636 ms (−13 %). Cached reads through the same bootstrap path.
  • /settings/webhooks: warm load 450 ms (was 1523 ms — −70 %). listWebhooks() now sits in the same unstable_cache layer as the rest of the dashboard; mutations bust the tag so the list stays fresh on the next render.

Real status feed

  • /status.json: a machine-readable status feed that mirrors what /status shows. Aggregate it in UptimeRobot / BetterStack / BetterUptime — body is { ok, checks, version, ts }. HTTP code is always 200; the truth signal is ok in the body.
  • The dashboard's /status page was already correctly flagging an upstream cloudflare_pages_api outage. That page is real-time and always current; we just hadn't shipped the JSON feed for it.

Social previews

  • Per-page OG + Twitter card metadata across every public route: /blog/<slug>, /docs/<slug>, /pricing, /legal/privacy, /legal/terms, /faq, /chatgpt-gpt. Sharing a link now picks up the page's title + description instead of the generic "Krexel" copy.
  • Implementation: new site/lib/marketing-md.ts reads the same YAML frontmatter the body renders from, so a single edit to the .md updates title, description, canonical, and the social preview.

New public pages

  • /legal/security — concrete list of the controls protecting customer data: TLS, HSTS preload, bcrypt via Supabase, KV/R2 scoping, rate limits, sub-processors. Includes a vulnerability disclosure channel.
  • /legal/dpa — public summary of the data-processing addendum for EU/UK B2B sales: SCC modules, retention windows, data subject rights, breach commitment. Enterprise customers can request the countersigned copy from legal@krexel.com.
  • /docs/api-quickstart — five-minute, no-dashboard path to a working API key. Replaces the "where do I read about the API?" that's been missing since launch.

Audit + 404 polish

  • Five audit-identified 404-prone routes shipped as 308 redirects + two stubs back in 4366e2e: /team, /settings/profile, /settings/billing, /templates, /usage.
  • React #418 hydration error from a server-rendered Date.getFullYear() patched in BrandPanel.tsx (now "use client" + useEffect).
  • Two 404 pages now match the rest of the product: root /not-found.tsx (cream surface, three CTAs) + dashboard (dashboard)/not-found.tsx (dark surface, kept inside DashboardChrome).

Honest caveats remaining

  • The /readyz CF Pages API check is currently failing because the cloudflare_api_token does not have Workers Scripts:Edit on the right account. Nothing under our control; once a token with the right scope is dropped in ~/.cloudflare/credentials, /readyz and /status.json flip to green with no code change.

— Saad

Permalink & structured data →

Released: 2026-07-08

This is the first version of Krexel that we consider production-ready for paying customers. Every feature documented on the website now works end-to-end.

What works

  • End-to-end deploys — signup, deploy, R2 file storage, Cloudflare Pages build, custom domain, SSL, all verified
  • Patch deploys — your AI can edit the live site in 8 seconds via the MCP server
  • Rollback — one command to revert to any previous deploy
  • Custom domains — GoDaddy, Cloudflare, Namecheap, and any other DNS provider
  • Stripe billing — live mode, $10/$25/$50 tiers, webhook handling tested
  • API — every endpoint documented, 170 tests pass
  • Marketing site — full SEO foundation (sitemap, JSON-LD, OG images)

Added

  • Stripe live mode — real payments wired through Krexel's own Stripe account
  • Patch deploys — single-file edits to the live site without full rebuild
  • R2 file tree storage — every deploy's file tree is stored in Cloudflare R2, enabling patch/rollback flows
  • Custom domain support — connect any domain via DNS records
  • Self-healing auth — legacy API keys auto-backfill the new token-sha256 index on first use
  • /readyz deep probe — opt-in KV round-trip check (use ?deep=true to verify writes)
  • SEO foundation on the marketing site — sitemap, robots, JSON-LD structured data, PNG OG image
  • Auto-deploy from GitHub — push to main deploys to Vercel automatically
  • Eight reference docs — getting-started, install-cli, install-mcp, connect-custom-domain, dns-godaddy, dns-cloudflare, dns-namecheap, billing-and-plans

Changed

  • /readyz no longer probes KV by default — saves 3 KV ops per call; use ?deep=true for the round-trip check
  • Auth flow uses sha256 token index — O(1) lookup instead of O(n) scan

Fixed

  • R2 was wired read-only — the deploy route now writes the file tree to R2 on every deploy
  • Pages manifest field rejected with 8000096 — switched from Blob to string in the multipart form
  • OG image was SVG, invisible on social — replaced with 1200×630 PNG
  • /sitemap.xml returned 404 — added Next.js dynamic sitemap
  • /robots.txt was missing — added declarative robots config
  • No structured data on the homepage — added JSON-LD for SoftwareApplication, Organization, WebSite, FAQPage

Security

  • Secrets backed up to ~/.hermes/credentials/ before every wrangler secret put
  • Tokens never logged — even in verbose mode
  • MCP server scopes per-tool — deploy tool can't read keys, patch tool can't deploy

Known limitations

  • No team seats yet — Studio tier pricing is published but team-seat feature isn't wired up. Pricing page has been updated to reflect this.
  • KV free tier — daily limit resets at 00:00 UTC. We'll move to paid tier when we exceed it consistently.
  • No in-dashboard onboarding tour — first-run experience uses the existing progress checklist. Improved tour coming in v0.4.
  • Test customers + Pages projects in KV — cosmetic, not affecting production. Will purge post-quota-reset.

Next: v0.4

  • Team seats (Studio tier)
  • Onboarding tour for first-time users
  • Deploy progress bar (replaces static status pill)
  • Deploy success celebration modal
  • /blog/ and /changelog/ with weekly content
  • Logo redesign (commissioned)

Thanks to everyone who tested, filed issues, and pushed us to ship. Let's go.

Permalink & structured data →

Released: 2026-07-05

Every deploy's file tree is now stored in Cloudflare R2. This unlocks patch deploys, rollback, and the future of in-browser file editing.

Added

  • R2BucketAdapter — bridges CF's R2Bucket to our internal R2Like interface
  • saveTree(deployId, files) — stores a file tree (Map<path, Uint8Array>) to R2
  • getTree(deployId) — reads back the file tree as a list of {path, size, sha256} entries
  • getFile(deployId, path) — fetches a single file's bytes
  • Retention sweep endpointPOST /api/v1/cron/retention deletes R2 trees older than the configured TTL (default 90 days)

Why

Patch deploys need to read the current file tree before generating a diff. Rollback needs to ship an old tree as a new deploy. Both of those require the file tree to be stored somewhere queryable.

R2 was the right choice because:

  • Cheap ($0.015/GB/month)
  • Globally distributed reads (CDN-fast)
  • Pairs naturally with Cloudflare Pages (where the deploys actually serve)
  • Already integrated with our other Cloudflare services

Changed

  • Deploy record schema — adds optional files_key field referencing the R2 tree
  • Worker init — constructs R2BucketAdapter from c.env.KREXEL_R2 and passes to createApp

Fixed

  • /api/v1/deploys/:id/files — was returning 404 files_not_available for all deploys. Now returns the actual file tree.

Migration

No user-facing migration. Existing deploys (pre-R2-storage) return files_not_available because their trees weren't stored. New deploys store automatically.

What this unlocks

  • Patch deploys — your AI reads the current tree, generates a patch, ships it (8 seconds)
  • Rollback — re-ship any past deploy's tree as a new deploy
  • Future: in-browser editing/dashboard/deploys/:id will let you click any file and edit it

Performance

  • R2 reads: typically <50ms globally (CF network)
  • Tree size: ~150 bytes metadata per file + actual file bytes
  • For a typical 50-file site: ~7KB metadata + files

Cost

At 100 customers × 50 deploys/month × 7KB metadata = ~35MB R2 metadata storage = ~$0.001/month.

File content storage scales with actual deploy size. Average ~500KB per deploy, so 2.5GB of file content for that workload = ~$0.04/month.

R2 is cheap. Don't worry about it.

Permalink & structured data →

Released: 2026-06-20

The first end-to-end deploy works. Three teammates used it to ship their personal sites. Lots of rough edges.

What works (in alpha)

  • Sign up with email → get API key
  • krexel deploy from CLI uploads folder to Cloudflare Pages
  • Custom domain via DNS records (manual)
  • Live URL on yourname.krexel.com subdomain
  • Dashboard with deploy history (basic)
  • Stripe test mode checkout

What's rough

  • Every deploy does a full rebuild (no patch deploys yet)
  • No rollback
  • No R2 file storage (so no file tree history)
  • Dashboard has minimal styling
  • No team features
  • Auth uses a naive O(n) key scan
  • Documentation is a single README

Why we're shipping it now

We needed real users hitting real edge cases before building the rest. The alpha taught us:

  • Most users don't know what an MCP server is. Need a "what is this" explainer.
  • Patch deploys are the killer feature. Every user said "I'd use this 10x more if I didn't have to wait for rebuilds."
  • Custom domain DNS is confusing. Three users got stuck on Cloudflare's proxy toggle.
  • Stripe checkout is the conversion bottleneck. Most users abandon at the card form. Need to optimize.

These insights shaped the v0.4 roadmap.

What changed since alpha

This entry is retrospective — we're writing it now (2026-07-08) to fill in the changelog from the start. Everything in this entry shipped between 2026-06-15 and 2026-06-20 but wasn't tracked in a public changelog at the time.

Future versions get their changelog entries written as they ship.

Permalink & structured data →