DevIdiot!
Tiny icons as data URIs — skip another network hop for chrome assets
Chrome UI is full of tiny assets that should never fight the critical path: a 16×16 chevron, a mute glyph, a spinner frame, a toolbar mark that shows up before the rest of the page finishes deciding who you are.I still see those shipped as separate /icons/*.svg or /icons/*.png requests. On a good day they ride HTTP/2 multiplexing and you barely notice. On a cold CDN edge, a flaky hotel Wi‑Fi, or a settings drawer that mounts before the icon sprite is warm, you get the classic flash of empty boxe
Turning Raw JSON into TypeScript Types is Harder Than You Think
In modern frontend tooling, a JSON to TypeScript converter is often dismissed as a weekend hobby project. The consensus intuition seems deceptively trivial: traverse a JavaScript object using Depth-First Search (DFS), emit an opening curly brace for nested objects, map primitive values to string, number, or boolean, and sprinkle a few regular expressions to format the output.Yet, the moment you subject such naive scripts to real-world production payloads—deeply nested microservice responses, eve
Theme App Extensions vs Script Tags: What Changed and Why It Matters
Theme App Extensions vs Script Tags: What Changed and Why It MattersIf an app on your store still injects itself via script tags instead of a theme app extension block, that's worth noticing — it's the older pattern, and it causes problems that theme app extensions were specifically built to fix. 🩹 What Script Tags Actually BrokeScript-tag apps inject JavaScript globally and hope it finds the right place in the DOM. Change themes, update a template, or install a second app doing the s
Stop dividing by 4. I counted 951 texts and the rule is wrong both ways.
Most token guides say one token is about four characters, and a lot of code runs Math.ceil(text.length / 4) right before an API call without anyone checking it.I build an LLM cost calculator, so this number ends up inside every estimate I make. This week I finally counted. I ran 951 text samples through OpenAI's o200k_base tokenizer (GPT-4o and newer) with tiktoken 0.14.0. Characters per tokenContentCharacters per tokenlength / 4 gives youEnglish blog writing4.981.24x the real countEnglish
Drawing semi-log and log-log graph paper: the math behind the lines
Semi-log graph paper looks like someone drew it by hand with a shaky ruler: the lines bunch uptoward the top of every band and then start over. It is actually one of the most regular gridsthere is. Every line comes from a single formula, and the only real decision is how many linesto draw before the page turns grey.I recently added semi-log and log-log paper to a printable graph paper generator, and these arethe notes I wish I'd had before starting. One decade, one formulaOn a log axis, a v
How Transferify encrypts files in your browser
Every file you send with Transferify is encrypted in your browser before any of its bytes leave your device. The cipher is AES-256-GCM, run by your browser's built-in Web Crypto API, and the key is made on your device for each transfer. The sending modes differ in one thing only: where that key goes afterwards.This post explains the mechanism for readers who want to check it: how the key is made, how a file is cut and sealed, what stops a stored file from being changed, and who can unlock it in
Detecting emoji that Windows 10 can't draw, and swapping in images without breaking copy
I run CopyCute, a small site of cute symbols and kaomoji. I started it after watching a friend search all over the place just to find a few emoji they wanted. Almost everything on the site is plain text, which is the whole point: you tap an item, it goes to your clipboard, and you paste it into a bio or a nickname.Plain text has one catch. I don't control how a character is drawn. The visitor's fonts do. For most symbols that's fine, but emoji have a hard cutoff on Windows 10, and I wanted to ha
Add a live filter to a server-rendered list with one script tag
Every server-rendered app ends up with this ticket:The team page has 40 people on it. Can we add a search box?You can build it. You can also solve it the way many teams do: render the list again in JavaScript, fetch JSON from a new endpoint, or turn the page into an SPA. All of those mean the list now exists twice, once on the server and once in the browser, and you have to keep them in agreement.There's a smaller option. The server already sent the list. The filter only has to hide the rows tha
Why Crypto Tax Calculators Overstate Swap Gains on Base (And How to Audit Unlimited Permit2 Exposures Client-Side)
Every crypto tax tool I have audited on Base makes the same two mistakes, and both inflate a number the user is about to hand to an accountant. One is a swap priced from two different sources that cannot agree. The other is a disposal with no cost basis scored as a 100% loss. Neither is exotic. Both are arithmetic that looks correct until you check that a swap should net to zero.This post is the working notes from building a browser-only scanner and tax exporter for Base, with the real numbers f
Your preventDefault() Did Nothing, and the Only Warning Went to a Phone You Do Not Have
The report says the page scrolled while they were dragging the slider. Or that pull-to-refresh fired in the middle of a swipe. Or that the carousel moved and the page moved with it.You open the handler and it is right there, the line that is supposed to stop exactly this:document.addEventListener("touchmove", (e) => { e.preventDefault() drag(e)})It is being ignored. Not failing, not throwing, not running late. Ignored, by the specification, and the only notice anybody gets is a console warn
Opening hours component in React with time zones
The first "Open now" badge I shipped for a client lied. The salon was in Zurich, the site was deployed on servers in the US, and I was testing from my laptop at home. It showed "Open" at 11 pm because somewhere in the chain a date was created in the wrong time zone. That bug is the reason the Opening hours component and the Open now badge in Facade compute everything in the business's own IANA time zone and never trust the raw clock. Here is how they work. Why new Date() on the client is wr
React & Modern UI Stack
IntroThe React & Modern UI Stack path covers the essential frontend ecosystem and modern tooling roadmap, built directly on top of the Core Web Stack foundation. Tutorials00. Core Web Stack Path ✅Internet Beginner: ✅ Start Now — Learn how the web works, client-server architecture, and HTTP request-response cycles.HTML: ✅ Start Now — Master semantic markup, document structure, and web form fundamentals.CSS: ✅ Start Now — Build responsive layouts using modern styling, Flexbox, and C
Prompt packs for empty / error / loading states — stop shipping happy-path only
Agents are weirdly good at the happy path. Give them a Figma frame of a filled dashboard and you get a filled dashboard. Give them a “build a projects list” prompt and you get rows, avatars, and a neat toolbar.What you usually don’t get: the empty list on day one, the 500 that lands mid-scroll, or the skeleton that doesn’t jump when real data arrives. Those states are where users decide whether the product feels finished — and they’re the first thing agents skip unless you ask for them on purpos
TypeScript Email Fixtures That Fail Clearly
Email verification tests often fail in the least helpful way: a button is clicked, a test waits, and then the runner reports a timeout. The product may be fine. The test may have created the wrong inbox. An old message may have won the race. Or the polling helper simply forgot to record what it saw.I like solving this at the fixture boundary. If a test needs to generate disposable email, the returned value should be more than a string. It should carry the inbox identity, the trigger time, and en
Next.js Cache Not Working? A 10-Step Checklist for Next.js 15 and 16
Quick SummaryYou save some data. The database says yes. The page still shows the old data. If your Next.js cache is not working, Next.js is usually doing what you told it to do, just on an old copy of the page that you forgot about. A Next.js page can live in four places at once: the build, the server, the browser, and a CDN. Below are five quick questions and 10 steps in order. They help you find the old copy and fix it, for Next.js 15 and for the new use cache style in Next.js 16. K
I got tired of simple browser caches, so I built one in Rust
A while ago, I kept running into the same problem.I wanted a client-side cache that felt solid enough for real apps — not just a quick Map wrapper, and not something locked into one data-fetching library.Most options were either:too minimaltoo framework-specificor not very predictable once the app got biggerSo I tried a different approach.Instead of keeping everything in JavaScript, I moved the cache engine into Rust and compiled it to WebAssembly.That project became Blaze Cache. The ideaTh
Split a File Into Parts in the Browser: The SHA-256 Manifest and a Verified Rejoin
I work on OnePassApps, so I am writing about a tool we ship.Splitting a big file usually means uploading it: to a converter site, to a drive, to yourself. The File Studio at app.onepassapps.com splits a file into parts and hands you back a bundle with a manifest, in the tab. What the split panel actually saysThe panel is three stages, and the copy is specific:Part size (MiB) - "A whole number from 1 to 64."Result - "Ready", then "Created 1 part and a verified manifest for 3.1 MiB."Bundle -
My Bloom Filter's Exact Formula Returned 1e+227 Per Cent
A Bloom filter makes exactly one promise and keeps it absolutely: no false negatives. Everything else is a rate you are choosing, whether or not you realise it.👉 Live, every number measured in your browser: https://dev48.in/solve/day82-bloom-filter.html The formula everyone quotes is optimisticp = (1 − e^(−kn/m))^kIt assumes the k bits a key sets are independent. They are not, and it is a limit result. At a fixed m/n ratio of 6.4, with only the size changing:filtertextbookexacterrordirectio
Storing the Selection as an Index Is Why Your Command Palette Sometimes Runs the Wrong Thing
Every Cmd-K palette has the same two halves. The half you see is a list that filters as you type. The half that decides whether it feels right is the ranking. And the half that decides whether it is safe is what happens to the selection when the list changes underneath it.👉 Live, type into it: https://dev48.in/design/day82-raycast-palette.html The bugType c, press Down twice, keep typing. Here is what happens if the selection is stored as an index:statepositionselected commandbefore, query
My Kakuro Solver's Baseline Was Solving a Different Puzzle, and the Page Asserted They Agreed
Kakuro is a crossword made of sums. Each run of white cells carries a clue, the digits come from 1 to 9, and no digit repeats inside a run. That last rule is the whole puzzle — it turns a clue into a question about which sets of distinct digits hit a total.👉 Live, runs in your browser: https://dev48.in/game/day82-kakuro.htmlI built the page to show one thing: candidate sets beat raw arithmetic. It did show that. It also showed me three defects in my own code, and none of them was the one I first