ux
Technical notes on web development, DevOps, and AI integration.
32 articles
- 08:58backend
One Value, Two Meanings: Global Scope Is a Choice, Not Null
Null in a scope filter doing two jobs at once: not chosen yet and choose all. A design note on why an ALL sentinel in the enum is more honest.
TL;DR: The KotaPortal dropdown used null to mean both nothing selected and all units, which created confusing backend logic. Instead an explicit ALL value was added to the BidangScope enum so null only means untouched. This keeps the API contract clear, makes validation reliable, and stops teammates guessing what empty means.
#typescript#openapi#api - 10:06frontend
Ditching Manual Height Math at the Bottom of the Page
The taller brand column needed no height math and no JavaScript at all: CSS grid stretch plus one auto margin did the entire job.
TL;DR: While refactoring a site footer, the author nearly wrote JavaScript to measure column heights before realizing CSS grid's default stretch already equalized them. Pinning the company line to the bottom took only flex column plus mt-auto. The lesson: inspect defaults first, since two class names beat any runtime measuring script.
#css#flexbox#tailwind - 21:30devops
Swapped Arguments, Burned Budget: Validate at the Very Top
set -euo pipefail will not save a script from swapped arguments. Whitelist guards and custom exit codes at the entry point stop the waste.
TL;DR: The script ran to completion on swapped arguments because set -euo pipefail only catches unset variables, not wrong values. The fix: eight guard lines at the top that validate the recipe path, integer, and budget using simple case globs with custom exit codes 45 and 46. Validate at the trust boundary, quote variables, keep it lightweight.
#bash#shellcheck#linux - 01:57backend
Lock stolen mid-run: what fencing tokens taught me
A lock checked once at startup guards the door, not the data. Fencing tokens validated at every state write, plus a heartbeat lease, are what guard the data.
TL;DR: A force-killed transcribe process showed why one-time lock checks fail: after the lock expired, a second session took over and idempotent resume reused finished windows from sidecars. The fix is fencing tokens, checked at every state write, so stale sessions die with lock-stolen-mid-run. Minimum package: TTL lock, heartbeat, and a negative control proving the guard fails.
#distributed-systems#idempotency#testing - 10:10devops
A reboot playbook brave enough to refuse the reboot
Rebooting one production server is easy; the hard part is the fencing. Lock pre-flight, the reboot module, and an uptime post-check that dares to fail.
TL;DR: An engineer built an Ansible playbook to reboot one server safely for kernel patching. The playbook guards against races with unattended-upgrades using lock checks, reboots, then verifies the operation by comparing uptime before and after. Manual invocation only, backed by 111 unit tests, because automated reboots turn one bug into nine downed servers.
#ansible#linux#reboot - 10:06devops
A permanent logrotate guard for btmp and wtmp
Internet-facing servers pile up failed-login logs with no guard. One logrotate drop-in, the su directive, and a logrotate -d gate close the problem for good.
TL;DR: btmp logs failed SSH logins and can grow past hundreds of megabytes between weekly rotations. A drop-in logrotate rule using maxsize 50M rotates oversized files early, while rotate 2 and compress keep archives small. Validate with logrotate -d before deploying; add su root utmp or logrotate refuses on group-writable directories.
#logrotate#linux#ansible - 02:28devops
654M in /var/log and the Evidence Task That Quietly Lied
A weekly playbook said OK while /var/log grew to 654M: rotated btmp archives, an active file to shrink, and a df pipe that never ran.
TL;DR: The dashboard caught disk creep my weekly playbook kept missing: years of SSH brute-force attempts had quietly stuffed btmp past 150M. Worse, the evidence task ran df through the command module, which ignores pipes, so it never filtered output. The fix swaps in shell and truncates oversized logs instead of deleting them, keeping sshd writing happily.
#ansible#linux#logrotate - 17:26devops
Three Fixes That Tamed My Server Monitoring Dashboard
A server monitoring dashboard becomes noise when attention items pile up with no organization. Three complementary fixes transform a flat grid into a usable workflow.
TL;DR: Dashboard Guy Eighteen flat grid of alerts made it impossible to find critical issues across nine servers. Backend search with debounce, severity filter buttons, and collapsible server groups solved the noise problem by pushing all filtering logic server-side. Three tools together let you triage from hundreds of items in two taps or three words.
#monitoring#ux#devops - 22:43frontend
The Nav Accent That Moved on Its Own Turned Out to Be Modulo
The AI entry in my navbar changed color after a menu reorder. A lesson in modulo index color assignment and fixing it with data identity.
TL;DR: Styling nav entries with a modulo index ties colors to render position, so reordering the menu silently reshuffles accents. Pinning the special "Ask AI" entry to its href identity keeps its color stable. Adding an idle pill also satisfies WCAG 1.4.1, since shape reinforces hue for users who can't distinguish colors.
#tailwind#react#css