frontend
Technical notes on web development, DevOps, and AI integration.
115 articles
- 23:48frontend
Tests That Lock Design Intent, Not Screenshots
Design intent does not survive on documentation alone. A 129-line unit test pins the house classes, so drift breaks the build, not the quarterly audit.
TL;DR: When a fresh restyle kept slipping back to old borders and colors, thicker documentation didn’t stop the drift. So the team shipped a 129-line test that renders components to static markup and checks exact Tailwind classes. It now catches silent design changes in CI and enforces token-only styles before shipping.
#testing#vitest#tailwind - 22:36testing
First Day With Vitest, and It Immediately Exposed Two Bugs
A Next.js frontend got its first vitest suite: 12/12 green, yet two bugs surfaced while writing the tests, before they could become complaints.
TL;DR: Installed Vitest on a Nextjs frontend that had no tests and wrote twelve passing checks. Writing them revealed two hidden issues, a client name duplicated across industry groups and a token gate whose glob missed files directly under src. The takeaway is to add a test harness early, since building tests finds bugs even when everything stays green.
#vitest#testing#git - 19:55testing
When the Test Reads Its Own Source Code
Vitest refuses to render components under Vite 8? Make the source files the test data: lock the rating flag invariant with toContain.
TL;DR: Vitest could not transform JSX after Vite 8 moved to rolldown and oxc without a React plugin, breaking the entity card render test. Instead the author added a text tripwire that reads source files and asserts rating_enabled !== false on six surfaces. It checks code shape not runtime, so integration tests verify the flag gates display without leaking rating data.
#vitest#testing#react - 18:03frontend
When Ratings Are Off, Hiding the Badge Is Not Enough
Switching the rating flag off is not enough while card badges and aggregateRating markup still ship. My notes on sweeping every surface clean.
TL;DR: Switching off ratings hid the detail page section but cards and JSON-LD still showed the old score from cached property data. That mismatch between what users see and what crawlers read risks spam penalties. Now the rating_enabled flag gates both the UI badge and the structured data so everything disappears together.
#react#seo#feature-flags - 17:10backend
The Checkbox That Silently Killed a Feature in a Go Backend
An unchecked checkbox sends nothing, and a Go backend reads that silence as false. Lessons from a silent admin-form bug.
TL;DR: Leaving checkboxes unchecked sent nothing, which the backend misread as disabling the features. In Go, a missing boolean unmarshals to false, so absent was treated as off and omitempty hid the problem. The fix was to always send explicit true or false and use null versus absent for nullable fields.
#go#json#react - 16:24backend
An Undocumented 404 Is a Contract Bug
Six lines of OpenAPI YAML and a regeneration changed what the frontend compiler knows. Error responses left undocumented are contract bugs.
TL;DR: What looked like a trivial six-line OpenAPI cleanup turned out to be critical for type safety. Since openapi-typescript only generates types for explicitly documented responses, an undocumented 404 forced the frontend to guess or use any. Documenting the error locks the contract so TypeScript catches missing handling early, saving hours of debugging later.
#openapi#api#typescript - 12:25frontend
Labels That Can Lie: When Status Vocabulary Lives in Two Places
A duplicated STATUS_MAP on the public page now reads labels from one lib: exhaustive types, an honest fallback for unknown values, countKey enforced.
TL;DR: The public status page broke because it kept its own four item map while the backend and shared lib handle six statuses. The fix makes STATUS_LABEL in layanan-flow the single source of truth, with TypeScript enforcing completeness and a runtime fallback to neutral raw text. CountKey is now required, so future status additions propagate automatically without silent display bugs.
#react#typescript#ui - 12:25frontend
Per-Status Counters in Admin Stats: Numbers From the Contract
Per-status snapshot counters joined AdminLayananStats additively; legacy fields kept, UI derives numbers from stats, no more meta.total tricks.
TL;DR: The dashboard showed dashes because the stats API only counted two of six statuses, leaving legacy fields at zero. The fix kept the old fields and added six current snapshot counters, with regenerated types now requiring a count for every tab and card. Counts respect user scope, and the queue badge now reads the submission counter directly with lightweight polling.
#go#api#openapi - 11:23frontend
An Honest Ticket Status Stepper: Learning from the History Array
The ticket stepper stops guessing from one status string: stage times come from the transition history, first row per status.
TL;DR: The stepper used to guess progress from one status string, now it maps real timestamps from the history array and falls back to created and updated times. Four display stages replace six cluttered steps, grouping terminal statuses while safely handling invalid dates and listing history in order. Transformations run during render, and const literal types prevent invalid pillar submissions.
#react#typescript#ux