frontend
Technical notes on web development, DevOps, and AI integration.
39 articles
- 23:29backend
Two Sets: What You May Read, What You May Manage
Opening read access across departments without loosening writes: readable and manageable module sets as two separate fail-closed sets.
TL;DR: KotaPortal treated the module query parameter as a write gate, hiding all content from other departments. The fix splits access into two sets: ModulesFor for writable modules and ReadableModules for readable ones, with fail-closed checks moved earlier in the chain. The frontend keeps full navigation while write affordances hide per permission, marked by a read-only banner.
#rbac#golang#http - 13:51frontend
The Date That Shifted by Itself: Pin the Timezone at Render
Data right, display wrong: toLocaleString without timeZone lets a UTC server and a WIB browser render different dates. Pin it at the presentation layer.
TL;DR: A date bug blamed on stored data was actually the render layer: toLocaleString was called with the id-ID locale but no timeZone option, so servers in UTC and browsers in WIB disagreed. Timestamps between 17:00 and 24:00 UTC crossed midnight once converted. Fix: store UTC, render with an explicit timeZone, locked by a test.
#frontend#nextjs#timezone - 11:22frontend
Mirroring the Status Transition Map in the Frontend
A tiny frontend mirror of the backend transition map: one union type, one map, and impossible options disabled before the click.
TL;DR: I refactored the tangled status logic into a clean switch that maps six statuses to four display stages. A lean NEXT_STATUSES map only decides which options light up, leaving the backend as the true authority that returns 409s. I added type guards, fallback labels for unknown statuses, and real disabling beyond just aria-disabled.
#frontend#typescript#state-machine - 13:59frontend
One Design Language for Every Page
The homepage redesign left five subpages looking like a different website. The fix was not restyling each page by hand but extracting shared components.
TL;DR: Shipping a polished homepage exposed inconsistent spacing, heroes and buttons across other pages. Instead of patching each page, the fix extended two components, page-hero.tsx and page-cta.tsx, plus a borderless card pattern using layered gradients, CSS variable tokens and consistent pill buttons. Pages now share the same visual language through props while keeping unique content, so updates happen in one place.
#css#design#frontend - 00:44frontend
[Placeholder] Was the Feature: Typed Content Cards
Company cards changed shape three times in a week, but the typed content contract held: optional fields plus truthiness guards make empty data hide itself.
TL;DR: Building a bilingual Next.js company profile, I kept adding card fields and filling gaps with placeholder strings. Turns out optional TypeScript properties plus truthiness guards meant absent data simply never rendered, no helper logic needed. Typed content files beat a headless CMS at this scale, surviving three redesigns with zero component changes.
#typescript#react#nextjs - 18:35frontend
Why I Put 92% Alpha in My Header Token Instead of Using bg-white/60
Dark navy header felt heavy in light mode. The fix: bake 92% alpha into the --color-header token so backdrop-blur works everywhere without per-component overrides.
TL;DR: Slapping bg-white/60 on a navbar breaks fast, since child elements inherit transparency and fixes scatter across files. The fix is baking alpha into a --color-header token (about 92 percent opacity), which cascades to every consumer and pairs cleanly with backdrop-blur-md. Trade-off: the header decouples from the global background token, but one line brings it back if needed.
#css#tailwind#design - 02:26devops
The Sidebar Said 30, the Ring Said 92
Two numbers for one server: risk score and health score point in opposite directions, and my sidebar was still reading the old one.
TL;DR: A dashboard showed conflicting scores for the same server because the sidebar still read the old risk-based fields (100 means critical) while everything else used the new health-based ones (100 means healthy). The lesson: invert metric direction once at the API boundary, never per component. Treat opposite-direction metric renames as data contract migrations, not simple renames.
#monitoring#frontend#observability - 14:17frontend
Fullscreen Mobile Chat Under a Fixed 66px Header
Fullscreen mobile wrapper under a 66px fixed header using mt-66px plus calc 100dvh-66px, uncapped transcript, and a compact messaging header.
#css#tailwind#frontend - 12:43frontend
A Separate Mobile Chat Component With One Answer Logic
My mobile chat needed its own messaging-app-style frame, but the answer logic stays single-sourced by reusing the exported TurnBody.
TL;DR: A desktop three-column chat layout doesn't survive shrinking to phones, so the author built a separate mobile thread component using the familiar messaging-app pattern. Sticky header, chat bubbles, composer, all done with CSS sticky and backdrop-filter. Only the frame is duplicated; shared TurnBody logic keeps desktop and mobile in sync.
#react#frontend#ux