[{"data":1,"prerenderedAt":270},["ShallowReactive",2],{"post-finishing-side-projects-without-burning-out":3,"blog-posts":14},{"_path":4,"title":5,"description":6,"date":7,"tags":8,"readingTime":12,"body":13},"\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",[9,10,11],"productivity","side-projects","habits",5,"# Finishing Side Projects Without Burning Out\n\nSide projects rarely die from bad ideas. They die from scope that grows faster than energy. Finishing is a design problem: protect momentum, cut ruthlessly, and treat “done” as a skill you practice.\n\n## Define done before you write clever code\n\nOpen a blank note and write the smallest thing that would still make you proud to show someone. Not the roadmap—the first shippable slice.\n\nGood definitions of done are observable:\n\n- “A static page that lists three posts and opens each one”\n- “A paste form that encrypts in the browser and returns a link”\n- “A CSS theme toggle that survives refresh”\n\nBad definitions hide work: “a polished platform,” “something like Notion,” “but with AI.” Those are directions, not finish lines. If you cannot demo the outcome in five minutes, the slice is still too big.\n\nPut the definition where you will see it—README top, sticky note, project board card titled **v1**. Everything else goes under **later** without apology. You are not abandoning features; you are sequencing them after evidence that the core works.\n\nRevisit the definition when you feel the itch to rewrite. Often the rewrite urge is avoidance: polishing architecture feels productive when the scary part is putting a link in front of people. If the definition of done is still unmet, shipping beats refactoring.\n\n## Work in vertical slices, not horizontal layers\n\nHorizontal work looks like: build the entire auth system, then the entire database layer, then finally one screen. Vertical slices flip that: one thin path from UI to result, end to end, even if it is ugly.\n\nA vertical slice for a small web tool might be:\n\n1. Hardcoded sample data rendered in the UI\n2. Replace sample data with a local file parse\n3. Add error and empty states\n4. Add download of results\n5. Only then consider persistence or accounts\n\nEach step leaves you with something runnable. That matters psychologically. Horizontal layers leave you with half a foundation and nothing to show, which is when weekends start feeling like unpaid work.\n\nResist the urge to “just finish the models first.” Data models without a screen are invisible progress. If you need a model, invent the smallest one the current slice requires—often a plain object or a JSON file—and refine shape when a second screen demands it. Premature generality is a common way ambitious side projects stall in week two.\n\nTimebox the slice. Ninety minutes of focused work with a clear “stop when this path works” beats an open-ended Saturday. When the timer ends, write a two-line note: what works, what is next. Future you should be able to resume without reconstructing context from memory. If you cannot write those two lines, the slice was too vague—shrink it before the next session.\n\n## Protect energy with constraints, not motivation\n\nMotivation is weather. Constraints are climate. Decide your constraints while you still like the project.\n\nUseful constraints:\n\n- **Session length** — 45–90 minutes, then stop even if you are “in the zone.” Stopping on a high note makes the next session easier to start.\n- **Scope freeze** — during a sprint toward v1, new ideas go in a parking lot file. You may add them after launch, not before.\n- **Tech freeze** — no new framework mid-build. Novelty is fun; unfinished repos are full of abandoned novelty.\n- **Social checkpoint** — show a draft to one person before you add another feature. External eyes shrink ego scope.\n\nBurnout on side projects often comes from treating them like a second job without the boundaries of a job. You do not owe your hobby nightly deploys. A sustainable cadence—two evenings a week, or one long morning—beats heroic streaks that vanish for a month.\n\nWatch for recovery debt: after a crunch to “just finish this,” take a deliberate pause. Projects that only move under guilt eventually stop moving.\n\n## Ship ugly, then improve what users actually touch\n\nLaunch criteria should favor learning over aesthetics. A readable layout, working core flow, and honest copy beat a custom illustration set and three unfinished settings panels.\n\nMake a pre-launch checklist that is allowed to be short:\n\n- Core path works on your phone and a second browser\n- Empty and error states exist for the main flow\n- README explains how to run it in under five minutes\n- You would not be embarrassed to send the link to one trusted person\n\nThat is enough for v1. Pixel-perfect spacing can wait for v1.1.\n\nAfter you ship:\n\n- Instrument only what helps you decide (even qualitative notes count)\n- Fix the top friction you hear twice\n- Ignore edge-case feature requests until the main path feels smooth\n- Schedule polish passes: accessibility, performance, visual consistency—as named milestones, not endless tinkering\n\nPublic shipping also closes the loop emotionally. A live URL turns vague shame (“I never finish anything”) into a concrete artifact. That identity shift—“I ship small things”—is more valuable than any single feature. Keep a personal “shipped” list; on hard weeks it reminds you that unfinished drafts are not your whole story.\n\nIf the project is private by nature, “ship” can mean a tagged release, a recorded demo, or a README that another developer could run. The point is a finish line you cannot move after the fact. Moving the finish line is how burnout dresses up as perfectionism.\n\n## Wrap-up\n\nFinishing side projects is less about grinding harder and more about deciding earlier. Write a tiny definition of done, advance in vertical slices, bind your energy with constraints, and ship before the polish fantasy eats the calendar. Burnout fades when progress is visible and “later” is allowed to stay later.",[15,24,33,42,49,56,63,71,78,80,87,95,102,109,116,124,130,138,147,155,161,168,174,182,190,197,203,209,216,222,228,234,241,248,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":32},"\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,9],"gadgets","hardware",4,{"_path":34,"title":35,"description":36,"date":37,"tags":38,"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",[39,40,41],"accessibility","css","design",{"_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,9],"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,11],"audio",{"_path":57,"title":58,"description":59,"date":60,"tags":61,"readingTime":32},"\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,9,62],"workspace",{"_path":64,"title":65,"description":66,"date":67,"tags":68,"readingTime":32},"\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",[69,11,70],"gaming","indie",{"_path":72,"title":73,"description":74,"date":75,"tags":76,"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,77,11],"mobile",{"_path":4,"title":5,"description":6,"date":7,"tags":79,"readingTime":12},[9,10,11],{"_path":81,"title":82,"description":83,"date":84,"tags":85,"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",[39,86,22],"html",{"_path":88,"title":89,"description":90,"date":91,"tags":92,"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",[93,94,22],"vue","javascript",{"_path":96,"title":97,"description":98,"date":99,"tags":100,"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",[101,22,41],"ux",{"_path":103,"title":104,"description":105,"date":106,"tags":107,"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",[69,70,108],"industry",{"_path":110,"title":111,"description":112,"date":113,"tags":114,"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",[93,22,115],"best-practices",{"_path":117,"title":118,"description":119,"date":120,"tags":121,"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",[122,22,123],"performance","web",{"_path":125,"title":126,"description":127,"date":128,"tags":129,"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",[40,22,41],{"_path":131,"title":132,"description":133,"date":134,"tags":135,"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",[69,136,137],"cloud-gaming","tech",{"_path":139,"title":140,"description":141,"date":142,"tags":143,"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",[144,145,146],"nuxt","ssg","devops",{"_path":148,"title":149,"description":150,"date":151,"tags":152,"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",[94,153,154],"devtools","debugging",{"_path":156,"title":157,"description":158,"date":159,"tags":160,"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",[94,115,22],{"_path":162,"title":163,"description":164,"date":165,"tags":166,"readingTime":32},"\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",[69,11,167],"wellness",{"_path":169,"title":170,"description":171,"date":172,"tags":173,"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",[86,122,22],{"_path":175,"title":176,"description":177,"date":178,"tags":179,"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",[180,181,9],"git","workflow",{"_path":183,"title":184,"description":185,"date":186,"tags":187,"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",[69,188,189],"streaming","content",{"_path":191,"title":192,"description":193,"date":194,"tags":195,"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",[196,93,22],"typescript",{"_path":198,"title":199,"description":200,"date":201,"tags":202,"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",[144,146,22],{"_path":204,"title":205,"description":206,"date":207,"tags":208,"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",[9,22,115],{"_path":210,"title":211,"description":212,"date":213,"tags":214,"readingTime":32},"\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",[69,215,11],"co-op",{"_path":217,"title":218,"description":219,"date":220,"tags":221,"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",[86,39,22],{"_path":223,"title":224,"description":225,"date":226,"tags":227,"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",[180,181,9],{"_path":229,"title":230,"description":231,"date":232,"tags":233,"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",[101,22,41],{"_path":235,"title":236,"description":237,"date":238,"tags":239,"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",[94,115,240],"maintainability",{"_path":242,"title":243,"description":244,"date":245,"tags":246,"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",[69,247,101],"game-design",{"_path":249,"title":250,"description":251,"date":252,"tags":253,"readingTime":12},"\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",[101,254,41],"writing",{"_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,11],"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",[86,22,269],"architecture",1784620504462]