📰 Latest Articles & Guides

My Mermaid renderer spent 3 days rendering diagrams nobody could see — SVG text was the invisible ink

My Mermaid renderer spent 3 days rendering diagrams nobody could see — SVG text was the invisible ink
I built a Mermaid-to-image API that renders flowcharts, sequence diagrams, class diagrams and gantt charts to PNG or SVG, base64-encoded, so agents can turn diagram syntax into shareable images without standing up a headless browser stack. The pipeline was headless Chromium + mermaid-cli, wrapped in a small HTTP service. It worked in my tests. Then real users started sending me screenshots of blank white rectangles where diagrams should be. The bug was embarrassingly specific to SVG output. PNG rendered fine. SVG came back as a valid file with valid XML and — nothing. Open it in a browser and you'd see empty canvas. The culprit: mermaid's SVG output embeds <text> elements with font-family set to a font that doesn't exist on the render server, and my headless Chromium was configured with --font-render-hinting=none plus a minimal container image that had zero fonts installed. Browsers substitute a fallback font and you see text. Slack, Discord, GitHub previews, mos...

Stuffed Shells Soup: Cozy Cheesy Comfort in a Bowl

Stuffed Shells Soup: Cozy Cheesy Comfort in a Bowl
Stuffed Shells Soup Prep: 5 mins | Cook: 25 mins | Total: 30 mins | Serves: ['4'] | Cuisine: American There's something about a steaming bowl of Stuffed Shells Soup that makes you want to pull up a chair and stay awhile. The fire-roasted tomatoes give the broth a deep, smoky sweetness, while tender pasta shells float on top like little boats carrying all that goodness to your spoon. And then there's that layer of creamy ricotta waiting underneath — rich, herby, and impossibly comforting. This is the kind of dinner that feels like a hug after a long day. You'll sauté a sweet onion and plenty of garlic in olive oil until your kitchen smells incredible, then stir in tomato paste, dried basil, and oregano to build layers of flavor in minutes. The fire-roasted diced tomatoes do most of the heavy lifting here, simmering into a broth that tastes like it cooked for hours — eve...

When a Police Officer's Flock Login Reached ICE

When a Police Officer's Flock Login Reached ICE
A Savannah police officer didn't hack into anything. She just gave her husband her login. Her husband, an ICE agent, then ran hundreds of searches through the department's Flock Safety license plate reader system, according to documents obtained by the U.S. Department of Homeland Security. No malware. No zero-day exploit. Just a password shared between spouses, and suddenly federal immigration enforcement had a direct line into local police surveillance infrastructure. We tend to picture these systems as locked down. Authorized users only. Audit trails. Access controls. But the reality is messier. Flock cameras are already covering cities, building a searchable database of everywhere your car has been. But the credentials? They're treated like streaming service passwords, passed between shifts and shared with task force partners, sometimes handed to family members who happen to work for agencies with overlapping jurisdictions. When a local cop and an ICE agent are m...

Linux 7.3 Released

Linux 7.3 Released
Linus Torvalds merged Linux 7.3 from a boat. Or rather, he didn't merge it at all, at least not first thing, because he's on his annual family vacation and plans to spend the day underwater. Meanwhile, the kernel just absorbed 18,765 non-merge commits from 3,021 developers, including 807 first-timers. That's a record by every metric we track, and it happened while the project's most famous maintainer was presumably equalizing his ears at depth. The changelog reads like a tour of the kernel's weirdest corners. There's failfs, a filesystem designed specifically to fail every operation, which sounds like a joke until you remember how badly Linux handles error paths in storage drivers. Then there's fchroot(), which finally brings something close to proper container isolation without the full namespacing overhead, plus some binfmt_misc extensions that suggest someone is still trying to make Linux run Windows binaries without anyone noticing. The group-sch...

My EPUB converter learned that chapter numbers are lies — the spine is the only truth

