[{"data":1,"prerenderedAt":270},["ShallowReactive",2],{"post-microcopy-that-makes-interfaces-human":3,"blog-posts":14},{"_path":4,"title":5,"description":6,"date":7,"tags":8,"readingTime":12,"body":13},"\u002Fblog\u002Fmicrocopy-that-makes-interfaces-human\u002F","Microcopy That Makes Interfaces Feel Human","Button labels, error lines, and helper text are product design. How to write UI words that reduce hesitation without sounding like a chatbot.","2025-01-22",[9,10,11],"ux","writing","design",5,"# Microcopy That Makes Interfaces Feel Human\n\nInterfaces speak in fragments: button verbs, empty hints, error reasons, confirm dialogs. Those scraps decide whether someone feels guided or blamed. Microcopy is design work that happens in sentences.\n\n## Prefer specific verbs over vague chrome\n\nGeneric labels force people to guess. “Submit,” “OK,” and “Continue” are sometimes inevitable; more often they hide a better verb that names the outcome.\n\nCompare:\n\n- “Submit” vs “Create paste”\n- “OK” vs “Delete export”\n- “Continue” vs “Start local analysis”\n- “Click here” vs the actual destination name\n\nSpecific verbs also clarify danger. A button that says “Delete forever” sets stakes better than “Confirm.” If an action is reversible, say so nearby—“You can undo this for 30 seconds”—instead of hoping the label alone carries the nuance.\n\nMatch the verb to the system’s real behavior. If the app only queues a job, “Publish” may oversell. If encryption happens on-device before upload, “Encrypt & upload” teaches the model better than “Save.” Microcopy is how architecture becomes understandable.\n\nKeep casing and grammar consistent across the product. Title Case Everywhere looks loud; sentence case often reads calmer. Pick a convention and apply it to buttons, tabs, and nav alike so the UI does not feel like several products stitched together.\n\nIcons do not replace words for primary actions. A trash can may be familiar, but pairing it with “Delete” removes doubt—especially across cultures and experience levels. Use icon-only controls sparingly, and always give them an accessible name that matches the visible verb elsewhere in the product.\n\n## Write errors that teach recovery\n\nError text is where products sound either helpful or hostile. The useful pattern is short and structural: what happened, why it matters if needed, what to try next.\n\nStronger errors:\n\n- “Couldn’t read that ZIP. Export a data download from Instagram, then choose the file again.”\n- “Paste is empty—add text or code before creating a link.”\n- “This link expired and was deleted. Create a new paste to share again.”\n\nWeaker errors:\n\n- “Something went wrong.”\n- “Invalid input.”\n- “Error 500.”\n- “You broke the form.” (even as a joke)\n\nInclude an identifier only when it helps support—correlation IDs for production apps, not stack traces for civilians. Never echo secrets, tokens, or raw file contents back into the page “for debugging.”\n\nTone should fit context. Playful copy on a success toast can work; playful copy on a failed payment or privacy tool failure rarely does. Calm, plain language scales better than forced personality under stress.\n\n## Use helper text to prevent mistakes, not to decorate\n\nHelper text under inputs is valuable when it answers a question the label cannot. Character limits, format examples, and privacy notes belong there. Repeating the label in longer words does not.\n\nGuidelines that hold up:\n\n- Place the constraint before the user fails (“Max 500 characters”)\n- Show examples for formats people get wrong (`YYYY-MM-DD`, not “enter a date”)\n- Disclose side effects near the control (“Stored encrypted until the expiry you choose”)\n- Remove helpers that only restate the obvious once the pattern is learned—or progressive-disclose them\n\nPlaceholder text is not a label. When the placeholder vanishes on focus, the field loses its name. Use a visible label; reserve placeholders for examples if you use them at all.\n\nFor confirmations, ask a real question with consequences in the body, not only in the title. “Delete this paste? Anyone with the link will lose access immediately.” Then pair with buttons that mirror the consequence—“Delete paste” \u002F “Keep paste”—instead of Yes\u002FNo.\n\n## Edit like a product surface, not a blog draft\n\nMicrocopy improves through constraint. Set a soft budget: primary buttons roughly under four words, errors under two short sentences, empty states with one action.\n\nEdit passes worth doing:\n\n1. Read every primary button aloud in order—do they form a coherent story?\n2. Search for “click,” “simply,” and “just”—usually filler or condescension\n3. Check that destructive actions never share a color+label pattern with safe ones\n4. Verify the same concept uses the same word (“paste” vs “snippet” vs “bin” randomly)\n\nTranslate early if you expect multiple locales. Clever idioms and puns break in translation and often break clarity even in English. Plain language is easier to localize and kinder to readers who skim.\n\nFinally, keep UI strings in a place you can review—message files or a shared copy list—not sprinkled as magic literals nobody finds. Reviewing copy in one pass catches contradictions that code review alone will miss.\n\nIf you work solo, schedule a copy pass the same way you schedule an accessibility pass: after the flow works, before you call it done. Reading the UI aloud—literally—is an underrated test. Awkward rhythms and doubled words show up in speech faster than in silent skimming.\n\n## Wrap-up\n\nHuman-feeling interfaces come from specific verbs, recoverable errors, honest helpers, and disciplined editing. Treat every label as part of the product’s voice. When the words point clearly at outcomes and next steps, the UI needs less chrome to feel friendly.",[15,24,34,42,49,57,64,72,79,86,93,101,107,114,121,129,135,143,152,160,166,173,179,187,195,202,208,214,221,227,233,239,246,253,255,263],{"_path":16,"title":17,"description":18,"date":19,"tags":20,"readingTime":12},"\u002Fblog\u002Fclient-side-tools-that-earn-trust\u002F","Client-Side Tools That Earn Trust","How to design browser tools that feel private by default—local processing, clear data boundaries, and UX that never asks people to guess where their files go.","2026-07-20",[21,22,23],"privacy","frontend","tools",{"_path":25,"title":26,"description":27,"date":28,"tags":29,"readingTime":33},"\u002Fblog\u002Fusb-c-cables-that-actually-matter\u002F","USB-C Cables That Actually Matter","How to buy USB-C cables by wattage and data speed so you stop guessing which cord charges slowly or fails a file transfer.","2026-07-14",[30,31,32],"gadgets","hardware","productivity",4,{"_path":35,"title":36,"description":37,"date":38,"tags":39,"readingTime":12},"\u002Fblog\u002Fcolor-contrast-people-can-read\u002F","Color Contrast People Can Actually Read","Quick checks for text and UI colors that stay legible in light mode, dark mode, and on mediocre displays.","2026-07-07",[40,41,11],"accessibility","css",{"_path":43,"title":44,"description":45,"date":46,"tags":47,"readingTime":12},"\u002Fblog\u002Fportable-ssds-worth-carrying\u002F","Portable SSDs Worth Carrying","When a pocket SSD beats cloud sync for travel, backups, and large media—and how to pick one that stays fast and durable.","2026-06-26",[30,48,32],"storage",{"_path":50,"title":51,"description":52,"date":53,"tags":54,"readingTime":12},"\u002Fblog\u002Fwireless-earbuds-that-last-the-day\u002F","Wireless Earbuds That Last the Day","Simple charging and fit habits that stretch earbud battery life without babysitting the case every few hours.","2026-06-18",[30,55,56],"audio","habits",{"_path":58,"title":59,"description":60,"date":61,"tags":62,"readingTime":33},"\u002Fblog\u002Fwhen-a-second-monitor-helps\u002F","When a Second Monitor Actually Helps","A practical take on dual screens for coding, writing, and research—plus when a single good display is still the better desk.","2026-06-10",[30,32,63],"workspace",{"_path":65,"title":66,"description":67,"date":68,"tags":69,"readingTime":33},"\u002Fblog\u002Fshort-session-game-picks\u002F","Short-Session Games That Respect Your Evening","Genres and design patterns that fit a 30-minute window without the “one more hour” trap.","2026-06-04",[70,56,71],"gaming","indie",{"_path":73,"title":74,"description":75,"date":76,"tags":77,"readingTime":12},"\u002Fblog\u002Fphone-charging-habits-that-age-better\u002F","Phone Charging Habits That Age Better","Practical charging routines that keep a phone useful longer—without obsessing over the perfect battery percentage.","2026-05-23",[30,78,56],"mobile",{"_path":80,"title":81,"description":82,"date":83,"tags":84,"readingTime":12},"\u002Fblog\u002Ffinishing-side-projects-without-burning-out\u002F","Finishing Side Projects Without Burning Out","A practical playbook for shrinking scope, shipping thin vertical slices, and keeping personal projects fun long enough to actually launch.","2026-05-14",[32,85,56],"side-projects",{"_path":87,"title":88,"description":89,"date":90,"tags":91,"readingTime":12},"\u002Fblog\u002Faccessible-forms-people-finish\u002F","Accessible Forms That People Actually Finish","Practical accessibility checks for labels, errors, and focus so your forms work for more users.","2026-05-07",[40,92,22],"html",{"_path":94,"title":95,"description":96,"date":97,"tags":98,"readingTime":12},"\u002Fblog\u002Fvue-composition-api-patterns\u002F","Practical Vue Composition API Patterns","Reusable patterns for composables, shared state, and cleaner component logic in Vue 3.","2026-04-27",[99,100,22],"vue","javascript",{"_path":102,"title":103,"description":104,"date":105,"tags":106,"readingTime":12},"\u002Fblog\u002Fdesigning-empty-states-that-teach\u002F","Designing Empty States That Teach the Product","Empty screens are not placeholders—they are onboarding. How to write, layout, and sequence first-run UI so people know what to do next.","2026-04-19",[9,22,11],{"_path":108,"title":109,"description":110,"date":111,"tags":112,"readingTime":12},"\u002Fblog\u002Fwhy-indie-games-keep-winning\u002F","Why Indie Games Keep Winning Attention","How small teams punch above their weight with focused design, personality, and smart scope.","2026-04-13",[70,71,113],"industry",{"_path":115,"title":116,"description":117,"date":118,"tags":119,"readingTime":12},"\u002Fblog\u002Fkeeping-component-props-simple\u002F","Keeping Component Props Simple","When to split a component, when to use slots, and how to avoid prop objects that grow forever.","2026-04-03",[99,22,120],"best-practices",{"_path":122,"title":123,"description":124,"date":125,"tags":126,"readingTime":12},"\u002Fblog\u002Fcalm-frontend-performance\u002F","A Calm Approach to Frontend Performance","Performance work that sticks: measure what users feel, fix the critical path first, and avoid optimization theater on personal and portfolio sites.","2026-03-26",[127,22,128],"performance","web",{"_path":130,"title":131,"description":132,"date":133,"tags":134,"readingTime":12},"\u002Fblog\u002Fcss-layout-without-the-hacks\u002F","CSS Layout Without the Hacks","Modern Flexbox and Grid techniques that replace brittle floats, magic numbers, and overflow tricks.","2026-03-17",[41,22,11],{"_path":136,"title":137,"description":138,"date":139,"tags":140,"readingTime":12},"\u002Fblog\u002Fcloud-gaming-what-gets-in-the-way\u002F","Cloud Gaming: What Still Gets in the Way","Latency, input feel, and library lock-in—why streaming games is impressive and still uneven.","2026-03-10",[70,141,142],"cloud-gaming","tech",{"_path":144,"title":145,"description":146,"date":147,"tags":148,"readingTime":12},"\u002Fblog\u002Fshipping-static-sites-with-nuxt\u002F","Shipping Static Sites with Nuxt","How I build and deploy a Nuxt site to Cloudflare Pages with predictable routes and content.","2026-03-02",[149,150,151],"nuxt","ssg","devops",{"_path":153,"title":154,"description":155,"date":156,"tags":157,"readingTime":12},"\u002Fblog\u002Fdebugging-faster-in-the-browser\u002F","Debugging Faster in the Browser","A short toolkit of DevTools habits—breakpoints, network filters, and DOM inspection—that cut debug time.","2026-02-24",[100,158,159],"devtools","debugging",{"_path":161,"title":162,"description":163,"date":164,"tags":165,"readingTime":12},"\u002Fblog\u002Fsmall-javascript-habits-that-scale\u002F","Small JavaScript Habits That Scale","Everyday habits—naming, early returns, and clearer async flow—that keep front-end codebases maintainable.","2026-02-18",[100,120,22],{"_path":167,"title":168,"description":169,"date":170,"tags":171,"readingTime":33},"\u002Fblog\u002Fhealthier-gaming-routine\u002F","Building a Healthier Gaming Routine","Simple habits for sessions that stay fun—breaks, goals, and knowing when to stop.","2026-02-02",[70,56,172],"wellness",{"_path":174,"title":175,"description":176,"date":177,"tags":178,"readingTime":12},"\u002Fblog\u002Fresponsive-images-without-layout-shift\u002F","Responsive Images Without Layout Shift","Width, height, srcset, and lazy loading patterns that keep pages stable while images load.","2026-01-22",[92,127,22],{"_path":180,"title":181,"description":182,"date":183,"tags":184,"readingTime":12},"\u002Fblog\u002Fgit-habits-for-small-teams\u002F","Git Habits for Solo and Small Teams","Branch naming, commit messages, and PR hygiene that keep history useful without slowing you down.","2026-01-09",[185,186,32],"git","workflow",{"_path":188,"title":189,"description":190,"date":191,"tags":192,"readingTime":12},"\u002Fblog\u002Fwhat-makes-a-game-stream-worth-watching\u002F","What Makes a Game Stream Worth Watching","Commentary, pacing, and community—why some streams click even when the gameplay is messy.","2025-12-14",[70,193,194],"streaming","content",{"_path":196,"title":197,"description":198,"date":199,"tags":200,"readingTime":12},"\u002Fblog\u002Fwhen-to-reach-for-typescript-vue\u002F","When to Reach for TypeScript on a Vue App","A pragmatic take on where TypeScript pays off in Vue—and where plain JS is still fine.","2025-11-30",[201,99,22],"typescript",{"_path":203,"title":204,"description":205,"date":206,"tags":207,"readingTime":12},"\u002Fblog\u002Fenvironment-variables-for-static-sites\u002F","Environment Variables for Static Sites","How to use build-time env vars in Nuxt and other static generators without leaking secrets or breaking CI.","2025-10-05",[149,151,22],{"_path":209,"title":210,"description":211,"date":212,"tags":213,"readingTime":12},"\u002Fblog\u002Fpicking-a-side-project-stack\u002F","Picking a Side Project Stack Without Overthinking It","How to choose tools for a personal project when the goal is shipping, not building the perfect architecture.","2025-09-18",[32,22,120],{"_path":215,"title":216,"description":217,"date":218,"tags":219,"readingTime":33},"\u002Fblog\u002Fco-op-games-for-busy-friends\u002F","Co-op Games That Work When Everyone Is Busy","Async-friendly and drop-in co-op picks for friend groups that rarely share the same free evening.","2025-08-22",[70,220,56],"co-op",{"_path":222,"title":223,"description":224,"date":225,"tags":226,"readingTime":12},"\u002Fblog\u002Fsemantic-html-still-matters\u002F","Semantic HTML Still Matters","Landmarks, headings, and native elements that make pages easier to use, style, and maintain.","2025-07-06",[92,40,22],{"_path":228,"title":229,"description":230,"date":231,"tags":232,"readingTime":12},"\u002Fblog\u002Fgit-without-the-jargon\u002F","Learning Git Without the Jargon","A plain-language mental model for commits, branches, and merges when tutorials assume you already know Git.","2025-05-14",[185,186,32],{"_path":234,"title":235,"description":236,"date":237,"tags":238,"readingTime":12},"\u002Fblog\u002Fwhy-loading-states-matter\u002F","Why Loading States Matter More Than Animations","Skeletons, disabled buttons, and honest feedback beat flashy spinners when data takes time to arrive.","2025-03-28",[9,22,11],{"_path":240,"title":241,"description":242,"date":243,"tags":244,"readingTime":12},"\u002Fblog\u002Fnaming-things-so-future-you-survives\u002F","Naming Things So Future You Survives","Practical rules for naming variables, components, and files so a codebase stays readable months after the clever jokes fade.","2025-03-10",[100,120,245],"maintainability",{"_path":247,"title":248,"description":249,"date":250,"tags":251,"readingTime":12},"\u002Fblog\u002Fsave-systems-that-respect-time\u002F","Save Systems That Respect the Player’s Time","Checkpoints, autosaves, and manual slots are design choices. How thoughtful saving reduces rage-quits without deleting tension from the game.","2025-02-28",[70,252,9],"game-design",{"_path":4,"title":5,"description":6,"date":7,"tags":254,"readingTime":12},[9,10,11],{"_path":256,"title":257,"description":258,"date":259,"tags":260,"readingTime":12},"\u002Fblog\u002Freadmes-that-get-projects-running\u002F","READMEs That Get Projects Running","How to write a README that helps someone—including future you—install, run, and understand a project without opening a support chat.","2024-12-18",[261,262,56],"documentation","open-source",{"_path":264,"title":265,"description":266,"date":267,"tags":268,"readingTime":12},"\u002Fblog\u002Fprogressive-enhancement-still-pays-off\u002F","Progressive Enhancement Still Pays Off","Build the core experience in HTML first, then layer CSS and JavaScript so your site stays useful when networks, scripts, or devices misbehave.","2024-11-05",[92,22,269],"architecture",1784620505240]