notes

This Week's Technical Takeaways

This Week's Technical Takeaways

Here are the architectural lessons from this week's Claude Code sessions, spanning three different projects.

ProxLink

A mobile-friendly Proxmox frontend connected via API.

1. Rely on diagnostic overlays over assumptions
When a client-side layout bug persists, stop guessing and measure. After an initial fix failed on an iOS zoom issue, I shipped two more blind code changes (an auto heuristic and a monkey-patch) based purely on reasoning. Both failed. Adding an on-screen diagnostic overlay immediately identified the actual issue (bad centering, not scale math). Output real numbers to the screen before writing the next iteration.

2. State geometric constraints upfront
A landscape VM screen cannot physically fill a portrait phone edge-to-edge while showing 100% of the display. This is a geometry constraint, not a bug. Instead of shipping four sequential implementations (cover → fit → auto → cover → fit) as the downsides of each became apparent, the crop-versus-letterbox trade-off should be defined and selected before writing the CSS.

3. Address root dependencies before client-side workarounds
Every client-side scaling scheme I built was a workaround for VMs lacking a resize-capable display driver. If a VM's vga= configuration does not accept resize requests, client-side cleverness will not yield a perfect fill. Hardware and driver limitations need to be identified and treated as the primary blocker before writing frontend scaling logic.

nullobjRMM

Device remote monitoring and management.

1. Swallowed errors surface as unrelated bugs
Suppressing errors guarantees they will manifest later in confusing ways. getOutboundIP() used json.NewDecoder to parse plain text from ipify.org, ignored the error (//nolint:errcheck), and returned an empty string. The resulting enrollment failure complained about ip_address length, masking the actual JSON parsing failure. An apt-get update script failed silently, causing dist-upgrade to run against stale package lists and falsely report success with zero packages upgraded.

2. Enforce timestamp units at the type level
Mixing Date.now() (milliseconds) and unixepoch() (seconds) in the same codebase without type-level enforcement leads to silent logic errors. A display function multiplied a raw value by 1,000, assuming it was receiving seconds. When a millisecond value was passed, the UI rendered "56,453 years." Using a branded type (e.g., UnixSeconds) or a dedicated helper function turns this from a runtime UI bug into a compile-time error.

3. Inspect real data before writing filters
Logic written against assumed data structures will fail in production. A PBS backup failure alert fired on all failed tasks, including apt-update and term-proxy, because the filter checked the status but ignored the task type. An upgrade script targeting .list files missed the DEB822 .sources format entirely. Five minutes of inspecting actual Proxmox directories and PBS task logs prevents both issues.

Solar Forecast

Solar panel, inverter, and battery forecaster and charge decider.

1. Cloudflare Pages Functions terminate unawaited promises
If you call return json(data) in a Cloudflare Pages Function, the runtime shuts down immediately. Any fire-and-forget background promises (like database inserts) will die before executing. Background work must be explicitly registered with platform.context.waitUntil(). Failing to do this resulted in silent failures where database inserts appeared correct in the code but resulted in zero rows written.

2. Duplicated files guarantee drift
A date-aware cache key fix was applied to src/lib/server/forecast.ts but missed in worker/src/forecast.ts. Because these were functionally identical files serving the same purpose in different runtimes, the dashboard updated correctly while the 01:15 cron job continuously served stale pre-midnight forecast data. Shared logic requires a single shared module.

3. Verify remote schema state before debugging inserts
Silent database failures are often infrastructure issues, not code issues. Every insert to the solar_readings table was failing silently because migrations 0002 and 0003 were never applied to the live D1 database, meaning the target columns did not exist. Pushing a migration file to Git does not guarantee remote execution. Always run PRAGMA table_info() against the production database to verify the schema before spending time debugging the application logic.

← back to blogmore posts →