2026-07-14
What changed at Krexel this week
Slower product = no product. Here's everything we shipped over the last four days to make Krexel faster to use, easier to share, and ready for B2B buyers.
This week was an audit week. We rewrote the dashboard cache layer, got hit by a subtle regression, fixed it, and shipped four other audit items in the same deploy cycle.
Here's what landed, with the honest numbers.
The dashboard is 30 % faster
We started the week measuring 1011 ms for the warm /dashboard load. After four days of cache-layer work (and one self-inflicted regression that we caught before it shipped to anyone but ourselves), it's at 708 ms for the same flow.
| Route | Before | After | Δ |
|---|---|---|---|
/dashboard | 1011 ms | 708 ms | −30 % |
/keys | 753 ms | 636 ms | −13 % |
/settings/webhooks | 1523 ms | 450 ms | −70 % |
/deploys | 1526 ms | 815 ms | −47 % |
The biggest single win was /settings/webhooks. The honest read is that listWebhooks() was doing its own worker round-trip outside the dashboard's bootstrap cache, which meant every page nav re-fetched the full list even when the data hadn't changed. The fix is the same unstable_cache + revalidateTag pattern we use for the rest of the dashboard — and tag-busting on the create / delete / rotate-secret server actions keeps it fresh when mutations happen.
We shipped a cacheKey regression we want to call out
Around the middle of the week we shipped a cache-key change to /keys and /settings/webhooks that regressed /dashboard from 587 ms to 914 ms in one build. The mistake: the new key triggered a dbGetCustomer per-render that the old key had implicitly short-circuited. We caught it in the end-to-end timing check before any user hit it (CI is good). The fix was wrapping resolveCustomerId in unstable_cache(5min) + React.cache().
We've added it to our internal notes: always re-measure every page that touches a cache layer, not just the one the change was intended for.
Real status feed — for both humans and machines
There's a /status page that has been correctly flagging an outage in our Cloudflare Pages API integration all week. The badge was red; the underlying cause was a Cloudflare token that doesn't have Workers Scripts:Edit on the right account (more on that below).
What's new is /status.json — a machine-readable mirror of the same data. Always returns HTTP 200; the body carries the truth. Aggregate it in UptimeRobot / BetterStack / BetterUptime — you get the full per-check status on every poll.
$ curl https://krexel.com/status.json
{ "ok": false, "checks": { ... }, "version": "...", "ts": "..." }
Every shared link now looks right
Sharing /blog/krexel-vs-vercel on Twitter used to fetch the generic "Krexel" preview. We added proper OpenGraph + Twitter card metadata to every public route — /blog/*, /docs/*, /pricing, /legal/*, /faq, /chatgpt-gpt. Implementation: a lib/marketing-md.ts helper that reads the same frontmatter the body renderer reads, so editing one .md updates title, description, canonical, and the social preview in a single pass.
Two new pages for B2B buyers
Anyone who has ever been mid-procurement and Googled "what's your security page" will recognize why these matter:
/legal/security— concrete list of controls (TLS + HSTS preload + bcrypt + KV scoping), sub-processors, vulnerability disclosure channel./legal/dpa— public summary of the data-processing addendum: SCC modules, retention windows, breach commitment. Enterprise procurement can request a countersigned copy fromlegal@krexel.com.
We also shipped /docs/api-quickstart — the five-minute, no-dashboard walkthrough of how to get an API key and ship a site. The exact gap was that, until this post, there was no public README for the API for users who came in from a Twitter link rather than from a friend.
Honest caveats
/status.jsonreportsok: falsebecause our storedcloudflare_api_tokendoesn't haveWorkers Scripts:Editon the right Cloudflare account (saadr234@gmail.com→b77dbe91…). We don't have a working token with the right scope on hand. Once one is dropped into~/.cloudflare/credentials, the/readyzupstream check, and therefore/status.json'sok, will flip to green — no code change from us required.- The
/templatesand/usagedashboard pages are stub pages today. They'll stay that way until we know whether to ship them — we'd rather not build them twice.
— Saad