Dispatches
Build logs, weekend recaps, and notes from the shipping floor.
-
The SortableJS Container Trap
Dragged items ended up at position #21 instead of #1 in empty day columns. SortableJS was counting empty input rows as sortable items.
-
From Legacy Chaos to Modern Vue: Tracking Buttons and Event Nightmares
Clicking one Track button changed the state of every other Track button on the page. A global jQuery function was querying all buttons -- including Vue-controlled ones.
-
Fixing Timer Sync Between Web and Mobile
A focus timer showed 12 minutes' discrepancy between web and mobile. One component had WebSocket sync, the other was running on stale data from mount time.
-
Adding LUSC Committee Support to Democracy.cc
Supporting a new committee type took a 5-line change to an existing Blade component -- because the architecture was already flexible enough.
-
React Navigation: The Cross-Navigator Back Button Problem
Navigating from Chat (RootStack) to Settings (inside MainTabs) broke the back button. goBack() is navigator-scoped, and navigate() pushes instead of popping.
-
Building a Dynamic Filter System for Government Agendas
Hardcoded commissioner dropdowns and fixed sponsor columns couldn't handle changing committee rosters. Migrated to JSON storage with cached dynamic extraction -- 60x faster.
-
The Backend Timezone Audit: 14 Hidden Date Bugs
A walk appeared on the wrong calendar date. The audit that followed found 14 places extracting dates from UTC timestamps without timezone conversion.
-
Fixing Audio/Video Sync in User-Generated Clips
FFmpeg's input seeking hits the nearest keyframe for video but the exact timestamp for audio -- causing A/V desync in clips from commission meeting recordings.
-
The Alpine.js Component Override Bug
After merging the Focus Queue PR, the right-click context menu silently stopped working. No errors -- an inline script tag in a Blade template was overwriting the JS component.
-
Improving AI Articles With Native PDF Processing
Text extraction mangled budget tables and lost column relationships. Sending raw PDF bytes to Claude produced more accurate dollar figures and specific dates.
-
Fixing iOS Universal Links: 'Open in App' Was Opening Safari
Deep links from Google Calendar opened Safari instead of the app. Two issues: missing paths in the Apple App Site Association file and a URL scheme collision with Google OAuth.
-
Building Bulletproof Video Data Persistence
A routine deployment almost wiped 2,215 video timestamps across 76 meetings. I built triple-layer protection so it can never happen again.
-
Fixing the Focus Timer Pause/Resume Bug
After pausing and resuming, the timer showed 10 minutes remaining instead of 20. Pause time was being counted as elapsed time.
-
Eliminating 1,200 Lines of Duplicate Video Clipper Code
Desktop and mobile video clippers had identical validation, API calls, and player controls duplicated across 1,200+ lines. I extracted four shared utilities.
-
When DELETE Returns the Wrong Response: Laravel Route Shadowing
Deleting a workout returned {success: false} with a 200 status and no logs. The controller method wasn't even being called -- a wildcard route was intercepting the request.
-
Connecting Meeting Transcripts to the AI Article Pipeline
The agenda tells you what was proposed. The transcript tells you who fought for it. I connected Democracy.cc's diarized transcripts to the Journal's article generation.
-
Fixing the 10-Second Walk Button Delay
Tapping 'Start Walk' froze for 10 seconds with no feedback. Sequential async calls, a blocking alert, and a slow GPS lock were all compounding.
-
Every Speaker Correction Now Teaches the AI
Inline speaker name edits in the transcript editor were a dead end -- corrections went in but the voice recognition system never learned. Now both edit paths feed the same enrollment pipeline.
-
Fixing 60-Second Timeouts: Batch Operations 120x Faster
The AI assistant's 'Execute Schedule' timed out creating 8 appointments. Three compounding problems -- sequential calls, synchronous Google sync, and observer loops.
-
Why Your Password Manager Couldn't Find Our Login Fields
Roboform, LastPass, 1Password -- they all autofilled the email but left the password blank. Three missing HTML attributes were the cause.
-
How I Got the Miami Beach Journal Into Google News
An SEO audit found no RSS feed, no news sitemap, and missing meta tags on listing pages. Three gaps that kept the site invisible to news aggregators.
-
Building a 1,378-Test Safety Net
From ~200 tests to 1,378 in a single push. The bugs found along the way proved the investment was already overdue.
-
Fixing iOS Background Location Tracking in Expo
A 20-minute walk test captured only 18 GPS points with a 15-minute data gap. The screen locked, and iOS killed the location subscription.
-
How I Diagnosed a Silent Registration Problem and Rebuilt the Paywall
167 paywall impressions, zero clicks. The registration wasn't broken -- the tracking was, and the UX was pushing people away.
-
SortableJS + Alpine.js: The DOM Ownership Battle
Drag once, nothing happens. Drag twice, it works. Two libraries fighting over who owns the DOM.
-
Teaching the AI to Recognize Who's Speaking -- Across Every Meeting
Speaker labels reset every meeting. I built a hybrid pipeline that matches voices across files using 512-dimensional embeddings and cosine similarity.
-
The N+1 Audit: From 100+ Queries to 2
API Resources make it easy to hide database queries inside serialization. A full audit found four patterns silently running 100+ queries per request.
-
From RunPod to Modal: GPU-Powered Speaker Identification for Government Meetings
Three GPU platforms in three days. DigitalOcean was fragile, RunPod never provisioned, Modal worked on the first try.
-
The Hidden Timezone Bug in JavaScript Date Formatting
A user's mindfulness minutes showed zero because toISOString() silently converted their local date to UTC -- returning tomorrow instead of today.
-
How I Stopped 500+ Fake Visitors From China From Flooding Democracy.cc
95% of our traffic was Chinese bot crawlers, not Miami Beach residents. Geographic blocking failed -- here's what actually worked.
-
The One-Line Bug That Transcribed the Wrong Meeting
A hardcoded fallback filename sent the GPU pipeline to confidently transcribe the wrong city commission meeting -- and nothing downstream could tell the difference.
-
From 60 Seconds to 14: Optimizing Laravel Forge Deployments
Nearly 80% of every deployment was npm. A conditional frontend build cut deploy time by 76% -- from over a minute to 14 seconds.