Keep the encryption key across restarts instead of inventing one
Every note body in production was unreadable. NOTES_MASTER_ENCRYPTION_KEY was never set anywhere - not in the deployment, and the deployed ConfigMap carried no ...
Tell an unreadable note apart from an empty one
A note whose body cannot be deciphered came back with content null and nothing else, which is exactly what an empty note looks like on the wire. Clients could n...
Render themed imagery server-side, and keep brand text readable
Every background on the homepage was being downloaded TWICE. The components rendered the local `/img/bg/N.webp`, then an effect resolved the org's theme path on...
Paint the knowledge console in the org's colour, not a fixed purple
The rebuild took its chrome from --accent-knowledge, which globals.css declares as #8b5cf6. That variable does not move with an organization's brand, so every c...
Compress the theme host, which was serving every text asset raw
MinIO returns object bytes exactly as stored — it does not negotiate Content-Encoding — and the two theme IngressRoutes carried `strip-hsts` and `cors` but no c...
Inline the stylesheet, and drop polyfills nothing can reach
Two Lighthouse findings, both of which stayed open after the last round because I had concluded they were not addressable. They were; I had not looked hard enou...
Name the controls that had no name, and lift the text under 4.5:1
Three separate defects, all of them invisible to the build, the type check, the lint run and both existing guards. UNNAMED CONTROLS — the phone layout's naviga...
Stop shipping 1.8 MB of unresized backgrounds after hydration
ThemedBackground was the most expensive thing left on the homepage, and none of it looked like a bug. It rendered a raw <img> straight at the theme bucket, so t...
Stop the fold waiting on hydration, and clear the load window
The homepage shipped its whole fold invisible. Framer Motion serialises an `initial` prop into the prerendered HTML as an inline style, so the markup arrived wi...
Remove the navigation timing probe
It did its job. The question it was added to answer — whether the remaining delay was network, script or paint — turned out to have a fourth answer the probe fo...
Seek the one candidate block instead of scanning back to the table start
/api/send took 1.8-7.9 s for most addresses and single-digit ms for a few, which is not a load problem — it is the shape of the geolite query. getLocation() is ...
Stop the analytics tracker hijacking every link but Home
Every page except the homepage took seconds to open, and the reason was never in this app's own navigation path: the server prerenders, prefetch payloads are co...
Every route change was animating a scroll back to the top
<html> carried Tailwind's `scroll-smooth` and nothing else. Next suppresses smooth scrolling while it scrolls to a new route, but only for pages that declare it...
Move the video controls to the top right
They sat bottom-left only because the frame used to bleed off the right edge of the viewport, which would have put a control anchored there off screen. The reel...
Measure real navigations and cold loads, not just flagged sessions
Five rounds of fixes have each removed a real defect and none has fixed what is actually being felt, because every diagnosis so far has been inference from outs...
Drop the sitewide loading boundary that only secondary pages paid for
Every page except the homepage felt slow, which points straight at the (pages) subtree — and at something I put there. When 4fae924 added (pages)/loading.tsx ev...
Prerender the changelog count, refresh it on publish instead of on visit
Every visitor was fetching this number themselves. PreviewBanner lives in the shared layout, so on every page it hit /api/changelog/today after hydration, waite...
Stop prefetching a megabyte per page, and stop calling the backend for free
Two costs that were paid on every page, both found by following the reporter's own hunch about i18n and needless backend calls. PREFETCH VOLUME — a regression ...
Add an opt-in navigation timing probe behind ?perf=1
Page switches still feel slow on production, and the server has been ruled out from the reporter's own machine: 55-122ms responses, x-nextjs-cache HIT, prefetch...
Rebuild the knowledge base as a console
The four knowledge-base screens were the last in the app still wearing the old look, and three of them stated things that were not true. /kb showed "Pinned Art...
Enforce is_fake, and close the holes that let an unattended signup in
Two halves of one incident. An account registered, verified an address at a disposable provider, took an auto-login session and created five organizations in th...
Serve what the knowledge console reads, and fix what it never could
Four endpoints the rebuilt knowledge base needs, and three facts the API was unable to state. GET /api/kb/pins returned a Page of pin ROWS, and KbArticlePin.ar...
Reject a replayed Capcha payload instead of accepting it forever
`verifySolution` answers "is this a correct solution to a challenge we issued". It says nothing about whether we have already accepted that exact solution, and ...
Add users.is_fake, in the only statement order a populated table allows
Mirrors the new `User.isFake` field. Four statements, and the order is the whole migration: YugabyteDB rejects `ADD COLUMN … NOT NULL` on a populated table — re...
Add is_fake, the flag that makes an account invisible instead of deleted
A synthetic account — a test artifact, a seeded fixture, or a signup judged to be automated — now carries `users.is_fake`, and the platform stops acknowledging ...
Survive a retried image pull, and stop deploying twice per push
The 013faf1 deploy failed on `exceeded its progress deadline` while the rollout itself was fine — the pod came up healthy about 90s in, and prod has been servin...
Stop every page switch waiting on a redirect and a 2s fade-in
The prerendering work in 4fae924 fixed the server and the router, and the site still felt like it took 1-2 seconds to change pages. It was never the network. Tw...
Prerender the routes again and give a navigation something to paint
The locale layout resolved its messages with a bare getMessages(), which reads request headers and so opted the ENTIRE app out of static rendering. With no load...
Resolve a public chat's owner without walking a lazy association
getChatSessions runs outside a transaction, so reaching the session owner through the visitor's lazy session proxy worked only for as long as open-in-view stays...
Nobody with a login is the anonymous web-chat visitor
A widget ticket names the org's SYSTEM member as its requestor because the visitor has no member record — and that member is the org owner, usually the person a...
Stop reading the org's system member as the web-chat visitor
Four reported faults, one cause. A widget visitor has no Member, so the org's SYSTEM member — the owner, who works the queue — stands in for them as the ticket'...
Give the web-chat visitor an identity of their own
A public web-chat visitor has no Member, so the platform stands the org's SYSTEM member in for them: the ticket's requestor, and the author of every message the...
Carry the heading contrast fix to pricing, security, about and offer
Same defect as the home page, same nine remaining spots: section headings opened on `--color-primary`, which measures 2.61:1 against a mid-green background — un...
Raise section-heading contrast off the green end of the ramp
Every section heading's second line ran `--color-primary` -> `--color-primary-light` -> `--color-secondary`, so it STARTED in the brand green. Measured against ...
Stop the inbox claiming email is unset while it works it out
Opening /messages showed the "email isn't available / you have no mailbox" panel for a moment on nearly every visit, then replaced it with the member's real inb...
Drop the masthead stat rail, move the filter to the bar
The five counted tiles are gone from the header. It now states what the page is and gives the rest of its width to the primary action. They were also the only ...
Rebuild /hr/attendance as a payroll console
Eight flat tabs over eight panels that each drew their own heading, table, skeleton, error line and Snackbar — and had drifted. The overhaul is three things at ...
Rebuild the network page as an operations console
The page was the last screen still wearing the old look — a flat gradient bar, white cards, a centred spinner, alert() for every failure — while the rest of the...
Let a member give up their own membership
The network page has offered "Unsubscribe" since it was written. It opened a confirmation dialog and then said the feature would be implemented soon, because th...
Rebuild /hr/legal-compliance as the legal registry
The surface was a MUI tab strip over two AG Grids. Packages rendered as seven columns of counts and an actions cell of six unlabelled icon buttons, three of whi...
Play the kamo13 reel
Points the hero at the new reel's ladder, MP4 fallback and poster. The source is spec-identical to the one it replaces (H.264 720p24, 66s, ~30 MB), so nothing a...
Swap the hero reel to kamo13
kamo13.mp4 uploaded to MinIO at public/kamo13.mp4 (30 MB, sha256 174aaec6…, verified byte-identical to the local source after transfer — this link has a history...
Rebuild /hr/training as a training console
The tab was two AG Grids under a tab bar: accurate and mute. It now opens on the org's whole training obligation and lets an admin act on the gaps. - A masthea...
Let a note pinned from its sticky reach the launchpad band
The home band fetched the pinned list once on mount, so a note pinned from its floating sticky afterwards was in no list it held. Closing the sticky then left t...
Move the grid out of styled-jsx; drop two dead components
Finishes the styled-jsx sweep started on the preview banner. No `<style jsx>` block remains anywhere in the app. SITEMAP — the grid was an inline `display:grid...
Rebuild to pick up the Start Group Chat/Meeting labels
The image bakes messages/ from kamo-translation-dictionary at build time, so the dictionary push alone left the deployed bundle on the old copy.
Stop the banner flashing unstyled, make whole feature cards clickable
PREVIEW BANNER — its CSS lived in a `<style jsx>` block inside the component. In the App Router styled-jsx does not server-render CSS for client components, so ...
Centre the reel in its column instead of pushing it to the edge
Two earlier passes had the stage reaching for the page edge — first overhanging the viewport by 1.5–5rem, then sitting flush against it. Overhanging cropped a p...
Wire the offer banner, fix dead Learn more links and the hexagon field
Five fixes, all of them things that looked present but did nothing. OFFER BANNER — HeroOfferBanner was dead code; nothing imported it. Restored, but driven by ...
Rebuild the welcome panel around a live status rail
The left column was a generic headline, a security platitude and a pile of ambient decoration (dot grid, floating orbs, a pulsing dash). Replace it with one sha...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.