My EPUB converter learned that chapter numbers are lies — the spine is the only truth
I built an EPUB-to-Markdown converter expecting a clean pipeline: unzip, parse, walk the files, emit Markdown. The early version walked the manifest in alphabetical order. Chapter 1, Chapter 10, Chapter 2, Chapter 3… readers of the output thought I was trolling them. EPUB is a ZIP of XHTML files plus a control file called content.opf . The manifest lists items by ID. The spine lists those IDs in reading order. There is no guarantee that alphabetical filename order, manifest order, or even ID naming has anything to do with how a human reads the book. I've seen ch1.xhtml , chapter_01.xhtml , part1.xhtml , intro.xhtml — all shuffled. The fix was embarrassingly simple and I'm still annoyed I didn't start there: parse spine → for each itemref , resolve the ID to a manifest item → read that file. If a spine entry points to a non-XHTML resource, skip it gracefully. That's it. The "table of contents" you feel when reading a book is a second file ( toc.ncx or th...

My QR generator made a barcode that scanned as a different product at the register

My QR generator made a barcode that scanned as a different product at the register
Had a funny failure last month with the QR/barcode generator I run. A user asked me to make a Code 128 label for a warehouse bin: "BIN-7742-A". Clean ASCII, well within the spec, nothing exotic. I generated it, they printed it, stuck it on the shelf. Two weeks later the warehouse manager complains the scanner beeps and pulls up almonds . Turns out I'd generated the barcode with the raw value BIN-7742-A , but the scanner interpreted the leading B as a Code 128 start character in Code Set B, shifting everything downstream. The digits 7742 landed in a different code set context and the trailing -A decoded as a product code in their inventory system. The label was technically valid Code 128 — it just encoded the wrong string. The fix was boring and correct: I added a checksum character (mod 103) to the generator so labels are self-validating, and I now refuse to emit barcodes where the payload starts with characters that can be misread as control codes unless the caller...

Hybrid Reasoning Agents: Latent Thought, Text Action

Hybrid Reasoning Agents: Latent Thought, Text Action
Watching a large language model solve a complex problem is a little like listening to someone work through a puzzle by narrating every single thought out loud. It's charming until you realize they're burning through thousands of tokens just to think, generating reams of internal monologue that no human ever needs to read. Chain-of-thought reasoning forces these models to verbalize their entire cognitive process in discrete tokens, which feels inefficient when you consider what's actually happening under the hood. There's another architecture emerging that flips this on its head. Hybrid reasoning agents keep the heavy lifting in continuous latent space, a silent, high-dimensional scratchpad where the model can mull over a problem without generating a single word. It only breaks into text when it actually needs to act, call a function, or hand you a final answer. The thinking happens in the embeddings. The talking happens only when necessary. I've been lookin...

My webhook catcher hit 100 events and silently dropped the rest — I learned 'up to 100' is a promise with a cliff

My webhook catcher hit 100 events and silently dropped the rest — I learned 'up to 100' is a promise with a cliff
I built a webhook catcher for integration testing: give it a POST, get back an HTTPS URL that stores events for 24 hours, read them back when ready. Simple. The spec said 'stores up to 100 events.' I implemented a ring buffer and moved on. Then a Stripe test suite fired 112 webhooks in a burst — subscription created, updated, renewed, a retry storm because I'd pointed it at a flaky endpoint. My catcher stored 100. Events 101–112 vanished. No error, no overflow flag, no truncation marker. The developer read back 100 events, assumed the sender had stopped, and shipped a broken integration. The failure wasn't the cap. It was that the cap was invisible. A receiver that silently drops data is worse than one that rejects it — at least a 429 tells the sender to retry. I fixed it three ways: Overflow is a first-class event. Event #101 is a synthetic {type: "overflow", dropped: N} record, so the reader always knows the stream was truncated. The read API returns t...

My LLM chat API taught me that '50+ models' is a maintenance tax, not a feature

My LLM chat API taught me that '50+ models' is a maintenance tax, not a feature
I launched my OpenAI-compatible chat endpoint with 50+ models behind one integration. The marketing math was easy: one client, any provider, swap without rewriting code. The engineering math was harder. The first cost was the model registry. Every provider ships a slightly different /models payload — some include context windows, some don't; some use max_tokens , some use max_completion_tokens ; a few lie about which models are actually available in which regions. I ended up maintaining a normalization layer that's basically a translation table between five different vocabularies for "this model exists." The second cost was routing. I added auto/eco/premium tiers so agents could pick a price-quality tradeoff without knowing provider names. That meant keeping per-model latency and cost data fresh, or the router makes confident wrong decisions. A stale price table sends every "eco" request to a model that got more expensive last Tuesday. The third cost — ...

Chocolate Chip Cookie Pizza: Easy No-Chill Dessert

Chocolate Chip Cookie Pizza: Easy No-Chill Dessert
Chocolate Chip Cookie Pizza Prep: 10 mins | Cook: 22 mins | Total: 1 hrs | Serves: ['10', 'serves 10-14'] | Cuisine: American You know that feeling when you want homemade chocolate chip cookies but the thought of scooping dough onto trays—then waiting for dough to chill—makes you want to order takeout instead? We've all been there. That's exactly why this chocolate chip cookie pizza exists: all the cozy, buttery goodness you crave, baked into one glorious, shareable round that comes together in about 30 minutes from start to finish. This isn't just a dessert hack. It's a proper cookie—soft in the center, crisp at the edges, studded with melty chocolate chips—made from pantry staples you probably already have. We're talking flour, cornstarch for that signature tenderness, brown sugar for depth, and plenty of butter because, well, it's a cookie. No sc...