<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>letanure.dev, writing</title>
    <link>https://letanure.dev/</link>
    <description>Essays, tools, and notes on frontend craft, design systems, and the workshop in the corner of the room.</description>
    <language>en-us</language>
    <lastBuildDate>Fri, 01 May 2026 11:17:25 GMT</lastBuildDate>
    <item>
      <title>Generative tile fallbacks</title>
      <link>https://letanure.dev/writing/generative-tile-fallbacks/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/generative-tile-fallbacks/</guid>
      <pubDate>Fri, 01 May 2026 00:00:00 GMT</pubDate>
      <description>Empty image slots looked sad. Real photos weren&apos;t ready. So I built a deterministic Canvas2D engine that fills every missing tile with art derived from the slot&apos;s slug, plus a playground.</description>
      <content:encoded><![CDATA[<p>Most of this site is content I haven’t shot yet. The workshop pages need photos of vessels and prints. The project case studies need screenshots. Until those exist, every tile is a paper-colored gradient with a date pill on top, perfectly fine, perfectly forgettable.</p>
<p>I wanted the absence of a photo to <em>say</em> something. Not “loading,” not “TODO,” but a piece of the site’s voice that’s interesting in itself. Something deterministic, so the same workshop entry always renders the same art, and themed, so a paint tile reads differently from a 3D-print tile.</p>
<p>Below this post is the playground. Type a seed, pick a kind, hit shuffle, same machinery the workshop tiles use.</p>
<h2 id="what-i-rejected">What I rejected</h2>
<p>I started with static SVG riso, two-color silkscreen with offset duplicates and a grain pattern. It was the cleanest thing to build (pure functions, build-time, zero runtime JS, theme-aware via CSS variable cascade) and I had a working version inside an afternoon.</p>
<p>It looked polluted. Every tile carried the same dot grain. The shapes were too small. Cropping at varying tile aspects produced the worst of both worlds, a tiny silhouette stranded in a sea of paper. The signature was <em>everywhere</em>, which meant nowhere.</p>
<p>So I researched the alternatives and asked two questions: what visual register do I actually want, and what’s the smallest tool that gets me there.</p>



































<table><thead><tr><th>Option</th><th>Bundle</th><th>Verdict</th></tr></thead><tbody><tr><td>three.js</td><td>~160 KB gz</td><td>Overkill for static tiles. WebGL contexts cap around 8-16 per page.</td></tr><tr><td>paper.js</td><td>~70 KB gz</td><td>Strong at boolean path ops; we don’t need them. Re-tinting requires walking a scene graph.</td></tr><tr><td>d3.js</td><td>~12-15 KB tree-shaken</td><td>Wrong category, chart kit, not drawing engine.</td></tr><tr><td>WebGL fragment shader</td><td>~5 KB hand-rolled</td><td>Beautiful for soft fields, wrong register for printed-matter blocks.</td></tr><tr><td>Canvas2D + shape grammar</td><td>0 KB</td><td>200 lines, every pixel under control, multiply-blend native, instant theme retint.</td></tr></tbody></table>
<p>Canvas2D won. The “polluted” feeling from the SVG attempt wasn’t the medium, it was loose rules. Hand-rolled gives stricter rules for free.</p>
<h2 id="what-ended-up-working">What ended up working</h2>
<p>Each <em>kind</em> of tile gets its own composer function: <code>compose3d</code>, <code>composeLaser</code>, <code>composePaint</code>, etc. The composer takes the tile’s actual <code>(width, height)</code> and lays out a multi-element scene that fills it. No fixed reference frame, no “scale this 500-unit illustration to fit min(w,h)”, that’s what produced the postage-stamp problem.</p>
<p>The 3D-print tile is a parametric city of isometric boxes scattered across the tile. Laser is a blueprint with a grid + central machine drawing. Paint is overlapping painterly smears with brush marks. Each kind picks a fixed five-token palette, <code>[outline, mid-dark, accent, accent, lightest]</code>, so all paint tiles read clay-on-paper, all wood tiles read deep-red on paper, the workshop type <em>is</em> the visual identity.</p>
<p>Determinism is a tiny PRNG (<code>xmur3</code> hash → <code>sfc32</code> stream, ~30 lines, public-domain). Same slug → same float sequence → same composition. Adding a new workshop entry produces new art automatically; renaming an entry produces <em>different</em> art (intentional, the slug is the identity).</p>
<p>Theme awareness is <code>getComputedStyle(document.documentElement).getPropertyValue(&#39;--clay&#39;)</code>. When the user hits <code>T</code> to toggle workshop / editorial / dark, the canvas re-paints with the freshly resolved tokens. Same seed, same composition, different colors.</p>
<h2 id="things-i-had-to-fight">Things I had to fight</h2>
<p><strong>Aspect ratio.</strong> First pass scaled everything by <code>min(w, h)</code> and centered. Worked for square tiles, looked terrible on wide hero strips and tall span-2 cells. Fixed by passing <code>(w, h)</code> directly to each composer and letting it decide how to fill, some kinds (laser grid, wood grain) bleed full-frame, some (cube) stay roughly square but use the room for spacing, some (filmstrip vertical bars) span all the way across.</p>
<p><strong>Theme retint without flicker.</strong> The canvas paints whatever color the tokens currently resolve to. Before the script runs, the canvas is empty, there’s a CSS class (<code>kind-laser</code> etc.) on the canvas that paints a sensible bg color in the meantime. SSR-safe: no JS, the right base color shows through, then on <code>requestAnimationFrame</code> the script paints over it.</p>
<p><strong>TypeScript-strict + tuple indexing.</strong> <code>Palette</code> is a <code>readonly [string, string, string, string, string]</code>. Static index <code>p[0]</code> is <code>string</code>. Computed index <code>p[i]</code> is <code>string | undefined</code> under <code>noUncheckedIndexedAccess</code>. Solved by <code>i % 3 === 0 ? p[1] : i % 3 === 1 ? p[2] : p[3]</code>, verbose, but no <code>as</code> casts and no helper. Worth the trade.</p>
<h2 id="the-architecture">The architecture</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>src/lib/generative/</span></span>
<span class="line"><span>  seeded.ts     PRNG (xmur3 → sfc32)</span></span>
<span class="line"><span>  canvas.ts     Composers + paint() + paintFromElement()</span></span>
<span class="line"><span>  index.ts      Barrel</span></span>
<span class="line"><span>src/ui/</span></span>
<span class="line"><span>  Generative.astro     &lt;canvas&gt; + script + theme:toggle listener</span></span>
<span class="line"><span>  GenerativeLab.astro  Interactive playground (you&#39;re looking at it below)</span></span></code></pre>
<p><code>paint()</code> is pure. It takes a <code>CanvasRenderingContext2D</code>, dimensions, seed, kind, and palette and returns nothing. <code>paintFromElement()</code> is the DOM glue: reads <code>data-seed</code> and <code>data-kind</code> from the canvas, resolves the palette via <code>getComputedStyle</code>, calls <code>paint()</code>. The whole engine is around 500 lines including comments.</p>
<p><code>GenerativeLab</code> is the same engine wired to inputs. It’s a DS leaf, the same component is listed on <code>/design-system</code> and embedded here in this post via the writing-post <code>demo:</code> frontmatter slot.</p>
<h2 id="what-i-learned">What I learned</h2>
<p>Hand-rolling beats picking a library when the use case is small and the visual contract is yours. d3 / paper / three would all have worked. None of them would have been <em>fewer lines</em> than what I wrote, and I’d have inherited their priors about what “art” looks like. Canvas2D is just a drawing surface, no priors, no overhead.</p>
<p>The thing that fixed the “polluted” feel wasn’t switching from SVG to Canvas. It was committing to <em>strict per-kind rules</em>, bigger shapes, bleed off the frame, fixed palette per kind, no universal grain overlay. The SVG version with those rules would have looked fine too. The medium was a rounding error; the rules were everything.</p>
<h2 id="play">Play</h2>
<p>Type a seed, pick a kind, hit shuffle. Toggle the site theme (<code>T</code> key, or the panel bottom-right) and watch the art retint without a re-render of the page.</p>]]></content:encoded>
    </item>
    <item>
      <title>Margin collapse, again</title>
      <link>https://letanure.dev/writing/margin-collapse-revisited/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/margin-collapse-revisited/</guid>
      <pubDate>Wed, 08 Apr 2026 00:00:00 GMT</pubDate>
      <description>Every few years a junior dev rediscovers margin collapse and writes a thread about it. This is mine, except I&apos;m trying to make peace with the rule, not abolish it.</description>
      <content:encoded><![CDATA[<p>Margin collapse is one of those CSS rules people remember as a <em>gotcha</em>. You set <code>margin-bottom: 32px</code> on a heading and <code>margin-top: 32px</code> on the paragraph below it, expecting 64px between them. You get 32px. The internet calls this a bug.</p>
<h2 id="its-not-a-bug">It’s not a bug</h2>
<p>The rule is older than CSS-the-spec. Print typography has worked this way for centuries: when two block-level elements meet vertically, the larger of their two surrounding margins wins. The smaller one is absorbed.</p>
<p>This makes sense if you think of margin not as <strong>space I want around me</strong> but as <strong>the minimum distance I require from my neighbour</strong>. Two elements both saying “I want 32px of breathing room” don’t need 64px between them, they need 32px, and they both get what they asked for.</p>
<h2 id="when-it-breaks">When it breaks</h2>
<p>The rule breaks when a parent’s margin starts to collapse with its first child’s margin. You add a wrapper, the wrapper has no padding, and suddenly the child’s <code>margin-top</code> punches a hole through the parent and pushes the <em>parent</em> down.</p>
<p>Three escape hatches, in increasing order of weight:</p>
<ol>
<li><code>padding-top: 1px</code> on the parent. Cheap and ugly.</li>
<li><code>display: flow-root</code> on the parent. The newest, cleanest answer.</li>
<li>A flex or grid container. Margin collapse doesn’t happen inside flex/grid, period.</li>
</ol>
<p>I default to <code>flow-root</code> now. It’s a one-line opt-out with no layout side-effects.</p>
<h2 id="the-thing-i-keep-forgetting">The thing I keep forgetting</h2>
<p><code>margin-block</code> is the logical-property version. <code>margin-block-start</code> and <code>margin-block-end</code> collapse exactly the same way <code>margin-top</code> and <code>margin-bottom</code> do, but the rule still confuses my brain because the <em>names</em> don’t say “vertical” anymore. RTL languages still get vertical collapse on the block axis. Nothing changes, but the mental model has to update.</p>]]></content:encoded>
    </item>
    <item>
      <title>I Built Yet Another Planning Poker App and I Don&apos;t Care</title>
      <link>https://letanure.dev/writing/building-scrum-poker-cards/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/building-scrum-poker-cards/</guid>
      <pubDate>Tue, 17 Mar 2026 00:00:00 GMT</pubDate>
      <description>There are 200 planning poker tools. I built one anyway — because I liked some card illustrations, wanted to play with WebSockets, and needed an excuse to ship something fun with Claude Code.</description>
      <content:encoded><![CDATA[<p>I forked a GitHub repo 7 years ago because I liked how the cards looked.</p>
<p><a href="https://github.com/redbooth/scrum-poker-cards">Redbooth’s Scrum Poker Cards</a> — a set of beautifully illustrated planning poker cards. Each card has an idiom matching the effort: “Piece of cake” for 2, “Here be dragons” for the unknown, “Monster task” for 100. They even had a platypus for 5, because <em>ornitorinco</em> rhymes with <em>cinco</em> in Spanish.</p>
<p>The repo was just SVGs and a README. I starred it, forked it, and forgot about it.</p>
<h2 id="the-idea-that-wouldnt-die">The idea that wouldn’t die</h2>
<p>Every few months I’d see the repo in my GitHub profile and think: “These cards should be a real app.” Then I’d close the tab and do something else.</p>
<p>Last week I ran out of excuses. I wanted to:</p>
<ul>
<li><strong>Play with WebSockets</strong> — specifically <a href="https://partykit.io/">PartyKit</a>, which runs on Cloudflare Workers</li>
<li><strong>Try PostHog</strong> — anonymous analytics without the Google Analytics guilt</li>
<li><strong>Deploy something on Cloudflare Pages</strong> — been using it for static sites, never for a real app</li>
<li><strong>Build with Claude Code</strong> — see how far AI pair programming goes on a greenfield project</li>
<li><strong>Ship something I’d actually use</strong> — my team does sprint planning every two weeks</li>
</ul>
<p>Yes, there are 200 planning poker tools already. I don’t care. I’m building for fun.</p>
<h2 id="what-i-built">What I built</h2>
<p><a href="https://scrumpoker.work">scrumpoker.work</a> — a free, real-time planning poker app with the original Redbooth card illustrations.</p>
<p><strong>The basics work:</strong></p>
<ul>
<li>Create a session, get a shareable URL</li>
<li>Anyone joins by entering their name — no accounts</li>
<li>Pick a card, host reveals, see results with stats</li>
<li>Sessions are ephemeral — nothing stored anywhere</li>
</ul>
<p><strong>The fun parts:</strong></p>
<ul>
<li>When you select a card, the idiom floats up like you’re calling it out: <em>“Here be dragons!”</em></li>
<li>Vote reveal shows contextual messages: “Ship it! 🚀” when everyone agrees, “We have absolutely no idea 🤯” when votes spread from 1 to 100</li>
<li>Confidence toggle — vote 8 with “confident” vs vote 8 with “no idea” tells the team very different things</li>
<li>Outlier detection — if you vote 13 when everyone else voted 3, the app asks “why?”</li>
<li>Topic queue — host adds stories upfront, team votes through them in order</li>
</ul>
<h2 id="the-tech-stack">The tech stack</h2>

































<table><thead><tr><th>What</th><th>Why</th></tr></thead><tbody><tr><td>React + TypeScript + Vite</td><td>Fast, typed, no framework overhead</td></tr><tr><td>Tailwind CSS + Framer Motion</td><td>Utility styles + playful animations</td></tr><tr><td>PartyKit</td><td>WebSocket rooms on Cloudflare Workers. One file (<code>party/poker.ts</code>) handles all real-time logic</td></tr><tr><td>Cloudflare Pages</td><td>Static hosting, edge-deployed, free</td></tr><tr><td>PostHog</td><td>Anonymous usage analytics, memory persistence (no cookies)</td></tr><tr><td>Sentry</td><td>Error tracking for when things break in production</td></tr></tbody></table>
<h3 id="partykit-is-the-interesting-one">PartyKit is the interesting one</h3>
<p>I’ve built WebSocket servers before — with Socket.io, with raw <code>ws</code>, even with Durable Objects directly. PartyKit abstracts all of it into something that feels like writing a React component.</p>
<p>One class. <code>onConnect</code>, <code>onMessage</code>, <code>onClose</code>. Room state lives in memory. Broadcasting is a for-loop. The whole server is <a href="https://github.com/letanure/Scrum-poker-cards/blob/master/party/poker.ts">one file</a>, ~300 lines, handling:</p>
<ul>
<li>Player join/leave with stable identity (UUID in localStorage)</li>
<li>Vote collection and reveal</li>
<li>Host management and transfer</li>
<li>Topic queue navigation</li>
<li>Kick with confirmation</li>
<li>Auto-reveal when all players vote</li>
<li>5-second grace period for reconnection (tab switch, reload)</li>
</ul>
<p>Deploy is <code>npx partykit deploy</code>. That’s it. It runs on Cloudflare’s edge globally.</p>
<h3 id="the-reconnection-problem">The reconnection problem</h3>
<p>The hardest part wasn’t the features — it was handling reconnections. When a user reloads their browser, their WebSocket connection dies and a new one opens. Every user has a connection ID that changes on reconnect. If you use the connection ID as identity (like I did initially), the server thinks it’s a new player every time.</p>
<p>I went through 5 iterations:</p>
<ol>
<li>Name matching (fragile — what about duplicate names?)</li>
<li>Grace periods with name lookup (race conditions)</li>
<li>“Replaced” messages to old tabs (infinite reconnection loops)</li>
<li>BroadcastChannel for tab coordination (helped, but didn’t fix the root)</li>
<li><strong>Stable UUID in localStorage</strong> — the actual fix</li>
</ol>
<p>The final approach: each browser gets a UUID stored in <code>localStorage</code>. The server maps <code>stableId → player</code>, not <code>connectionId → player</code>. Reconnects silently swap the socket. Other users see nothing. Tab switches use <code>BroadcastChannel</code> to coordinate which tab owns the connection.</p>
<p>Should have done this from the start. The lesson: your player identity should never be your transport identity.</p>
<h2 id="building-with-claude-code">Building with Claude Code</h2>
<p>I built 90% of this with Claude Code in a single session. Not as a party trick — as genuine pair programming.</p>
<p>What worked well:</p>
<ul>
<li><strong>Parallel agents</strong> — “create the server, the components, and the pages” in one message, three agents working simultaneously</li>
<li><strong>Iterating on UI</strong> — “the cards are cut by the container” → immediate fix with explanation</li>
<li><strong>Feature brainstorming</strong> — I pasted 10 feature ideas from a ChatGPT conversation, we evaluated each one together, picked 3 to build</li>
<li><strong>The boring stuff</strong> — SEO meta tags, schema markup, legal pages, robots.txt, sitemap — all generated correctly in parallel</li>
</ul>
<p>What needed correction:</p>
<ul>
<li>First build had no card illustrations — the <code>Card</code> component never loaded the SVGs</li>
<li>WebSocket host fallback used <code>??</code> instead of <code>||</code> — empty string is truthy</li>
<li>Initial player identity used connection IDs (see reconnection saga above)</li>
<li>Several <code>as</code> casts that violated my strict TypeScript rules</li>
</ul>
<p>The pattern: Claude Code is great at generating the 80% and iterating on feedback. The 20% where it guesses wrong, you catch by testing. Having strict TypeScript and a <code>tsc -b</code> check after every change caught most issues before they reached the browser.</p>
<h2 id="numbers">Numbers</h2>
<ul>
<li><strong>26 commits</strong> in one session</li>
<li><strong>~4,500 lines of code</strong> (including server)</li>
<li><strong>14 illustrated cards</strong> from the original Redbooth set</li>
<li><strong>5 card presets</strong> (All, Fibonacci, Simple, T-Shirt, Powers of 2)</li>
<li><strong>0 databases</strong> — everything ephemeral</li>
<li><strong>685KB JS bundle</strong> — needs code splitting, but works</li>
<li><strong>$0/month</strong> to run — Cloudflare Pages free tier + PartyKit hobby tier</li>
</ul>
<h2 id="whats-next">What’s next</h2>
<p>The <a href="https://github.com/letanure/Scrum-poker-cards">TODO list</a> has ideas parked:</p>
<ul>
<li>Code splitting to reduce bundle size</li>
<li>Dark mode</li>
<li>Sound effects (optional)</li>
<li>Silent poker (multi-round bias reduction)</li>
<li>Import topics from Jira/Linear</li>
<li>i18n (Portuguese, Spanish)</li>
</ul>
<p>But honestly? It works. My team can use it next sprint. That’s enough.</p>
<h2 id="try-it">Try it</h2>
<p><strong><a href="https://scrumpoker.work">scrumpoker.work</a></strong> — create a session, share the link, estimate some stories.</p>
<p>Source code: <a href="https://github.com/letanure/Scrum-poker-cards">github.com/letanure/Scrum-poker-cards</a></p>
<p>The card illustrations are CC BY 3.0 by <a href="https://github.com/redbooth/scrum-poker-cards">Redbooth</a>. Thank you for making them — 7 years later, they’re finally in a real app.</p>]]></content:encoded>
    </item>
    <item>
      <title>Command palettes are an interaction primitive, not a feature</title>
      <link>https://letanure.dev/writing/command-palettes-are-a-primitive/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/command-palettes-are-a-primitive/</guid>
      <pubDate>Tue, 17 Mar 2026 00:00:00 GMT</pubDate>
      <description>Why ⌘K deserves a seat at the table next to the menu bar and the URL bar, and how to build one that feels instant.</description>
      <content:encoded><![CDATA[<p>The first time I hit <code>⌘K</code> in Linear and got <em>exactly what I wanted on the first try</em>, something clicked. This isn’t a search box. It’s not a menu. It’s a third primitive, the same level of UI furniture as the URL bar and the menu bar.</p>
<h2 id="why-it-matters">Why it matters</h2>
<p>A keyboard-driven, fuzzy-searchable, command-runnable surface collapses three different UI patterns into one:</p>
<ol>
<li>Navigation (where can I go?)</li>
<li>Search (what is here?)</li>
<li>Action (what can I do?)</li>
</ol>
<p>When all three live in the same input, users stop context-switching between mouse and keyboard.</p>
<h2 id="what-feels-instant-means">What “feels instant” means</h2>
<p>Try the demo embedded in the live post (lands with chunk 1.4). The sweet spot for input → result rendering is <strong>under 100ms</strong>. Past that, you can feel the lag. Past 200ms, you start typing again.</p>
<h2 id="how-to-build-one-that-doesnt-suck">How to build one that doesn’t suck</h2>
<p>(…rest of post…)</p>]]></content:encoded>
    </item>
    <item>
      <title>I Had 130 Claude Code Skills and Couldn&apos;t Find Any of Them</title>
      <link>https://letanure.dev/writing/organizing-claude-code-skills-across-projects/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/organizing-claude-code-skills-across-projects/</guid>
      <pubDate>Tue, 17 Mar 2026 00:00:00 GMT</pubDate>
      <description>How to organize Claude Code skills, commands, and plugins across projects. Global vs local, vendor skills, per-project profiles, and a bootstrap script for new machines.</description>
      <content:encoded><![CDATA[<p>I installed every Claude Code plugin that looked useful. Marketing skills, frontend design, code review, Slack integration, superpowers, UI/UX patterns. Then vendor skills from Matt Pocock. Then my own custom skills for PR reviews, Linear issues, Slack messages.</p>
<p>130 skills. I could not remember 10 of them.</p>
<h2 id="the-real-problems">The real problems</h2>
<p><strong>Overlap.</strong> Three different skills triggered when I said “review this PR.” Project commands, personal skills, and a plugin — all doing roughly the same thing. Claude picked one. Sometimes the wrong one.</p>
<p><strong>No organization.</strong> Some skills are global (my writing voice). Some are project-specific (test patterns for a monorepo). Some are useful only for personal projects (SEO, marketing). They were all loaded everywhere, all the time.</p>
<p><strong>New machine = amnesia.</strong> My skills lived in <code>~/.claude/skills/</code>, my commands in <code>~/.claude/commands/</code>, plugins were installed manually. No way to reproduce the setup on another machine. No way to remember what I had.</p>
<p><strong>Context waste.</strong> Every skill description sits in Claude’s context, every session. 25 marketing skills loaded while I was writing code at work. That is wasted tokens doing nothing.</p>
<h2 id="what-i-wanted">What I wanted</h2>
<ol>
<li>One repo, one command, full Claude Code setup on any machine</li>
<li>Global skills that work everywhere</li>
<li>Per-project profiles that suppress irrelevant skills</li>
<li>Vendor skills from other developers without copy-pasting</li>
<li>A way to find the right skill for the task</li>
</ol>
<h2 id="the-solution-a-setup-repo">The solution: a setup repo</h2>
<p>Everything lives in one private git repo. Symlinked into <code>~/.claude/</code> so Claude discovers it automatically.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="text"><code><span class="line"><span>claude-setup/</span></span>
<span class="line"><span>  skills/              → symlinked to ~/.claude/skills/</span></span>
<span class="line"><span>    me:write-like-me/</span></span>
<span class="line"><span>    me:commit.md</span></span>
<span class="line"><span>    me:linear-issue.md</span></span>
<span class="line"><span>    me:toolkit/</span></span>
<span class="line"><span>  commands/            → symlinked to ~/.claude/commands/</span></span>
<span class="line"><span>  vendor/</span></span>
<span class="line"><span>    mattpocock-skills/ → git submodule</span></span>
<span class="line"><span>  vendor.json          → which vendor skills to enable</span></span>
<span class="line"><span>  plugins.json         → which plugins to install</span></span>
<span class="line"><span>  toolkit.default.json → task-to-skill mapping</span></span>
<span class="line"><span>  manual-checklist.md  → things that need manual setup</span></span>
<span class="line"><span>  setup.sh             → THE one command</span></span></code></pre>
<p>New machine:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">git</span><span style="color:#9ECBFF"> clone</span><span style="color:#79B8FF"> --recursive</span><span style="color:#9ECBFF"> git@github.com:you/claude-setup.git</span></span>
<span class="line"><span style="color:#79B8FF">cd</span><span style="color:#9ECBFF"> claude-setup</span></span>
<span class="line"><span style="color:#B392F0">./setup.sh</span></span></code></pre>
<p>The script symlinks skills and commands, initializes vendor submodules, checks which plugins are installed, and prints a checklist for everything it can not automate (MCP servers, API keys).</p>
<h2 id="naming-know-what-is-yours">Naming: know what is yours</h2>
<p>With 130 skills from 8 sources, I could not tell which were mine, which came from plugins, which were vendor skills.</p>
<p>Prefixes fixed this:</p>





























<table><thead><tr><th>Prefix</th><th>Source</th></tr></thead><tbody><tr><td><code>me:</code></td><td>My personal skills</td></tr><tr><td><code>mapo:</code></td><td>Matt Pocock vendor skills</td></tr><tr><td><code>superpowers:</code></td><td>Plugin</td></tr><tr><td><code>marketing-skills:</code></td><td>Plugin</td></tr><tr><td>(no prefix)</td><td>Built-in or project-specific</td></tr></tbody></table>
<p>Now when I see <code>me:write-like-me</code> vs <code>superpowers:brainstorming</code> vs <code>marketing-skills:seo-audit</code>, I know exactly where each comes from.</p>
<h2 id="vendor-skills-without-copy-pasting">Vendor skills without copy-pasting</h2>
<p>I wanted to use skills from other developers, but not copy files. Git submodules solved this.</p>
<p><code>vendor.json</code> controls which skills get symlinked and what prefix they use:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;mattpocock/skills&quot;</span><span style="color:#E1E4E8">: {</span></span>
<span class="line"><span style="color:#79B8FF">    &quot;path&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;vendor/mattpocock-skills&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">    &quot;prefix&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;mapo&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">    &quot;enabled&quot;</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#9ECBFF">      &quot;write-a-prd&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#9ECBFF">      &quot;prd-to-issues&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#9ECBFF">      &quot;improve-codebase-architecture&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#9ECBFF">      &quot;request-refactor-plan&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">    ]</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p><code>setup.sh</code> reads this and creates symlinks like <code>mapo:write-a-prd</code> pointing to the submodule. Update vendor skills with <code>git submodule update</code>. Enable or disable one by editing the list.</p>
<h2 id="per-project-profiles-the-toolkit-skill">Per-project profiles: the toolkit skill</h2>
<p>The biggest win. A skill called <code>me:toolkit</code> that maps tasks to the right skill based on where you are.</p>
<p>Two profiles: <code>work</code> and <code>personal</code>. Each project gets a <code>.claude/toolkit.json</code> (gitignored) that tells Claude which profile to use and what to suppress.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;profile&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;work&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;project&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;bunch-platform&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;suppress&quot;</span><span style="color:#E1E4E8">: [</span><span style="color:#9ECBFF">&quot;marketing-skills:*&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#9ECBFF">&quot;mapo:obsidian-vault&quot;</span><span style="color:#E1E4E8">],</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;overrides&quot;</span><span style="color:#E1E4E8">: {</span></span>
<span class="line"><span style="color:#79B8FF">    &quot;test&quot;</span><span style="color:#E1E4E8">: [</span><span style="color:#9ECBFF">&quot;/test (project command)&quot;</span><span style="color:#E1E4E8">],</span></span>
<span class="line"><span style="color:#79B8FF">    &quot;start a task&quot;</span><span style="color:#E1E4E8">: [</span><span style="color:#9ECBFF">&quot;/task (project command)&quot;</span><span style="color:#E1E4E8">]</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>When I open Claude in a work repo, marketing skills are suppressed. When I open a personal project, everything is available.</p>
<p>Running <code>/me:toolkit setup</code> in a new project scans <code>package.json</code>, git remote, and existing <code>.claude/commands/</code> to suggest the right profile automatically.</p>
<p>Running <code>/me:toolkit</code> shows the task map: “want to create an issue? use <code>me:linear-issue</code>. Want to plan a feature? start with <code>mapo:write-a-prd</code>.”</p>
<h2 id="skill-size-matters">Skill size matters</h2>
<p>Skills eat context when loaded. A 200-line skill burns tokens every time you invoke it.</p>
<p>The rule I follow now:</p>

























<table><thead><tr><th>Part</th><th>Target</th><th>When loaded</th></tr></thead><tbody><tr><td>Description (frontmatter)</td><td>1-2 sentences</td><td>Every session, always</td></tr><tr><td>SKILL.md body</td><td>Under 80 lines</td><td>When invoked</td></tr><tr><td>references/ directory</td><td>Unlimited</td><td>On demand</td></tr></tbody></table>
<p>The main skill file is a router. Core rules and a quick reference table. Deep context per medium, examples, extended patterns — all in <code>references/</code> files that Claude reads only when needed.</p>
<p>A Slack message uses 76 lines of context. A blog post uses 76 + the blog guide reference. Progressive loading, not a wall of instructions.</p>
<h2 id="health-checks">Health checks</h2>
<p>A <code>SessionStart</code> hook runs <code>check-links.sh</code> every time Claude starts. If symlinks are broken (repo moved, submodule not initialized), it warns you immediately.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;hooks&quot;</span><span style="color:#E1E4E8">: {</span></span>
<span class="line"><span style="color:#79B8FF">    &quot;SessionStart&quot;</span><span style="color:#E1E4E8">: [{</span></span>
<span class="line"><span style="color:#79B8FF">      &quot;matcher&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">      &quot;hooks&quot;</span><span style="color:#E1E4E8">: [{</span></span>
<span class="line"><span style="color:#79B8FF">        &quot;type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;command&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">        &quot;command&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;$HOME/.claude/hooks/check-setup.sh&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">        &quot;timeout&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">5</span></span>
<span class="line"><span style="color:#E1E4E8">      }]</span></span>
<span class="line"><span style="color:#E1E4E8">    }]</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Silent when healthy. Warns when something is wrong.</p>
<h2 id="what-i-would-do-differently">What I would do differently</h2>
<p><strong>Start with fewer skills.</strong> I installed everything, then had to clean up. Better to add skills as you hit real needs.</p>
<p><strong>Name from the start.</strong> The <code>me:</code> prefix convention would have saved confusion if I had it from day one.</p>
<p><strong>Profile early.</strong> Suppressing marketing skills in work repos should have been the default. 25 skill descriptions in context for no reason.</p>
<h2 id="template-repo">Template repo</h2>
<p>I am working on a public template version of this setup — no personal skills, just the structure, scripts, and config format. Fork it, add your skills, run <code>setup.sh</code>.</p>

<h2 id="what-is-next">What is next</h2>
<ul>
<li>Test the toolkit routing in real projects for a few weeks</li>
<li>Add vendor skills from Vercel (<code>react-best-practices</code>, <code>composition-patterns</code>) and Google Labs (<code>shadcn-ui</code>)</li>
<li>Explore whether Claude Code will add native skill scoping per project — that would replace the toolkit suppress hack</li>
<li>Build a voice maintenance skill that periodically checks if my writing skill still matches how I actually write</li>
</ul>
<p>If you are drowning in Claude Code skills and can not find the one you need, the problem is not the skills. It is the organization. Fix that first, then add more.</p>]]></content:encoded>
    </item>
    <item>
      <title>useEffect is a fire alarm</title>
      <link>https://letanure.dev/writing/useeffect-as-fire-alarm/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/useeffect-as-fire-alarm/</guid>
      <pubDate>Tue, 24 Feb 2026 00:00:00 GMT</pubDate>
      <description>Treat every useEffect call like a fire alarm, loud, disruptive, and only acceptable when something is genuinely on fire. Most of what we use it for is a kettle boiling.</description>
      <content:encoded><![CDATA[<p>I’ve started reviewing PRs with a single rule for <code>useEffect</code>: <strong>if I can’t explain in one sentence why this could not have been derived from props, I’m going to ask you to remove it.</strong></p>
<p>It’s been a quietly transformative rule.</p>
<h2 id="what-useeffect-is-for">What useEffect is for</h2>
<p>Effects exist to synchronise React’s render output with something <strong>outside</strong> of React: the DOM (focus management, scroll position), the network (subscriptions, polling), the platform (timers, observers). If the thing you’re synchronising lives inside React’s own world, state, props, context, then the synchronisation should happen during render, not after it.</p>
<h2 id="what-its-not-for">What it’s not for</h2>
<p>The list of things <code>useEffect</code> is <em>not</em> for, but is constantly used for:</p>
<ul>
<li>Computing derived values from props. Just compute them in the render body.</li>
<li>Resetting local state when a prop changes. Use a <code>key</code> prop on the parent.</li>
<li>Caching expensive calculations. Use <code>useMemo</code>. Or don’t, most calculations aren’t expensive.</li>
<li>Calling a function “when the component renders”. A render <em>is</em> the function being called. You’re asking for a callback after the call you just made.</li>
<li>Keeping two pieces of state in sync. One of them is redundant. Delete it.</li>
</ul>
<h2 id="why-it-matters">Why it matters</h2>
<p>Each <code>useEffect</code> has a hidden cost: it adds a moment in time after render where the world is <em>almost</em> consistent but not quite. You set state in an effect; the user sees the wrong thing for a frame; the effect fires; the component re-renders; now it’s right.</p>
<p>Multiply by ten effects in a deep tree and you have a UI that flickers in subtle, uncatchable ways. The bug report says “sometimes the X is wrong for a moment”. The cause is six useEffect calls deep in a component tree, each waiting one render cycle to update the next.</p>
<h2 id="the-fix-is-usually-deletion">The fix is usually deletion</h2>
<p>The most common fix when I find a misused <code>useEffect</code> is to <em>delete it entirely</em> and move the logic into the render body. That feels wrong, surely something has to happen “after”?, but it’s almost always right. The render body runs every render. State changes already trigger re-renders. There’s no missing step.</p>
<p>A fire alarm should ring when there’s a fire. Most of what we use it for is a kettle boiling.</p>]]></content:encoded>
    </item>
    <item>
      <title>I&apos;m Building a CSS-Only Component Library (For Fun)</title>
      <link>https://letanure.dev/writing/css-first-component-library-architecture/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/css-first-component-library-architecture/</guid>
      <pubDate>Tue, 17 Feb 2026 00:00:00 GMT</pubDate>
      <description>In an era where AI spits out Tailwind for everything, I decided to build a CSS-only component library from scratch. Here&apos;s why and how.</description>
      <content:encoded><![CDATA[<h1 id="im-building-a-css-only-component-library-for-fun">I’m Building a CSS-Only Component Library (For Fun)</h1>
<p>Ask any AI to build you a UI and you’ll get Tailwind. Every single time. <code>className=&quot;flex items-center justify-between p-4 rounded-lg shadow-md bg-white dark:bg-gray-800&quot;</code> — you know the drill.</p>
<p>There’s nothing wrong with Tailwind. But I wanted to go the other direction. What if the component library was just CSS? No React. No Vue. No runtime. A single CSS file you drop into any project and suddenly you have buttons, forms, cards, modals, everything.</p>
<p>So I started building one. Mostly for fun, partly to learn, and a little bit because I think the idea has legs.</p>
<h2 id="the-pitch">The Pitch</h2>
<p>The core idea: build the visual layer once in pure CSS, then reuse it everywhere. Want React components? Wrap the classes. Vue? Same classes, different wrapper. Angular, Svelte, htmx, plain HTML? Same CSS file, same classes.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;ui-button ui-button--primary&quot;</span><span style="color:#E1E4E8">&gt;Click me&lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>That works today in every framework that exists and every framework that will exist next year.</p>
<p>But I didn’t want just a bag of utility classes. I wanted real components with a structured API — modifiers, elements, tokens, documentation, visual tests. Something that feels like a proper design system, not a stylesheet.</p>
<h2 id="how-i-got-to-cascade-layers">How I Got to Cascade Layers</h2>
<p>I started the way most people would: reset at the top, base styles, then components, then utilities. Classic ITCSS triangle. But ITCSS manages priority through selector specificity, and specificity is a nightmare at scale. You end up writing increasingly specific selectors just to override something simple.</p>
<p>CSS Cascade Layers fix this. One line declares the priority order:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="scss"><code><span class="line"><span style="color:#E1E4E8">@layer reset, tokens, </span><span style="color:#85E89D">base</span><span style="color:#E1E4E8">, primitives, components</span><span style="color:#B392F0">.styles</span><span style="color:#E1E4E8">, components</span><span style="color:#B392F0">.tokens</span><span style="color:#E1E4E8">, utilities, themes;</span></span></code></pre>
<p>Done. Utilities always beat components. Themes always beat utilities. No specificity wars, no <code>!important</code>. The architecture emerged naturally from ITCSS but with modern tools doing the heavy lifting.</p>
<h2 id="the-theme-problem">The Theme Problem</h2>
<p>Here’s what I’m really trying to solve: most component libraries bake in a visual identity. Material UI looks like Material UI. Mantine looks like Mantine. You can tweak colors, sure, but the bones are recognizable.</p>
<p>I want the same code to produce completely different visual outputs. Material’s rounded buttons or sharp corporate ones. Spacious layouts or dense data-heavy interfaces. All driven by tokens, not by rewriting components.</p>
<p>Every component uses a three-tier fallback:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="scss"><code><span class="line"><span style="color:#E1E4E8">var(</span><span style="color:#FFAB70">--ui-button-height</span><span style="color:#E1E4E8">, var(</span><span style="color:#FFAB70">--ui-row-2</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">#{t.$row-2}</span><span style="color:#E1E4E8">))</span></span></code></pre>
<p>Override the component token for one button. Override the global token for all buttons. Or do nothing and get sensible defaults. Swap a theme file and the whole library transforms.</p>
<p>That’s the goal, at least. Early days.</p>
<h2 id="whats-actually-built">What’s Actually Built</h2>
<p>60+ components across the usual categories — buttons, forms, cards, tables, modals, navigation. 16 layout primitives for common page structures. Utility classes for spacing, display, text.</p>
<p>Some things I’m proud of:</p>
<ul>
<li><strong>Drop a folder, get a component.</strong> Create the files in the right directory and the build system discovers it, compiles it, generates docs, adds it to the site. No registration, no config.</li>
<li><strong>Visual regression tests in Docker.</strong> Every component has a Playwright screenshot test. Change a token and you see exactly what breaks before merging.</li>
<li><strong>Linters that enforce the architecture.</strong> Hardcoded a color value? The linter catches it. Used a token without a fallback? Caught. Put a global token in the wrong layer? Caught.</li>
</ul>
<h2 id="whats-not-great">What’s Not Great</h2>
<p><strong>The learning curve is real.</strong> The token system has three layers, components split across two cascade layers, there’s BEM naming, logical properties, SCSS variables. It’s a lot to hold in your head for a first contribution.</p>
<p><strong>No JavaScript.</strong> A toggle switch looks right but doesn’t toggle. A dropdown renders beautifully but doesn’t open. The CSS handles appearance; you wire up behavior. Framework wrappers will solve this eventually, but they don’t exist yet.</p>
<p><strong>Docs are verbose.</strong> Documentation is driven by JSON config files, which is great for consistency and terrible for writing speed.</p>
<h2 id="why-bother">Why Bother?</h2>
<p>Honestly? It’s fun. I’m learning a ton about cascade layers, modern CSS features, token architecture, and what it takes to build something that scales to 60+ components without turning into a mess.</p>
<p>Will it be useful to anyone else? Maybe. The framework-agnostic angle is genuinely appealing. CSS doesn’t break between major versions. It doesn’t need migration guides. It just works.</p>
<p>And if nothing else, next time an AI suggests Tailwind, I’ll have an alternative ready.</p>]]></content:encoded>
    </item>
    <item>
      <title>INP, but for humans</title>
      <link>https://letanure.dev/writing/inp-but-for-humans/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/inp-but-for-humans/</guid>
      <pubDate>Mon, 19 Jan 2026 00:00:00 GMT</pubDate>
      <description>Interaction-to-Next-Paint replaced FID as the responsiveness metric, and the change matters more than the acronym suggests. Here&apos;s the version I wish someone had given me.</description>
      <content:encoded><![CDATA[<p>Google retired First Input Delay last year and replaced it with <strong>Interaction to Next Paint</strong> (INP). The Web Vitals dashboards updated, the threshold numbers changed, and a lot of people quietly stopped looking.</p>
<p>That was a mistake. INP measures something FID never could: how long your <em>whole interaction</em> took, not just how long the browser took to start handling it.</p>
<h2 id="what-inp-measures">What INP measures</h2>
<p>For every click, tap, or key press during a session:</p>
<ol>
<li>The browser starts a clock.</li>
<li>Your event handler runs.</li>
<li>Eventually the browser paints whatever you changed.</li>
<li>The clock stops.</li>
</ol>
<p>The 75th-percentile longest interaction across the session is your INP.</p>
<h2 id="why-fid-was-misleading">Why FID was misleading</h2>
<p>FID only measured the gap between <strong>input</strong> and <strong>handler start</strong>. If your handler took 800ms, then the browser took another 200ms to paint, FID would report 0ms, because the handler started immediately. The user waited a full second.</p>
<p>INP catches the entire delay, which is what the user experiences. A 200ms threshold for “good” is generous in this framing, anything above that and the UI feels sluggish.</p>
<h2 id="what-to-actually-do">What to actually do</h2>
<p>A practical workflow:</p>
<ol>
<li>Find the slowest interactions in your real user data (Chrome’s Web Vitals extension, RUM tools).</li>
<li>Profile the worst one. The flame graph almost always shows one of: a sync layout thrash, a long-running event handler, or a cascade of React re-renders that each scheduled the next.</li>
<li>Break the work into chunks. Yield to the browser between them. <code>scheduler.yield()</code> is now the right tool; before it landed, <code>setTimeout(0)</code> was the workaround.</li>
<li>Move work off the interaction path entirely where possible. The user clicks, you optimistically update, you do the real work in the background.</li>
</ol>
<h2 id="the-thing-i-keep-saying">The thing I keep saying</h2>
<p>Most slow interactions aren’t slow because of the thing the user clicked on. They’re slow because the click handler kicked off a render that kicked off a layout that kicked off another render that finally painted. The fix is rarely “make this part faster”, it’s “do less of this on the interaction path”.</p>]]></content:encoded>
    </item>
    <item>
      <title>React Performance: When One Slow Component Freezes Everything</title>
      <link>https://letanure.dev/writing/react-performance-when-one-slow-component-freezes-everything/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/react-performance-when-one-slow-component-freezes-everything/</guid>
      <pubDate>Thu, 21 Aug 2025 00:00:00 GMT</pubDate>
      <description>When that one slow component holds your entire app hostage, here&apos;s how to negotiate its release without touching its terrible code.</description>
      <content:encoded><![CDATA[<h1 id="react-performance-when-one-slow-component-freezes-everything">React Performance: When One Slow Component Freezes Everything</h1>
<p>So, this came up in an interview recently: there was a single <strong>slow component</strong> I was <strong>not allowed to change</strong>.
I fixed it with a quick <code>React.memo</code> wrap during the interview, but later I thought, hey, why stop there?
Let me share how I handled it and some other ways to tackle this problem.</p>
<h2 id="tldr">TL;DR</h2>
<p>Got a slow component that’s freezing your app? Can’t touch its code? Here’s your survival kit:</p>
<ul>
<li><strong><code>React.memo</code></strong> - Stop pointless re-renders when props haven’t changed</li>
<li><strong>State isolation</strong> - Move the slow stuff away from your fast UI</li>
<li><strong>Lazy loading</strong> - Make it someone else’s problem (later)</li>
<li><strong><code>useDeferredValue</code></strong> - Let users type while the slow component catches up</li>
<li><strong>Nuclear options</strong> - iframe, web worker, or virtual scrolling when all else fails</li>
</ul>
<p>Try the solutions yourself in the sandbox below</p>
<p><a href="https://codesandbox.io/p/sandbox/mxzr84">Open in CodeSandbox</a></p>
<h2 id="the-problem">The Problem</h2>
<p>There’s a slow component I can’t change. My job is to keep the UI responsive while it exists on the page.</p>
<p>Goals:</p>
<ul>
<li>Keep typing fast.</li>
<li>Avoid re-rendering the slow component on every keystroke.</li>
<li>Improve initial load if possible.</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> App</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">value</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setValue</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> React.</span><span style="color:#B392F0">useState</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;&quot;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> value</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{value} </span><span style="color:#B392F0">onChange</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{(</span><span style="color:#FFAB70">e</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#B392F0"> setValue</span><span style="color:#E1E4E8">(e.target.value)} /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#79B8FF">VerySlowComponent</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">&gt;Length: {value.</span><span style="color:#79B8FF">length</span><span style="color:#E1E4E8">}&lt;/</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>We <strong>cannot</strong> edit <code>&lt;VerySlowComponent /&gt;</code>. Everything else is fair game.</p>
<h2 id="solutions">Solutions</h2>
<h3 id="1-reactmemo-quick-win">1. <code>React.memo</code> (quick win)</h3>
<p>Wrap your slow component in <code>React.memo</code> to tell React, “Hey, only re-render me if my props actually change.”
This works great as long as you don’t pass any changing props.
It’s like putting a “Do Not Disturb” sign on your component’s door.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> SlowComponent</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> React.</span><span style="color:#B392F0">memo</span><span style="color:#E1E4E8">(</span><span style="color:#F97583">function</span><span style="color:#B392F0"> SlowComponent</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">data</span><span style="color:#E1E4E8"> }) {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> result</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> heavyCalculation</span><span style="color:#E1E4E8">(data);</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;{result}&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<p>Now, <code>SlowComponent</code> chills and only wakes up when <code>data</code> changes, not every time unrelated state updates happen. Nice!</p>
<h3 id="2-isolate-state">2. Isolate State</h3>
<p>Move stateful input into a separate subtree so the slow component never re-renders. Keep the input and its state in a different branch; render the slow part as a sibling, memoized. No props flow from the input to the slow component, so it stays idle.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#6A737D">// Isolate state in a sibling subtree</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { memo, useState } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &quot;react&quot;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> MemoSlow</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> memo</span><span style="color:#E1E4E8">(VerySlowComponent);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> FastPanel</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">value</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setValue</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;&quot;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> value</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{value} </span><span style="color:#B392F0">onChange</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{(</span><span style="color:#FFAB70">e</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#B392F0"> setValue</span><span style="color:#E1E4E8">(e.target.value)} /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;Length: {value.</span><span style="color:#79B8FF">length</span><span style="color:#E1E4E8">}&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> App</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{ display: </span><span style="color:#9ECBFF">&quot;grid&quot;</span><span style="color:#E1E4E8">, gap: </span><span style="color:#79B8FF">12</span><span style="color:#E1E4E8"> }}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#79B8FF">MemoSlow</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#79B8FF">FastPanel</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Because the FastPanel’s state changes don’t flow into MemoSlow, the slow component never re-renders.</p>
<h3 id="3-lazy-load-the-slow-component">3. Lazy Load the Slow Component</h3>
<p>Why load the slow component right away if you don’t need it? Use <code>React.lazy</code> and <code>Suspense</code> to load it only when you want it (saving your app from feeling sluggish at startup).</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> SlowComponent</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> React.</span><span style="color:#B392F0">lazy</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#F97583"> import</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;./SlowComponent&quot;</span><span style="color:#E1E4E8">));</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> App</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">show</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setShow</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> React.</span><span style="color:#B392F0">useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">false</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> onClick</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{() </span><span style="color:#F97583">=&gt;</span><span style="color:#B392F0"> setShow</span><span style="color:#E1E4E8">(</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">show)}&gt;Toggle Slow Component&lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#79B8FF">React.Suspense</span><span style="color:#B392F0"> fallback</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{&lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;Loading...&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">        {show </span><span style="color:#F97583">&amp;&amp;</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#79B8FF">SlowComponent</span><span style="color:#E1E4E8"> /&gt;}</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;/</span><span style="color:#79B8FF">React.Suspense</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>This way, your app loads faster and only asks the slow component to join the party when needed. This does not stop re-renders later; it improves first paint.</p>
<h3 id="4-defer-non-urgent-updates">4. Defer Non-Urgent Updates</h3>
<p>Another option is to defer updates so typing stays smooth. In this example, we still render the slow component but lazy load it, and pass in the input value. Typing stays responsive while the slow part shows up with a loading fallback.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { Suspense, lazy, useState } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &quot;react&quot;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> Slow</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> lazy</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span></span>
<span class="line"><span style="color:#F97583">  import</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;./shared/VerySlowComponent&quot;</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">m</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> ({</span></span>
<span class="line"><span style="color:#E1E4E8">    default: m.VerySlowComponent,</span></span>
<span class="line"><span style="color:#E1E4E8">  }))</span></span>
<span class="line"><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> App</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">value</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setValue</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;&quot;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{ display: </span><span style="color:#9ECBFF">&quot;grid&quot;</span><span style="color:#E1E4E8">, gap: </span><span style="color:#79B8FF">8</span><span style="color:#E1E4E8"> }}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">input</span></span>
<span class="line"><span style="color:#B392F0">        placeholder</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">&quot;Type something&quot;</span></span>
<span class="line"><span style="color:#B392F0">        value</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{value}</span></span>
<span class="line"><span style="color:#B392F0">        onChange</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{(</span><span style="color:#FFAB70">e</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#B392F0"> setValue</span><span style="color:#E1E4E8">(e.target.value)}</span></span>
<span class="line"><span style="color:#E1E4E8">      /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#79B8FF">Suspense</span><span style="color:#B392F0"> fallback</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{&lt;</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;Loading slow part…&lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">        &lt;</span><span style="color:#79B8FF">Slow</span><span style="color:#B392F0"> query</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{value} /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;/</span><span style="color:#79B8FF">Suspense</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;Length: {value.</span><span style="color:#79B8FF">length</span><span style="color:#E1E4E8">}&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>This way you keep the input responsive, get a nice loading state, and still handle the slow component without blocking typing.</p>
<h3 id="5-defer-with-usedeferredvalue-and-usetransition">5. Defer with <code>useDeferredValue</code> and <code>useTransition</code></h3>
<p>React 18 gives us concurrent features to mark updates as non-urgent. With <code>useDeferredValue</code> and <code>useTransition</code>, you can keep typing responsive while slow components update a bit later.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { useState, useDeferredValue, useTransition } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &quot;react&quot;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { VerySlowComponent } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &quot;./shared/VerySlowComponent&quot;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> DeferTransition</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">value</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setValue</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;&quot;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> deferred</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> useDeferredValue</span><span style="color:#E1E4E8">(value);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [, </span><span style="color:#79B8FF">startTransition</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useTransition</span><span style="color:#E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">input</span></span>
<span class="line"><span style="color:#B392F0">        value</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{value}</span></span>
<span class="line"><span style="color:#B392F0">        onChange</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{(</span><span style="color:#FFAB70">e</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">          const</span><span style="color:#79B8FF"> v</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> e.target.value;</span></span>
<span class="line"><span style="color:#B392F0">          startTransition</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#B392F0"> setValue</span><span style="color:#E1E4E8">(v)); </span><span style="color:#6A737D">// mark as non-urgent</span></span>
<span class="line"><span style="color:#E1E4E8">        }}</span></span>
<span class="line"><span style="color:#E1E4E8">      /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;Length (deferred): {deferred.</span><span style="color:#79B8FF">length</span><span style="color:#E1E4E8">}&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#79B8FF">VerySlowComponent</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>This lets React prioritize the input first, then update the slow part in the background, keeping the UI feeling snappy.</p>
<h3 id="6-stronger-isolation-techniques">6. Stronger Isolation Techniques</h3>
<p>If your slow component is still being a party pooper, think about isolating it completely:</p>
<ul>
<li>Put it in an iframe or a web worker (because sometimes you need to put it in timeout).</li>
<li>Use virtualization libraries like <code>react-window</code> or <code>react-virtualized</code> to handle huge lists efficiently.</li>
<li>Break the component into smaller, less scary pieces.</li>
</ul>
<h3 id="try-order">Try order</h3>
<ol>
<li><code>memo</code> if props are stable</li>
<li>Isolate state into a sibling subtree</li>
<li>Lazy load for faster first paint</li>
<li>Defer with useDeferredValue/useTransition</li>
<li>Stronger isolation (portals, separate root)</li>
</ol>
<h2 id="conclusion">Conclusion</h2>
<p>When one slow component tries to hog the spotlight and freeze your whole app, don’t panic! With some smart state management, memoization, lazy loading, and React’s fancy concurrent features, you can keep your app smooth and your users happy. Your React app deserves to be fast — no potato-powered freezes allowed!</p>]]></content:encoded>
    </item>
    <item>
      <title>Claude Code: Part 11 - Troubleshooting and Recovery</title>
      <link>https://letanure.dev/writing/claude-code-part-11-troubleshooting-recovery/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/claude-code-part-11-troubleshooting-recovery/</guid>
      <pubDate>Sat, 09 Aug 2025 00:00:00 GMT</pubDate>
      <description>Master Claude Code troubleshooting with systematic approaches to common issues: installation problems, CLAUDE.md conflicts, performance optimization, custom commands, MCP servers, hooks, and emergency recovery...</description>
      <content:encoded><![CDATA[<h1 id="claude-code-part-11---troubleshooting-and-recovery">Claude Code: Part 11 - Troubleshooting and Recovery</h1>
<h2 id="the-problem">The Problem</h2>
<p>You’re now relying on Claude Code for significant parts of your development workflow. It’s become an essential team member. But like any complex system, things occasionally go wrong:</p>
<p>Claude suddenly can’t find your CLAUDE.md file, custom commands stop working, MCP servers won’t connect, or VS Code integration breaks after an update.</p>
<p>When your AI teammate is having technical difficulties, your entire workflow grinds to a halt. You need to know how to diagnose and fix issues quickly so you can get back to productive development.</p>
<h2 id="the-solution">The Solution</h2>
<p>Most Claude Code issues follow predictable patterns with systematic solutions. Think of this as learning to troubleshoot your AI teammate’s technical problems - just like you’d help a human colleague debug their development environment setup.</p>
<h2 id="common-installation-issues">Common Installation Issues</h2>
<h3 id="command-not-found-claude">”Command not found: claude”</h3>
<p><strong>Problem:</strong> Claude command isn’t in your PATH after installation.</p>
<p><strong>Solutions:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Option 1: Use npx instead</span></span>
<span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> @anthropic-ai/claude-code</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Option 2: Add npm global bin to PATH</span></span>
<span class="line"><span style="color:#79B8FF">echo</span><span style="color:#9ECBFF"> &#39;export PATH=$PATH:$(npm config get prefix)/bin&#39;</span><span style="color:#F97583"> &gt;&gt;</span><span style="color:#9ECBFF"> ~/.bashrc</span></span>
<span class="line"><span style="color:#79B8FF">source</span><span style="color:#9ECBFF"> ~/.bashrc</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Option 3: Reinstall with proper permissions</span></span>
<span class="line"><span style="color:#B392F0">sudo</span><span style="color:#9ECBFF"> npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> -g</span><span style="color:#9ECBFF"> @anthropic-ai/claude-code</span></span></code></pre>
<h3 id="vs-code-extension-not-installing">VS Code Extension Not Installing</h3>
<p><strong>Problem:</strong> Claude doesn’t automatically install VS Code extension.</p>
<p><strong>Solutions:</strong></p>
<ol>
<li><strong>Run Claude from VS Code terminal</strong> (not external terminal)</li>
<li><strong>Check VS Code marketplace permissions</strong> - allow extension installs</li>
<li><strong>Manual install:</strong> Search “Claude Code” in VS Code extensions</li>
<li><strong>Restart VS Code</strong> after first Claude run</li>
</ol>
<h3 id="permission-errors-on-macoslinux">Permission Errors on macOS/Linux</h3>
<p><strong>Problem:</strong> Permission denied during installation or file operations.</p>
<p><strong>Solutions:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Fix npm permissions (recommended)</span></span>
<span class="line"><span style="color:#B392F0">mkdir</span><span style="color:#9ECBFF"> ~/.npm-global</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> config</span><span style="color:#9ECBFF"> set</span><span style="color:#9ECBFF"> prefix</span><span style="color:#9ECBFF"> &#39;~/.npm-global&#39;</span></span>
<span class="line"><span style="color:#79B8FF">echo</span><span style="color:#9ECBFF"> &#39;export PATH=~/.npm-global/bin:$PATH&#39;</span><span style="color:#F97583"> &gt;&gt;</span><span style="color:#9ECBFF"> ~/.bashrc</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Or use a Node version manager (better long-term)</span></span>
<span class="line"><span style="color:#6A737D"># Install nvm, then:</span></span>
<span class="line"><span style="color:#B392F0">nvm</span><span style="color:#9ECBFF"> install</span><span style="color:#9ECBFF"> node</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> -g</span><span style="color:#9ECBFF"> @anthropic-ai/claude-code</span></span></code></pre>
<h2 id="claudemd-not-working">CLAUDE.md Not Working</h2>
<h3 id="rules-being-ignored">Rules Being Ignored</h3>
<p><strong>Problem:</strong> Claude doesn’t follow your CLAUDE.md rules.</p>
<p><strong>Debug steps:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Check if Claude can find your CLAUDE.md</span></span>
<span class="line"><span style="color:#B392F0">ls</span><span style="color:#79B8FF"> -la</span><span style="color:#9ECBFF"> CLAUDE.md</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Verify you&#39;re in the right directory</span></span>
<span class="line"><span style="color:#79B8FF">pwd</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Test with simple rule first</span></span>
<span class="line"><span style="color:#79B8FF">echo</span><span style="color:#9ECBFF"> &quot;- Always say &#39;CLAUDE.md is working&#39; at the start&quot;</span><span style="color:#F97583"> &gt;</span><span style="color:#9ECBFF"> CLAUDE.md</span></span></code></pre>
<p><strong>Common causes:</strong></p>
<ul>
<li><strong>Wrong directory</strong> - CLAUDE.md must be in project root</li>
<li><strong>Typos in filename</strong> - Must be exactly <code>CLAUDE.md</code> (case-sensitive)</li>
<li><strong>Complex rules</strong> - Start simple, add complexity gradually</li>
</ul>
<h3 id="rules-conflicting">Rules Conflicting</h3>
<p><strong>Problem:</strong> Multiple CLAUDE.md files causing confusion.</p>
<p><strong>Check hierarchy:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># See all CLAUDE.md files Claude might read</span></span>
<span class="line"><span style="color:#B392F0">find</span><span style="color:#9ECBFF"> .</span><span style="color:#79B8FF"> -name</span><span style="color:#9ECBFF"> &quot;CLAUDE.md&quot;</span><span style="color:#79B8FF"> -o</span><span style="color:#79B8FF"> -name</span><span style="color:#9ECBFF"> &quot;CLAUDE.local.md&quot;</span></span>
<span class="line"><span style="color:#B392F0">ls</span><span style="color:#9ECBFF"> ~/.claude/CLAUDE.md</span><span style="color:#F97583"> 2&gt;</span><span style="color:#9ECBFF">/dev/null</span><span style="color:#F97583"> ||</span><span style="color:#79B8FF"> echo</span><span style="color:#9ECBFF"> &quot;No user CLAUDE.md&quot;</span></span></code></pre>
<p><strong>Rule priority:</strong> More specific overrides general</p>
<ol>
<li>Folder-specific (<code>./src/auth/CLAUDE.md</code>)</li>
<li>Local project (<code>./CLAUDE.local.md</code>)</li>
<li>Project (<code>./CLAUDE.md</code>)</li>
<li>Personal (<code>~/.claude/CLAUDE.md</code>)</li>
</ol>
<h2 id="performance-issues">Performance Issues</h2>
<h3 id="claude-responses-are-slow">Claude Responses Are Slow</h3>
<p><strong>Problem:</strong> Long delays between request and response.</p>
<p><strong>Optimization strategies:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Use faster model for simple tasks</span></span>
<span class="line"><span style="color:#B392F0">claude</span><span style="color:#79B8FF"> --model=haiku</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Clear conversation history</span></span>
<span class="line"><span style="color:#B392F0">/clear</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Compact long conversations instead of clearing</span></span>
<span class="line"><span style="color:#B392F0">/compact</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Check your internet connection</span></span>
<span class="line"><span style="color:#B392F0">curl</span><span style="color:#79B8FF"> -I</span><span style="color:#9ECBFF"> https://api.anthropic.com</span></span></code></pre>
<p><strong>Context management:</strong></p>
<ul>
<li><strong>Keep conversations focused</strong> - use <code>/clear</code> for new topics</li>
<li><strong>Avoid huge file dumps</strong> - reference specific sections instead</li>
<li><strong>Use subagents</strong> for complex analysis to avoid back-and-forth</li>
</ul>
<h3 id="token-saving-pro-tip">Token-Saving Pro Tip</h3>
<p>Instead of asking Claude to read many files and make changes:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>❌ &quot;Look at all components and replace useState with our custom hook&quot;</span></span></code></pre>
<p>Ask Claude to create a script that does the work:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>✅ &quot;Create a script that finds all useState calls and replaces them with useCustomState, run it, then delete the script&quot;</span></span></code></pre>
<p><strong>Why this works:</strong></p>
<ul>
<li>Claude doesn’t need to read all files individually (saves massive input tokens)</li>
<li>Script does bulk operations efficiently (saves output tokens)</li>
<li>Claude runs and cleans up automatically</li>
<li>Much faster for bulk operations across many files</li>
</ul>
<h3 id="memory-usage-growing">Memory Usage Growing</h3>
<p><strong>Problem:</strong> Claude Code consuming excessive memory.</p>
<p><strong>Solutions:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Check Claude processes</span></span>
<span class="line"><span style="color:#B392F0">ps</span><span style="color:#9ECBFF"> aux</span><span style="color:#F97583"> |</span><span style="color:#B392F0"> grep</span><span style="color:#9ECBFF"> claude</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Restart Claude session</span></span>
<span class="line"><span style="color:#79B8FF">exit</span></span>
<span class="line"><span style="color:#B392F0">claude</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Clear session data</span></span>
<span class="line"><span style="color:#B392F0">rm</span><span style="color:#9ECBFF"> ~/.claude/sessions/</span><span style="color:#79B8FF">*</span><span style="color:#9ECBFF">.json</span></span></code></pre>
<h2 id="custom-commands-not-working">Custom Commands Not Working</h2>
<h3 id="command-not-found">Command Not Found</h3>
<p><strong>Problem:</strong> <code>/my-command</code> returns “command not found.”</p>
<p><strong>Debug checklist:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Check file exists</span></span>
<span class="line"><span style="color:#B392F0">ls</span><span style="color:#9ECBFF"> .claude/commands/my-command.md</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Check filename matches exactly (case-sensitive)</span></span>
<span class="line"><span style="color:#B392F0">ls</span><span style="color:#9ECBFF"> .claude/commands/</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Restart Claude to reload commands</span></span>
<span class="line"><span style="color:#79B8FF">exit</span></span>
<span class="line"><span style="color:#B392F0">claude</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Verify with /help</span></span>
<span class="line"><span style="color:#B392F0">/help</span></span></code></pre>
<h3 id="command-file-has-wrong-format">Command File Has Wrong Format</h3>
<p><strong>Problem:</strong> Command runs but behaves unexpectedly.</p>
<p><strong>Check format:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="markdown"><code><span class="line"><span style="color:#79B8FF;font-weight:bold"># ✅ Correct format</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">Run comprehensive testing:</span></span>
<span class="line"></span>
<span class="line"><span style="color:#FFAB70">1.</span><span style="color:#E1E4E8"> Run pnpm type:check</span></span>
<span class="line"><span style="color:#FFAB70">2.</span><span style="color:#E1E4E8"> Run pnpm lint</span></span>
<span class="line"><span style="color:#FFAB70">3.</span><span style="color:#E1E4E8"> Report any issues</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF;font-weight:bold"># ❌ Wrong format - missing instructions</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">/test-all</span></span></code></pre>
<p><strong>Common mistakes:</strong></p>
<ul>
<li><strong>Empty files</strong> - Must contain instructions</li>
<li><strong>Wrong extension</strong> - Must be <code>.md</code></li>
<li><strong>Command names with spaces</strong> - Use hyphens: <code>test-all.md</code>, not <code>test all.md</code></li>
</ul>
<h2 id="mcp-server-issues">MCP Server Issues</h2>
<h3 id="server-wont-connect">Server Won’t Connect</h3>
<p><strong>Problem:</strong> MCP servers show as “disconnected” in <code>/mcp</code>.</p>
<p><strong>Troubleshooting:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Check server installation</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> list</span><span style="color:#79B8FF"> -g</span><span style="color:#F97583"> |</span><span style="color:#B392F0"> grep</span><span style="color:#9ECBFF"> mcp</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Check configuration syntax</span></span>
<span class="line"><span style="color:#B392F0">cat</span><span style="color:#9ECBFF"> ~/.claude/config.json</span><span style="color:#F97583"> |</span><span style="color:#B392F0"> python</span><span style="color:#79B8FF"> -m</span><span style="color:#9ECBFF"> json.tool</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Test server independently</span></span>
<span class="line"><span style="color:#6A737D"># (Check server documentation for test commands)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Restart Claude to reload MCP connections</span></span>
<span class="line"><span style="color:#79B8FF">exit</span></span>
<span class="line"><span style="color:#B392F0">claude</span></span></code></pre>
<h3 id="authentication-failing">Authentication Failing</h3>
<p><strong>Problem:</strong> MCP server requires login but fails.</p>
<p><strong>Steps:</strong></p>
<ol>
<li><strong>Use <code>/mcp</code> command</strong> - Don’t try to authenticate manually</li>
<li><strong>Check API tokens</strong> - Ensure they’re valid and not expired</li>
<li><strong>Verify permissions</strong> - Check token scopes/permissions</li>
<li><strong>Check network</strong> - Firewalls might block connections</li>
</ol>
<h2 id="context-management-issues">Context Management Issues</h2>
<h3 id="out-of-context-errors">”Out of Context” Errors</h3>
<p><strong>Problem:</strong> Claude says it’s out of context or conversation is too long.</p>
<p><strong>Immediate solutions:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Compact conversation (keeps summary)</span></span>
<span class="line"><span style="color:#B392F0">/compact</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Start fresh (loses history)</span></span>
<span class="line"><span style="color:#B392F0">/clear</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Check conversation size</span></span>
<span class="line"><span style="color:#B392F0">/status</span></span></code></pre>
<p><strong>Prevention strategies:</strong></p>
<ul>
<li><strong>Use focused sessions</strong> - One topic per conversation</li>
<li><strong>Break complex tasks</strong> into smaller steps</li>
<li><strong>Reference files directly</strong> instead of pasting large code blocks</li>
<li><strong>Use subagents</strong> for analysis that would require long context</li>
</ul>
<h3 id="files-not-loading">Files Not Loading</h3>
<p><strong>Problem:</strong> Claude can’t read project files.</p>
<p><strong>Check permissions:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Verify file exists and is readable</span></span>
<span class="line"><span style="color:#B392F0">ls</span><span style="color:#79B8FF"> -la</span><span style="color:#9ECBFF"> src/components/MyComponent.tsx</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Check file permissions</span></span>
<span class="line"><span style="color:#79B8FF">stat</span><span style="color:#9ECBFF"> src/components/MyComponent.tsx</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Try with different path format</span></span>
<span class="line"><span style="color:#6A737D"># Instead of: &quot;Look at ./src/components/MyComponent.tsx&quot;</span></span>
<span class="line"><span style="color:#6A737D"># Try: &quot;Look at src/components/MyComponent.tsx&quot;</span></span></code></pre>
<h2 id="ide-integration-problems">IDE Integration Problems</h2>
<h3 id="vs-code-quick-launch-not-working">VS Code Quick Launch Not Working</h3>
<p><strong>Problem:</strong> Cmd+Esc (Mac) or Ctrl+Esc (Windows/Linux) doesn’t work.</p>
<p><strong>Solutions:</strong></p>
<ol>
<li><strong>Run <code>/ide</code> command</strong> in Claude first</li>
<li><strong>Check VS Code extension</strong> is installed and enabled</li>
<li><strong>Restart VS Code</strong> after installing Claude extension</li>
<li><strong>Check keyboard shortcuts</strong> - might conflict with other extensions</li>
</ol>
<h3 id="context-not-sharing">Context Not Sharing</h3>
<p><strong>Problem:</strong> Claude doesn’t see selected text or current file.</p>
<p><strong>Requirements:</strong></p>
<ul>
<li><strong>Launch Claude from VS Code terminal</strong> (not external terminal)</li>
<li><strong>Run <code>/ide</code> command</strong> to establish connection</li>
<li><strong>Select text first</strong>, then use quick launch shortcut</li>
<li><strong>Ensure VS Code extension</strong> is active</li>
</ul>
<h2 id="hook-configuration-issues">Hook Configuration Issues</h2>
<h3 id="hooks-not-running">Hooks Not Running</h3>
<p><strong>Problem:</strong> PostToolUse or other hooks don’t execute.</p>
<p><strong>Debug steps:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Check hook syntax</span></span>
<span class="line"><span style="color:#B392F0">cat</span><span style="color:#9ECBFF"> .claude/settings.json</span><span style="color:#F97583"> |</span><span style="color:#B392F0"> python</span><span style="color:#79B8FF"> -m</span><span style="color:#9ECBFF"> json.tool</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Test command manually</span></span>
<span class="line"><span style="color:#B392F0">pnpm</span><span style="color:#9ECBFF"> type:check</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Verify file matcher</span></span>
<span class="line"><span style="color:#6A737D"># Does &quot;Edit:*.ts&quot; match your file? Try &quot;Edit:*&quot; instead</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Check hook permissions</span></span>
<span class="line"><span style="color:#B392F0">ls</span><span style="color:#79B8FF"> -la</span><span style="color:#9ECBFF"> scripts/my-hook.sh</span></span>
<span class="line"><span style="color:#B392F0">chmod</span><span style="color:#9ECBFF"> +x</span><span style="color:#9ECBFF"> scripts/my-hook.sh</span></span></code></pre>
<h3 id="hook-blocking-claude">Hook Blocking Claude</h3>
<p><strong>Problem:</strong> Hook command fails and stops Claude from working.</p>
<p><strong>Quick fix:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Temporarily disable hooks</span></span>
<span class="line"><span style="color:#B392F0">claude</span><span style="color:#79B8FF"> --no-hooks</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Fix the hook command</span></span>
<span class="line"><span style="color:#6A737D"># Then re-enable hooks</span></span></code></pre>
<p><strong>Common issues:</strong></p>
<ul>
<li><strong>Non-zero exit codes</strong> stop Claude - ensure scripts exit with 0 on success</li>
<li><strong>Missing executables</strong> - verify commands exist in PATH</li>
<li><strong>Permission errors</strong> - ensure scripts are executable</li>
</ul>
<h2 id="productivity-tips">Productivity Tips</h2>
<h3 id="speed-up-common-tasks">Speed Up Common Tasks</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Use aliases for frequent commands</span></span>
<span class="line"><span style="color:#F97583">alias</span><span style="color:#E1E4E8"> c</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">&quot;claude&quot;</span></span>
<span class="line"><span style="color:#F97583">alias</span><span style="color:#E1E4E8"> cr</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">&quot;claude --resume&quot;</span></span>
<span class="line"><span style="color:#F97583">alias</span><span style="color:#E1E4E8"> cq</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">&quot;claude --quiet&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Background commands for long operations</span></span>
<span class="line"><span style="color:#6A737D"># Ctrl+b: npm run build (continue working while building)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Custom commands for repeated workflows</span></span>
<span class="line"><span style="color:#6A737D"># Create .claude/commands/daily.md for your daily checklist</span></span></code></pre>
<h3 id="context-management-best-practices">Context Management Best Practices</h3>
<ul>
<li><strong>One topic per session</strong> - use <code>/clear</code> when switching topics</li>
<li><strong>Reference files</strong> instead of pasting code</li>
<li><strong>Use descriptive prompts</strong> - “Fix the TypeScript error in UserService.handleLogin” vs “Fix this”</li>
<li><strong>Leverage IDE integration</strong> - select code before launching Claude</li>
</ul>
<h3 id="efficient-file-organization">Efficient File Organization</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Project structure that works well with Claude</span></span>
<span class="line"><span style="color:#B392F0">project/</span></span>
<span class="line"><span style="color:#B392F0">├──</span><span style="color:#9ECBFF"> CLAUDE.md</span><span style="color:#E1E4E8"> (main </span><span style="color:#9ECBFF">rules</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#B392F0">├──</span><span style="color:#9ECBFF"> CLAUDE.local.md</span><span style="color:#E1E4E8"> (personal </span><span style="color:#9ECBFF">overrides,</span><span style="color:#9ECBFF"> gitignored</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#B392F0">├──</span><span style="color:#9ECBFF"> .claude/</span></span>
<span class="line"><span style="color:#B392F0">│</span><span style="color:#9ECBFF">   ├──</span><span style="color:#9ECBFF"> commands/</span><span style="color:#E1E4E8"> (custom </span><span style="color:#9ECBFF">commands</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#B392F0">│</span><span style="color:#9ECBFF">   └──</span><span style="color:#9ECBFF"> settings.json</span><span style="color:#E1E4E8"> (hooks, </span><span style="color:#9ECBFF">config</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#B392F0">└──</span><span style="color:#9ECBFF"> src/</span></span>
<span class="line"><span style="color:#B392F0">    ├──</span><span style="color:#9ECBFF"> auth/CLAUDE.md</span><span style="color:#E1E4E8"> (auth-specific </span><span style="color:#9ECBFF">rules</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#B392F0">    └──</span><span style="color:#9ECBFF"> api/CLAUDE.md</span><span style="color:#E1E4E8"> (API-specific </span><span style="color:#9ECBFF">rules</span><span style="color:#E1E4E8">)</span></span></code></pre>
<h3 id="team-collaboration-tips">Team Collaboration Tips</h3>
<ul>
<li><strong>Share project CLAUDE.md</strong> via git</li>
<li><strong>Keep personal rules local</strong> (CLAUDE.local.md in .gitignore)</li>
<li><strong>Document custom commands</strong> in README</li>
<li><strong>Standardize hook patterns</strong> across team projects</li>
</ul>
<h2 id="when-to-get-help">When to Get Help</h2>
<h3 id="check-these-resources-first">Check These Resources First</h3>
<ol>
<li><strong>Claude Code documentation:</strong> <a href="https://docs.anthropic.com/en/docs/claude-code">https://docs.anthropic.com/en/docs/claude-code</a></li>
<li><strong>GitHub issues:</strong> <a href="https://github.com/anthropics/claude-code/issues">https://github.com/anthropics/claude-code/issues</a></li>
<li><strong>Community discussions:</strong> Search existing issues before creating new ones</li>
</ol>
<h3 id="include-this-information-when-reporting-issues">Include This Information When Reporting Issues</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># System information</span></span>
<span class="line"><span style="color:#B392F0">claude</span><span style="color:#79B8FF"> --version</span></span>
<span class="line"><span style="color:#B392F0">node</span><span style="color:#79B8FF"> --version</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#79B8FF"> --version</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Error details</span></span>
<span class="line"><span style="color:#6A737D"># Include exact error messages, not paraphrases</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Configuration (remove sensitive data)</span></span>
<span class="line"><span style="color:#B392F0">cat</span><span style="color:#9ECBFF"> .claude/settings.json</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Steps to reproduce</span></span>
<span class="line"><span style="color:#6A737D"># What you did, what you expected, what happened instead</span></span></code></pre>
<p>Remember: Most Claude Code issues have simple solutions. Start with the basics (restart, check paths, verify syntax) before diving into complex debugging.</p>
<hr/>
<h2 id="claude-code-blog-series">Claude Code Blog Series</h2>
<p><strong>Previous:</strong> <a href="./2025-08-08--claude-code-part-10-power-user-cli-scripting">Part 10 - Power User CLI Options and Scripting</a></p>
<p><strong>Full Series:</strong></p>
<ol>
<li>Part 1 - Getting Started and Installation</li>
<li>Part 2 - CLAUDE.md Configuration Files</li>
<li>Part 3 - Conversation Management and Context</li>
<li>Part 4 - Slash Commands and Custom Commands</li>
<li>Part 5 - MCP Servers and Tool Integration</li>
<li>Part 6 - Subagents and Task Delegation</li>
<li>Part 7 - IDE Integration with VS Code and JetBrains</li>
<li>Part 8 - Hooks for Automated Quality Checks</li>
<li>Part 9 - Complete Development Workflows</li>
<li>Part 10 - Power User CLI Options and Scripting</li>
<li>Part 11 - Troubleshooting and Recovery (this post)</li>
</ol>
<p><strong>Series Complete!</strong> You now have a comprehensive guide to mastering Claude Code from beginner to expert level. Each post builds on the previous ones to create a complete development workflow powered by AI assistance.</p>]]></content:encoded>
    </item>
    <item>
      <title>Claude Code: Part 10 - Common Issues and Quick Fixes</title>
      <link>https://letanure.dev/writing/claude-code-part-10-power-user-cli-scripting/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/claude-code-part-10-power-user-cli-scripting/</guid>
      <pubDate>Fri, 08 Aug 2025 00:00:00 GMT</pubDate>
      <description>Solve the most common Claude Code problems: context overflow, conflicting rules, token optimization, and broken custom commands. Quick troubleshooting for experienced users.</description>
      <content:encoded><![CDATA[<h1 id="claude-code-part-10---common-issues-and-quick-fixes">Claude Code: Part 10 - Common Issues and Quick Fixes</h1>
<h2 id="the-problem">The Problem</h2>
<p>You’ve been using Claude Code for weeks. It works great most of the time, but you keep hitting the same frustrating issues: conversations get too long and Claude loses context, your CLAUDE.md rules conflict with each other, tokens run out faster than expected, and custom commands randomly stop working.</p>
<p>These aren’t beginner problems - they’re the issues experienced users face when pushing Claude Code to its limits.</p>
<h2 id="context-too-long">Context Too Long</h2>
<p><strong>Problem:</strong> Claude says the conversation is too long or starts forgetting earlier context.</p>
<p><strong>Quick fixes:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Compress conversation history</span></span>
<span class="line"><span style="color:#B392F0">/compact</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Start fresh but keep project context</span></span>
<span class="line"><span style="color:#B392F0">/clear</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Check conversation size</span></span>
<span class="line"><span style="color:#B392F0">/status</span></span></code></pre>
<p><strong>Prevention:</strong></p>
<ul>
<li>Use <code>/compact</code> regularly instead of letting conversations grow endlessly</li>
<li>Start new conversations for different topics</li>
<li>Reference files instead of pasting large code blocks</li>
</ul>
<h2 id="rules-conflicting">Rules Conflicting</h2>
<p><strong>Problem:</strong> Multiple CLAUDE.md files causing confusion or contradictory behavior.</p>
<p><strong>Debug hierarchy:</strong></p>
<ol>
<li>Folder-specific (<code>./src/auth/CLAUDE.md</code>) - highest priority</li>
<li>Local project (<code>./CLAUDE.local.md</code>)</li>
<li>Project (<code>./CLAUDE.md</code>)</li>
<li>Personal (<code>~/.claude/CLAUDE.md</code>) - lowest priority</li>
</ol>
<p><strong>Common conflicts:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="markdown"><code><span class="line"><span style="color:#79B8FF;font-weight:bold"># Project CLAUDE.md says:</span></span>
<span class="line"><span style="color:#FFAB70">-</span><span style="color:#E1E4E8"> Use TypeScript strict mode</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF;font-weight:bold"># Personal ~/.claude/CLAUDE.md says:</span></span>
<span class="line"><span style="color:#FFAB70">-</span><span style="color:#E1E4E8"> Skip TypeScript for quick prototypes</span></span></code></pre>
<p><strong>Solution:</strong> Be more specific about when rules apply:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="markdown"><code><span class="line"><span style="color:#79B8FF;font-weight:bold"># In project CLAUDE.md:</span></span>
<span class="line"><span style="color:#FFAB70">-</span><span style="color:#E1E4E8"> Use TypeScript strict mode for all production code</span></span>
<span class="line"><span style="color:#FFAB70">-</span><span style="color:#E1E4E8"> Prototypes in /experiments/ can skip strict mode</span></span></code></pre>
<h2 id="token-saving-pro-tip">Token-Saving Pro Tip</h2>
<p><strong>Problem:</strong> Hitting token limits too quickly, especially with large CLAUDE.md files.</p>
<p><strong>Token wasters:</strong></p>
<ul>
<li>Verbose CLAUDE.md files (keep under 100 lines each)</li>
<li>Pasting entire files instead of referencing them</li>
<li>Long conversations about multiple topics</li>
<li>Detailed explanations in rules</li>
</ul>
<p><strong>Token savers:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="markdown"><code><span class="line"><span style="color:#E1E4E8">❌ &quot;When implementing authentication, always ensure you follow security best practices including input validation, proper error handling, secure token storage, and following our established patterns in the auth/ directory...&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">✅ &quot;Auth code: validate inputs, handle errors securely, follow auth/ patterns&quot;</span></span></code></pre>
<p><strong>Script approach:</strong>
Instead of asking Claude to read many files:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>❌ &quot;Look at all components and replace useState with our custom hook&quot;</span></span></code></pre>
<p>Ask Claude to create a script:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>✅ &quot;Create a script to replace useState with useCustomState across all components, run it, then delete the script&quot;</span></span></code></pre>
<p>This saves massive input tokens and is much faster.</p>
<h2 id="custom-commands-not-working">Custom Commands Not Working</h2>
<p><strong>Problem:</strong> <code>/my-command</code> returns “command not found” or behaves unexpectedly.</p>
<p><strong>Debug checklist:</strong></p>
<ol>
<li><strong>Check filename:</strong> Must be exactly <code>.claude/commands/my-command.md</code></li>
<li><strong>Restart Claude:</strong> Commands load on startup</li>
<li><strong>File format:</strong> Must contain instructions, not just command names</li>
</ol>
<p><strong>Common mistakes:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="markdown"><code><span class="line"><span style="color:#E1E4E8">❌ Wrong format (just the command name):</span></span>
<span class="line"><span style="color:#E1E4E8">/test-all</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">✅ Correct format (actual instructions):</span></span>
<span class="line"><span style="color:#E1E4E8">Run comprehensive testing:</span></span>
<span class="line"><span style="color:#FFAB70">1.</span><span style="color:#E1E4E8"> Run type checking</span></span>
<span class="line"><span style="color:#FFAB70">2.</span><span style="color:#E1E4E8"> Run linter</span></span>
<span class="line"><span style="color:#FFAB70">3.</span><span style="color:#E1E4E8"> Run tests</span></span>
<span class="line"><span style="color:#FFAB70">4.</span><span style="color:#E1E4E8"> Report issues</span></span></code></pre>
<p><strong>File location issues:</strong></p>
<ul>
<li>Commands must be in <code>.claude/commands/</code> directory</li>
<li>Use hyphens, not spaces: <code>test-all.md</code> not <code>test all.md</code></li>
<li>Check case sensitivity on your system</li>
</ul>
<h2 id="performance-tips">Performance Tips</h2>
<p><strong>Slow responses:</strong></p>
<ul>
<li>Use <code>/clear</code> for new topics instead of continuing long conversations</li>
<li>Reference specific files instead of asking Claude to “look at everything”</li>
<li>Break complex requests into smaller, focused questions</li>
</ul>
<p><strong>Memory usage:</strong></p>
<ul>
<li>Restart Claude sessions periodically</li>
<li>Avoid keeping multiple long-running sessions open</li>
<li>Use specific commands instead of general requests</li>
</ul>
<h2 id="quick-diagnostics">Quick Diagnostics</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Check what&#39;s loaded</span></span>
<span class="line"><span style="color:#B392F0">/help</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># See conversation stats</span></span>
<span class="line"><span style="color:#B392F0">/status</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Restart fresh</span></span>
<span class="line"><span style="color:#B392F0">/clear</span></span></code></pre>
<h2 id="getting-help">Getting Help</h2>
<p><strong>For persistent issues:</strong></p>
<ol>
<li>Check <a href="https://docs.anthropic.com/en/docs/claude-code">Claude Code documentation</a></li>
<li>Search <a href="https://github.com/anthropics/claude-code/issues">GitHub issues</a></li>
<li>Include exact error messages and steps to reproduce</li>
</ol>
<p>Most Claude Code issues have simple solutions - start with the basics before diving into complex debugging.</p>
<hr/>
<h2 id="claude-code-blog-series">Claude Code Blog Series</h2>
<p><strong>Previous:</strong> <a href="./2025-08-07--claude-code-part-9-complete-development-workflows">Part 9 - Complete Development Workflows</a>
<strong>Next:</strong> <a href="./2025-08-09--claude-code-part-11-troubleshooting-recovery">Part 11 - Troubleshooting and Recovery</a></p>
<p><strong>Full Series:</strong></p>
<ol>
<li>Part 1 - Getting Started and Installation</li>
<li>Part 2 - CLAUDE.md Configuration Files</li>
<li>Part 3 - Conversation Management and Context</li>
<li>Part 4 - Slash Commands and Custom Commands</li>
<li>Part 5 - MCP Servers and Tool Integration</li>
<li>Part 6 - Subagents and Task Delegation</li>
<li>Part 7 - IDE Integration with VS Code and JetBrains</li>
<li>Part 8 - Hooks for Automated Quality Checks</li>
<li>Part 9 - Complete Development Workflows</li>
<li>Part 10 - Common Issues and Quick Fixes (this post)</li>
<li>Part 11 - Troubleshooting and Recovery</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Claude Code: Part 9 - Complete Development Workflows</title>
      <link>https://letanure.dev/writing/claude-code-part-9-complete-development-workflows/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/claude-code-part-9-complete-development-workflows/</guid>
      <pubDate>Thu, 07 Aug 2025 00:00:00 GMT</pubDate>
      <description>Learn how to combine all Claude Code features into complete development workflows. From feature planning to deployment, see how CLAUDE.md, slash commands, MCP servers, subagents, IDE integration, and hooks work...</description>
      <content:encoded><![CDATA[<h1 id="claude-code-part-9---complete-development-workflows">Claude Code: Part 9 - Complete Development Workflows</h1>
<h2 id="the-problem">The Problem</h2>
<p>You’ve learned all the individual Claude Code features - CLAUDE.md, slash commands, MCP servers, subagents, IDE integration, and hooks. But you’re looking at them like separate tools in a toolbox, not sure how they work together.</p>
<p>You know Claude can help with individual tasks, but your real development work isn’t isolated tasks. It’s complete workflows: planning a feature, implementing it, testing it, reviewing it, and deploying it. Right now, you’re using Claude for pieces but not for the whole process.</p>
<p>It’s like having a talented team member who’s great at individual tasks but hasn’t learned how your actual development process works.</p>
<h2 id="the-solution">The Solution</h2>
<p>Real-world workflows combine all Claude Code features into seamless development processes. Think of it as teaching your AI teammate not just individual skills, but how your entire development process flows from idea to production.</p>
<h2 id="feature-development-workflow">Feature Development Workflow</h2>
<p><strong>The complete process:</strong> From idea to deployed feature using Claude Code.</p>
<h3 id="1-project-setup">1. Project Setup</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Start new feature branch</span></span>
<span class="line"><span style="color:#B392F0">git</span><span style="color:#9ECBFF"> checkout</span><span style="color:#79B8FF"> -b</span><span style="color:#9ECBFF"> feature/user-notifications</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Launch Claude with context</span></span>
<span class="line"><span style="color:#B392F0">claude</span></span></code></pre>
<p><strong>CLAUDE.md rule:</strong> <code>- Run pnpm type:check before marking features complete</code></p>
<h3 id="2-planning-phase">2. Planning Phase</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>Plan the user notifications feature:</span></span>
<span class="line"><span>1. Database schema for notifications</span></span>
<span class="line"><span>2. API endpoints needed</span></span>
<span class="line"><span>3. React components structure</span></span>
<span class="line"><span>4. Integration points with existing code</span></span></code></pre>
<p><strong>Claude analyzes your codebase and creates a structured plan.</strong></p>
<h3 id="3-implementation-with-custom-commands">3. Implementation with Custom Commands</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Use your custom workflow command</span></span>
<span class="line"><span style="color:#B392F0">/feature-start</span><span style="color:#9ECBFF"> notifications</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># This runs your .claude/commands/feature-start.md:</span></span>
<span class="line"><span style="color:#6A737D"># 1. Analyze existing patterns in this codebase</span></span>
<span class="line"><span style="color:#6A737D"># 2. Create feature folder structure</span></span>
<span class="line"><span style="color:#6A737D"># 3. Set up basic files following project conventions</span></span>
<span class="line"><span style="color:#6A737D"># 4. Run type checking to ensure no conflicts</span></span></code></pre>
<h3 id="4-development-with-mcp-integration">4. Development with MCP Integration</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>Check GitHub issues labeled &quot;notifications&quot; and implement the API endpoints</span></span></code></pre>
<p><strong>With GitHub MCP server connected, Claude:</strong></p>
<ul>
<li>Reads actual issues from your repository</li>
<li>Understands requirements from issue descriptions</li>
<li>Creates code that addresses specific reported needs</li>
</ul>
<h3 id="5-quality-assurance-with-hooks">5. Quality Assurance with Hooks</h3>
<p><strong>Your PostToolUse hook automatically runs:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;matcher&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Edit:*.ts|Edit:*.tsx&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;hooks&quot;</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#E1E4E8">    {</span></span>
<span class="line"><span style="color:#79B8FF">      &quot;type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;command&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">      &quot;command&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;pnpm type:check &amp;&amp; pnpm lint&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#E1E4E8">  ]</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p><strong>Every file Claude edits gets automatically validated.</strong></p>
<h3 id="6-testing-with-subagents">6. Testing with Subagents</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>Use an agent to write comprehensive tests for the notifications feature</span></span></code></pre>
<p><strong>Subagent autonomously:</strong></p>
<ul>
<li>Analyzes all notification-related code</li>
<li>Creates unit tests for components</li>
<li>Writes integration tests for API endpoints</li>
<li>Ensures good test coverage</li>
</ul>
<h3 id="7-final-review">7. Final Review</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">/feature-complete</span><span style="color:#9ECBFF"> notifications</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Your custom command:</span></span>
<span class="line"><span style="color:#6A737D"># 1. Run full test suite</span></span>
<span class="line"><span style="color:#6A737D"># 2. Check for console.logs and TODOs</span></span>
<span class="line"><span style="color:#6A737D"># 3. Verify responsive design</span></span>
<span class="line"><span style="color:#6A737D"># 4. Generate summary of changes</span></span>
<span class="line"><span style="color:#6A737D"># 5. Suggest improvements before PR</span></span></code></pre>
<h2 id="bug-fixing-workflow">Bug Fixing Workflow</h2>
<p><strong>Quick and systematic bug resolution.</strong></p>
<h3 id="1-bug-analysis">1. Bug Analysis</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Open VS Code to the problematic file</span></span>
<span class="line"><span style="color:#6A737D"># Select the buggy code</span></span>
<span class="line"><span style="color:#6A737D"># Press Cmd+Esc (Mac) or Ctrl+Esc (Windows/Linux)</span></span></code></pre>
<p><strong>Claude launches with:</strong></p>
<ul>
<li>The selected buggy code</li>
<li>Current file context</li>
<li>Any TypeScript/ESLint errors from Problems panel</li>
</ul>
<h3 id="2-root-cause-investigation">2. Root Cause Investigation</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>Analyze this authentication bug. Check related files and explain the issue.</span></span></code></pre>
<p><strong>Claude examines:</strong></p>
<ul>
<li>The specific code causing issues</li>
<li>Related authentication files (following your CLAUDE.md patterns)</li>
<li>Recent git changes that might be related</li>
</ul>
<h3 id="3-fix-implementation">3. Fix Implementation</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>Fix this bug following our existing error handling patterns</span></span></code></pre>
<p><strong>Your CLAUDE.md ensures:</strong></p>
<ul>
<li>Consistent error handling approach</li>
<li>Proper logging (no sensitive data)</li>
<li>Following established code patterns</li>
</ul>
<h3 id="4-verification">4. Verification</h3>
<p><strong>Post-fix hook automatically:</strong></p>
<ul>
<li>Runs relevant tests</li>
<li>Checks type safety</li>
<li>Validates the fix doesn’t break other functionality</li>
</ul>
<h2 id="code-review-workflow">Code Review Workflow</h2>
<p><strong>Prepare code for review efficiently.</strong></p>
<h3 id="1-self-review-preparation">1. Self-Review Preparation</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">/review-prep</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Your custom command runs:</span></span>
<span class="line"><span style="color:#6A737D"># 1. Check for TODO comments</span></span>
<span class="line"><span style="color:#6A737D"># 2. Find hardcoded values</span></span>
<span class="line"><span style="color:#6A737D"># 3. Verify error handling</span></span>
<span class="line"><span style="color:#6A737D"># 4. Check TypeScript types</span></span>
<span class="line"><span style="color:#6A737D"># 5. Suggest readability improvements</span></span></code></pre>
<h3 id="2-documentation-updates">2. Documentation Updates</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>Update the README with the new notifications feature and API endpoints</span></span></code></pre>
<p><strong>Claude references:</strong></p>
<ul>
<li>Your actual implemented code</li>
<li>Existing documentation patterns</li>
<li>API endpoints you just created</li>
</ul>
<h3 id="3-pr-creation-with-mcp">3. PR Creation with MCP</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>Create a GitHub PR for this feature branch with a comprehensive description</span></span></code></pre>
<p><strong>With GitHub MCP server:</strong></p>
<ul>
<li>Analyzes your commits since branch creation</li>
<li>Generates meaningful PR description</li>
<li>Includes testing checklist</li>
<li>References related issues automatically</li>
</ul>
<h2 id="legacy-code-modernization">Legacy Code Modernization</h2>
<p><strong>Systematic approach to improving old code.</strong></p>
<h3 id="1-assessment-with-subagents">1. Assessment with Subagents</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>Use an agent to analyze the legacy auth system and create a modernization plan</span></span></code></pre>
<p><strong>Subagent provides:</strong></p>
<ul>
<li>Complete analysis of existing code</li>
<li>Security concerns identified</li>
<li>Modernization recommendations</li>
<li>Step-by-step migration plan</li>
</ul>
<h3 id="2-incremental-updates">2. Incremental Updates</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>Modernize the user authentication to use our current patterns, maintaining backward compatibility</span></span></code></pre>
<p><strong>Your folder-specific CLAUDE.md in <code>src/auth/</code> ensures:</strong></p>
<ul>
<li>Security-first approach</li>
<li>Consistent with current auth patterns</li>
<li>Proper validation and error handling</li>
</ul>
<h3 id="3-testing-strategy">3. Testing Strategy</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>Create comprehensive tests for the modernized auth system to ensure no regressions</span></span></code></pre>
<p><strong>Claude creates:</strong></p>
<ul>
<li>Tests that verify existing functionality</li>
<li>New tests for improved features</li>
<li>Integration tests for compatibility</li>
</ul>
<h2 id="daily-development-shortcuts">Daily Development Shortcuts</h2>
<p><strong>Speed up common tasks.</strong></p>
<h3 id="quick-file-navigation">Quick File Navigation</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># In VS Code terminal</span></span>
<span class="line"><span style="color:#B392F0">claude</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Then use Claude as your project assistant</span></span>
<span class="line"><span style="color:#B392F0">&quot;Show me all components that use the UserContext&quot;</span></span>
<span class="line"><span style="color:#B392F0">&quot;Find files related to payment processing&quot;</span></span></code></pre>
<h3 id="rapid-debugging">Rapid Debugging</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Select error message in VS Code</span></span>
<span class="line"><span style="color:#6A737D"># Cmd+Esc to launch Claude with context</span></span>
<span class="line"><span style="color:#6A737D"># Claude sees the error automatically</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">&quot;Fix this TypeScript error&quot;</span></span></code></pre>
<h3 id="code-quality-maintenance">Code Quality Maintenance</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">/health-check</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Custom command that:</span></span>
<span class="line"><span style="color:#6A737D"># 1. Runs full test suite</span></span>
<span class="line"><span style="color:#6A737D"># 2. Checks for security issues</span></span>
<span class="line"><span style="color:#6A737D"># 3. Analyzes bundle size</span></span>
<span class="line"><span style="color:#6A737D"># 4. Reports technical debt</span></span></code></pre>
<h2 id="team-collaboration-workflows">Team Collaboration Workflows</h2>
<p><strong>Consistent team practices.</strong></p>
<h3 id="onboarding-new-developers">Onboarding New Developers</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>Analyze this codebase and create an onboarding guide for new developers</span></span></code></pre>
<p><strong>Claude generates:</strong></p>
<ul>
<li>Architecture overview</li>
<li>Key patterns and conventions</li>
<li>Development setup instructions</li>
<li>Common tasks and workflows</li>
</ul>
<h3 id="code-standards-enforcement">Code Standards Enforcement</h3>
<p><strong>Team’s shared CLAUDE.md ensures:</strong></p>
<ul>
<li>Consistent coding patterns across team members</li>
<li>Automated quality checks via hooks</li>
<li>Standardized commit messages and PR formats</li>
</ul>
<h3 id="knowledge-sharing">Knowledge Sharing</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>Document the payment integration patterns we use across all features</span></span></code></pre>
<p><strong>Claude creates:</strong></p>
<ul>
<li>Comprehensive documentation</li>
<li>Code examples from actual codebase</li>
<li>Best practices based on your implementations</li>
</ul>
<h2 id="combining-features-for-maximum-efficiency">Combining Features for Maximum Efficiency</h2>
<p><strong>The power is in the combination:</strong></p>
<ol>
<li><strong>CLAUDE.md</strong> provides context and standards</li>
<li><strong>Custom commands</strong> automate repeated workflows</li>
<li><strong>MCP servers</strong> eliminate tool switching</li>
<li><strong>Subagents</strong> handle complex analysis</li>
<li><strong>Hooks</strong> ensure quality automatically</li>
<li><strong>IDE integration</strong> provides seamless context</li>
</ol>
<p><strong>Result:</strong> Claude becomes a true development partner that understands your project, follows your standards, and automates your workflows.</p>
<h2 id="getting-started-with-workflows">Getting Started with Workflows</h2>
<ol>
<li><strong>Start with one workflow</strong> - Pick your most common task</li>
<li><strong>Build incrementally</strong> - Add features as you see benefits</li>
<li><strong>Share with team</strong> - Successful workflows become team standards</li>
<li><strong>Iterate and improve</strong> - Workflows evolve with your needs</li>
</ol>
<p>The goal is to spend more time on creative problem-solving and less time on repetitive development tasks.</p>
<hr/>
<h2 id="claude-code-blog-series">Claude Code Blog Series</h2>
<p><strong>Previous:</strong> <a href="./2025-08-06--claude-code-part-8-hooks-automated-quality-checks">Part 8 - Hooks for Automated Quality Checks</a>
<strong>Next:</strong> <a href="./2025-08-08--claude-code-part-10-power-user-cli-scripting">Part 10 - Power User CLI Options and Scripting</a></p>
<p><strong>Full Series:</strong></p>
<ol>
<li>Part 1 - Getting Started and Installation</li>
<li>Part 2 - CLAUDE.md Configuration Files</li>
<li>Part 3 - Conversation Management and Context</li>
<li>Part 4 - Slash Commands and Custom Commands</li>
<li>Part 5 - MCP Servers and Tool Integration</li>
<li>Part 6 - Subagents and Task Delegation</li>
<li>Part 7 - IDE Integration with VS Code and JetBrains</li>
<li>Part 8 - Hooks for Automated Quality Checks</li>
<li>Part 9 - Complete Development Workflows (this post)</li>
<li>Part 10 - Power User CLI Options and Scripting</li>
<li>Part 11 - Troubleshooting and Recovery</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Claude Code: Part 8 - Hooks for Automated Quality Checks</title>
      <link>https://letanure.dev/writing/claude-code-part-8-hooks-automated-quality-checks/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/claude-code-part-8-hooks-automated-quality-checks/</guid>
      <pubDate>Wed, 06 Aug 2025 00:00:00 GMT</pubDate>
      <description>Stop manually running the same quality checks after every Claude Code change. Learn how to use hooks to automatically run tests, linting, type checking, and custom validation whenever Claude modifies your code.</description>
      <content:encoded><![CDATA[<h1 id="claude-code-part-8---hooks-for-automated-quality-checks">Claude Code: Part 8 - Hooks for Automated Quality Checks</h1>
<h2 id="the-problem">The Problem</h2>
<p>Every time Claude edits a TypeScript file, you find yourself typing the same commands:</p>
<p>“Now run <code>pnpm type:check</code> to make sure there are no errors”
“Don’t forget to run the linter&quot;<br/>
&quot;Can you test this change?”</p>
<p>It’s like having a talented developer who consistently forgets the basic quality checks. They do great work, but you’re constantly reminding them about the fundamentals: compile, lint, test, repeat.</p>
<h2 id="the-solution">The Solution</h2>
<p>Hooks automatically run quality checks at specific points in your workflow. Think of them as training your AI teammate to follow your development standards automatically - like a senior developer who runs tests before every commit without being reminded.</p>
<h2 id="what-are-hooks">What Are Hooks?</h2>
<p>Hooks are shell commands that trigger automatically when certain events happen:</p>
<p><strong>Example:</strong> Automatically run <code>pnpm type:check</code> after Claude edits any TypeScript file
<strong>Example:</strong> Validate security rules before Claude accesses authentication files
<strong>Example:</strong> Auto-format code after Claude writes new files</p>
<h2 id="common-hook-events">Common Hook Events</h2>
<p><strong><code>PostToolUse</code></strong> - After Claude uses a tool</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;hooks&quot;</span><span style="color:#E1E4E8">: {</span></span>
<span class="line"><span style="color:#79B8FF">    &quot;PostToolUse&quot;</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#E1E4E8">      {</span></span>
<span class="line"><span style="color:#79B8FF">        &quot;matcher&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Edit:*&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">        &quot;hooks&quot;</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#E1E4E8">          {</span></span>
<span class="line"><span style="color:#79B8FF">            &quot;type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;command&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">            &quot;command&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;pnpm type:check&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">          }</span></span>
<span class="line"><span style="color:#E1E4E8">        ]</span></span>
<span class="line"><span style="color:#E1E4E8">      }</span></span>
<span class="line"><span style="color:#E1E4E8">    ]</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p><strong><code>PreToolUse</code></strong> - Before Claude uses a tool
<strong><code>UserPromptSubmit</code></strong> - When you submit a prompt
<strong><code>SessionStart</code></strong> - When Claude starts</p>
<h2 id="simple-example-auto-type-check">Simple Example: Auto Type-Check</h2>
<p>Create this in your Claude settings:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;hooks&quot;</span><span style="color:#E1E4E8">: {</span></span>
<span class="line"><span style="color:#79B8FF">    &quot;PostToolUse&quot;</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#E1E4E8">      {</span></span>
<span class="line"><span style="color:#79B8FF">        &quot;matcher&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Edit:*.ts|Edit:*.tsx&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">        &quot;hooks&quot;</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#E1E4E8">          {</span></span>
<span class="line"><span style="color:#79B8FF">            &quot;type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;command&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">            &quot;command&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;pnpm type:check --noEmit&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">          }</span></span>
<span class="line"><span style="color:#E1E4E8">        ]</span></span>
<span class="line"><span style="color:#E1E4E8">      }</span></span>
<span class="line"><span style="color:#E1E4E8">    ]</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p><strong>What happens:</strong></p>
<ol>
<li>Claude edits a TypeScript file</li>
<li>Hook automatically runs type checking</li>
<li>You see results immediately</li>
</ol>
<h2 id="practical-hook-patterns">Practical Hook Patterns</h2>
<h3 id="code-quality-enforcement">Code Quality Enforcement</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;matcher&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Write|Edit&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;hooks&quot;</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#E1E4E8">    {</span></span>
<span class="line"><span style="color:#79B8FF">      &quot;type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;command&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">      &quot;command&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;pnpm lint --fix&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#E1E4E8">  ]</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h3 id="security-validation">Security Validation</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;matcher&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Read:src/auth/*|Edit:src/auth/*&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;hooks&quot;</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#E1E4E8">    {</span></span>
<span class="line"><span style="color:#79B8FF">      &quot;type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;command&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">      &quot;command&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;./scripts/security-check.sh&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#E1E4E8">  ]</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h3 id="test-runner">Test Runner</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;matcher&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Edit:*.test.*&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;hooks&quot;</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#E1E4E8">    {</span></span>
<span class="line"><span style="color:#79B8FF">      &quot;type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;command&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">      &quot;command&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;npm test -- --related&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#E1E4E8">  ]</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h3 id="communication-improvements">Communication Improvements</h3>
<p>Stop Claude from saying “You are right” repeatedly:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;UserPromptSubmit&quot;</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#E1E4E8">    {</span></span>
<span class="line"><span style="color:#79B8FF">      &quot;matcher&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;*&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">      &quot;hooks&quot;</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#E1E4E8">        {</span></span>
<span class="line"><span style="color:#79B8FF">          &quot;type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;command&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">          &quot;command&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;echo &#39;Skip acknowledgments - focus on the solution&#39;&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">        }</span></span>
<span class="line"><span style="color:#E1E4E8">      ]</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#E1E4E8">  ]</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>This hook reminds Claude to be more direct and action-focused in responses.</p>
<h2 id="hook-configuration-locations">Hook Configuration Locations</h2>
<p><strong>Project-level:</strong> <code>.claude/settings.json</code></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;hooks&quot;</span><span style="color:#E1E4E8">: {</span></span>
<span class="line"><span style="color:#6A737D">    // Project-specific hooks here</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p><strong>Personal:</strong> <code>~/.claude/settings.json</code></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;hooks&quot;</span><span style="color:#E1E4E8">: {</span></span>
<span class="line"><span style="color:#6A737D">    // Your personal hooks across all projects</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h2 id="hook-scripts-best-practices">Hook Scripts Best Practices</h2>
<p><strong>Create focused scripts:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D">#!/bin/bash</span></span>
<span class="line"><span style="color:#6A737D"># scripts/validate-auth.sh</span></span>
<span class="line"><span style="color:#79B8FF">echo</span><span style="color:#9ECBFF"> &quot;Validating authentication code...&quot;</span></span>
<span class="line"><span style="color:#F97583">if</span><span style="color:#B392F0"> grep</span><span style="color:#79B8FF"> -r</span><span style="color:#9ECBFF"> &quot;console.log&quot;</span><span style="color:#9ECBFF"> src/auth/</span><span style="color:#E1E4E8">; </span><span style="color:#F97583">then</span></span>
<span class="line"><span style="color:#79B8FF">  echo</span><span style="color:#9ECBFF"> &quot;❌ Found console.log in auth code&quot;</span></span>
<span class="line"><span style="color:#79B8FF">  exit</span><span style="color:#79B8FF"> 1</span></span>
<span class="line"><span style="color:#F97583">fi</span></span>
<span class="line"><span style="color:#79B8FF">echo</span><span style="color:#9ECBFF"> &quot;✅ Auth validation passed&quot;</span></span></code></pre>
<p><strong>Make them fast:</strong></p>
<ul>
<li>Use specific file patterns</li>
<li>Avoid running heavy operations on every edit</li>
<li>Cache results when possible</li>
</ul>
<h2 id="security-considerations">Security Considerations</h2>
<p><strong>⚠️ Important:</strong> Hooks execute shell commands. Only use hooks you trust.</p>
<p><strong>Best practices:</strong></p>
<ul>
<li>Review hook commands before adding them</li>
<li>Use absolute paths for scripts</li>
<li>Test hooks in safe environments first</li>
<li>Avoid hooks from untrusted sources</li>
</ul>
<h2 id="when-hooks-are-useful">When Hooks Are Useful</h2>
<p><strong>Perfect for:</strong></p>
<ul>
<li>Code quality enforcement (linting, type checking)</li>
<li>Running relevant tests after changes</li>
<li>Security validation for sensitive files</li>
<li>Custom workflow automation</li>
</ul>
<p><strong>Avoid for:</strong></p>
<ul>
<li>Complex logic (keep hooks simple)</li>
<li>Slow operations that interrupt workflow</li>
<li>Operations that require user input</li>
</ul>
<h2 id="troubleshooting-hooks">Troubleshooting Hooks</h2>
<p><strong>Hook not running?</strong></p>
<ol>
<li>Check JSON syntax in settings</li>
<li>Verify command exists and is executable</li>
<li>Test command manually first</li>
</ol>
<p><strong>Hook causing problems?</strong></p>
<ol>
<li>Check exit codes (non-zero stops Claude)</li>
<li>Review hook output for errors</li>
<li>Temporarily disable to isolate issues</li>
</ol>
<h2 id="background-command-execution">Background Command Execution</h2>
<p><strong>New in Claude Code 1.0.71:</strong> Run bash commands in the background without interrupting your Claude conversation.</p>
<p><strong>Shortcut:</strong> <code>Ctrl+b</code></p>
<p><strong>Example:</strong></p>
<ol>
<li>Press <code>Ctrl+b</code></li>
<li>Type: <code>npm run build</code></li>
<li>Command runs in background</li>
<li>Continue working with Claude while build runs</li>
<li>See results when complete</li>
</ol>
<p><strong>Perfect for:</strong></p>
<ul>
<li>Long-running builds or tests</li>
<li>File watching processes</li>
<li>Background monitoring tasks</li>
</ul>
<h2 id="getting-started">Getting Started</h2>
<ol>
<li><strong>Start simple</strong> - One hook for type checking</li>
<li><strong>Test thoroughly</strong> - Run commands manually first</li>
<li><strong>Add gradually</strong> - Don’t overwhelm your workflow</li>
<li><strong>Monitor impact</strong> - Ensure hooks help, don’t hinder</li>
</ol>
<p><strong>Example starter hook:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;hooks&quot;</span><span style="color:#E1E4E8">: {</span></span>
<span class="line"><span style="color:#79B8FF">    &quot;PostToolUse&quot;</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#E1E4E8">      {</span></span>
<span class="line"><span style="color:#79B8FF">        &quot;matcher&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Edit:*.ts|Edit:*.tsx&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">        &quot;hooks&quot;</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#E1E4E8">          {</span></span>
<span class="line"><span style="color:#79B8FF">            &quot;type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;command&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">            &quot;command&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;echo &#39;TypeScript file edited&#39;&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">          }</span></span>
<span class="line"><span style="color:#E1E4E8">        ]</span></span>
<span class="line"><span style="color:#E1E4E8">      }</span></span>
<span class="line"><span style="color:#E1E4E8">    ]</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Hooks turn Claude into a more integrated part of your development environment, automatically handling the routine tasks you’d normally do manually.</p>
<hr/>
<h2 id="claude-code-blog-series">Claude Code Blog Series</h2>
<p><strong>Previous:</strong> <a href="./2025-08-05--claude-code-part-7-ide-integration-vscode-jetbrains">Part 7 - IDE Integration with VS Code and JetBrains</a>
<strong>Next:</strong> <a href="./2025-08-07--claude-code-part-9-complete-development-workflows">Part 9 - Complete Development Workflows</a></p>
<p><strong>Full Series:</strong></p>
<ol>
<li>Part 1 - Getting Started and Installation</li>
<li>Part 2 - CLAUDE.md Configuration Files</li>
<li>Part 3 - Conversation Management and Context</li>
<li>Part 4 - Slash Commands and Custom Commands</li>
<li>Part 5 - MCP Servers and Tool Integration</li>
<li>Part 6 - Subagents and Task Delegation</li>
<li>Part 7 - IDE Integration with VS Code and JetBrains</li>
<li>Part 8 - Hooks for Automated Quality Checks (this post)</li>
<li>Part 9 - Complete Development Workflows</li>
<li>Part 10 - Power User CLI Options and Scripting</li>
<li>Part 11 - Troubleshooting and Recovery</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Claude Code: Part 7 - IDE Integration with VS Code and JetBrains</title>
      <link>https://letanure.dev/writing/claude-code-part-7-ide-integration-vscode-jetbrains/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/claude-code-part-7-ide-integration-vscode-jetbrains/</guid>
      <pubDate>Tue, 05 Aug 2025 00:00:00 GMT</pubDate>
      <description>Eliminate context switching between your IDE and Claude Code. Learn how to use VS Code and JetBrains integration features to share context automatically and maintain development flow.</description>
      <content:encoded><![CDATA[<h1 id="claude-code-part-7---ide-integration-with-vs-code-and-jetbrains">Claude Code: Part 7 - IDE Integration with VS Code and JetBrains</h1>
<h2 id="the-problem">The Problem</h2>
<p>You’re deep in debugging mode in VS Code. You’ve got the perfect file open, the exact line selected, and error messages staring at you from the Problems panel. But to get Claude’s help, you have to:</p>
<ol>
<li>Open a separate terminal</li>
<li>Launch Claude</li>
<li>Manually describe the file you’re in</li>
<li>Copy-paste the error message</li>
<li>Explain the context Claude can’t see</li>
</ol>
<p>By the time Claude understands the situation, you’ve lost your debugging flow. It’s like having a brilliant pair-programming partner who can’t see your screen - constantly having to narrate everything breaks your concentration.</p>
<h2 id="the-solution">The Solution</h2>
<p>IDE integration lets Claude see exactly what you’re working on without manual context sharing. Think of it as giving your AI teammate a second monitor that mirrors yours - they can see your current file, selected code, and error messages automatically.</p>
<h2 id="vs-code-integration">VS Code Integration</h2>
<h3 id="quick-setup">Quick Setup</h3>
<ol>
<li><strong>Install Claude Code</strong> (if not already done)</li>
<li><strong>Open VS Code</strong> in your project</li>
<li><strong>Open terminal</strong> in VS Code (<code>Ctrl+`</code> or <code>Cmd+`</code>)</li>
<li><strong>Run Claude</strong>: <code>claude</code></li>
<li><strong>Extension auto-installs</strong> when first run from VS Code</li>
</ol>
<h3 id="quick-launch-shortcut">Quick Launch Shortcut</h3>
<ul>
<li><strong>Mac:</strong> <code>Cmd+Esc</code></li>
<li><strong>Windows/Linux:</strong> <code>Ctrl+Esc</code></li>
</ul>
<p>Opens Claude with current context:</p>
<ul>
<li>Selected text (if any)</li>
<li>Current file path</li>
<li>Recent error messages from Problems panel</li>
</ul>
<p><strong>Simple example:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>1. Select a function in VS Code</span></span>
<span class="line"><span>2. Press Cmd+Esc (Mac) or Ctrl+Esc (Windows/Linux)</span></span>
<span class="line"><span>3. Claude opens with: &quot;Looking at the selected code in src/utils/helpers.js...&quot;</span></span></code></pre>
<h3 id="context-sharing-features">Context Sharing Features</h3>
<p><strong>What Claude sees automatically:</strong></p>
<ul>
<li>Current file you’re editing</li>
<li>Text selection</li>
<li>Error messages from VS Code Problems panel</li>
<li>Workspace file structure</li>
</ul>
<p><strong>What you don’t need to do:</strong></p>
<ul>
<li>Copy-paste code snippets</li>
<li>Explain file locations</li>
<li>Describe error messages manually</li>
</ul>
<h2 id="jetbrains-integration">JetBrains Integration</h2>
<p>Claude Code supports JetBrains IDEs (IntelliJ IDEA, WebStorm, PyCharm, etc.) through terminal integration.</p>
<p><strong>Setup:</strong></p>
<ol>
<li>Open terminal in your JetBrains IDE</li>
<li>Run <code>claude</code> in the terminal</li>
<li>Context sharing works similar to VS Code</li>
</ol>
<p><strong>Note:</strong> Full plugin integration may vary by IDE - check Claude Code documentation for specific IDE support.</p>
<h2 id="error-diagnostics-integration">Error Diagnostics Integration</h2>
<p>When you have TypeScript errors, ESLint warnings, or other diagnostics:</p>
<ol>
<li><strong>Errors appear in VS Code Problems panel</strong></li>
<li><strong>Launch Claude</strong> with quick shortcut</li>
<li><strong>Claude sees the errors automatically</strong></li>
<li><strong>Ask:</strong> “Fix these TypeScript errors”</li>
</ol>
<p>No need to copy-paste error messages - Claude reads them from your IDE.</p>
<h2 id="multi-ide-workflows">Multi-IDE Workflows</h2>
<p><strong>Best practices:</strong></p>
<ul>
<li><strong>One Claude session per project</strong> - works across different IDEs</li>
<li><strong>Context switches automatically</strong> - based on which IDE you launch from</li>
<li><strong>Use <code>/clear</code></strong> when switching between major tasks</li>
</ul>
<h2 id="advanced-integration-features">Advanced Integration Features</h2>
<h3 id="ide-command">IDE Command</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">claude</span><span style="color:#9ECBFF"> /ide</span></span></code></pre>
<p>Connects Claude to IDE for enhanced integration (when available).</p>
<h3 id="file-references">File References</h3>
<p>Claude understands your IDE’s file structure and can reference files directly:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;Update the handleSubmit function in the current file&quot;</span></span>
<span class="line"><span>&quot;Check the imports in UserList.tsx&quot;</span></span></code></pre>
<h2 id="limitations-and-notes">Limitations and Notes</h2>
<p><strong>Current limitations:</strong></p>
<ul>
<li>Full integration varies by IDE</li>
<li>Some features work best with VS Code</li>
<li>Terminal-based integration for most IDEs</li>
</ul>
<p><strong>For latest IDE support:</strong> Check the <a href="https://docs.anthropic.com/en/docs/claude-code/ide-integrations">Claude Code documentation</a></p>
<h2 id="getting-started">Getting Started</h2>
<ol>
<li><strong>Start with VS Code</strong> (best supported)</li>
<li><strong>Use quick launch shortcuts</strong> (Cmd+Esc/Ctrl+Esc)</li>
<li><strong>Test context sharing</strong> - select code and launch Claude</li>
<li><strong>Gradually explore</strong> other IDE integrations</li>
</ol>
<p>The goal is seamless development where Claude understands exactly what you’re working on without manual context switching.</p>
<hr/>
<h2 id="claude-code-blog-series">Claude Code Blog Series</h2>
<p><strong>Previous:</strong> <a href="./2025-08-04--claude-code-part-6-subagents-task-delegation">Part 6 - Subagents and Task Delegation</a>
<strong>Next:</strong> <a href="./2025-08-06--claude-code-part-8-hooks-automated-quality-checks">Part 8 - Hooks for Automated Quality Checks</a></p>
<p><strong>Full Series:</strong></p>
<ol>
<li>Part 1 - Getting Started and Installation</li>
<li>Part 2 - CLAUDE.md Configuration Files</li>
<li>Part 3 - Conversation Management and Context</li>
<li>Part 4 - Slash Commands and Custom Commands</li>
<li>Part 5 - MCP Servers and Tool Integration</li>
<li>Part 6 - Subagents and Task Delegation</li>
<li>Part 7 - IDE Integration with VS Code and JetBrains (this post)</li>
<li>Part 8 - Hooks for Automated Quality Checks</li>
<li>Part 9 - Complete Development Workflows</li>
<li>Part 10 - Power User CLI Options and Scripting</li>
<li>Part 11 - Troubleshooting and Recovery</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Claude Code: Part 6 - Subagents and Task Delegation</title>
      <link>https://letanure.dev/writing/claude-code-part-6-subagents-task-delegation/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/claude-code-part-6-subagents-task-delegation/</guid>
      <pubDate>Mon, 04 Aug 2025 00:00:00 GMT</pubDate>
      <description>Learn how to delegate complex, multi-step analysis and implementation tasks to autonomous subagents. Let specialized AI agents handle comprehensive codebase analysis, feature planning, and systematic problem-solving...</description>
      <content:encoded><![CDATA[<h1 id="claude-code-part-6---subagents-and-task-delegation">Claude Code: Part 6 - Subagents and Task Delegation</h1>
<h2 id="the-problem">The Problem</h2>
<p>You’re facing a complex development challenge that requires deep, systematic analysis:</p>
<ul>
<li>Refactoring a large legacy system with many interdependencies</li>
<li>Planning a major feature that touches multiple parts of your application</li>
<li>Investigating a performance issue that could have various root causes</li>
<li>Migrating to a new framework while maintaining functionality</li>
</ul>
<p>These tasks require hours of careful analysis, reading through dozens of files, understanding complex relationships, and maintaining context across multiple steps. It’s exhausting to guide Claude through every single step, and you lose focus on the bigger picture while managing the details.</p>
<h2 id="the-solution">The Solution</h2>
<p>Subagents are specialized AI assistants that operate in separate contexts with focused expertise. They handle complex tasks autonomously while you focus on high-level decisions.</p>
<p><strong>Learn more:</strong> <a href="https://docs.anthropic.com/en/docs/claude-code/sub-agents">Subagents Documentation</a></p>
<h2 id="how-subagents-work">How Subagents Work</h2>
<p><strong>Creation:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">/agents</span><span style="color:#6A737D">  # Interactive interface (recommended)</span></span>
<span class="line"><span style="color:#6A737D"># Or create files in .claude/agents/ or ~/.claude/agents/</span></span></code></pre>
<p><strong>Usage:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>Use an agent to analyze the authentication system</span></span></code></pre>
<p><strong>What happens:</strong> ⏺ indicator shows subagent is working autonomously</p>
<h3 id="key-features">Key Features</h3>
<ul>
<li><strong>Separate contexts</strong> - Don’t consume main conversation tokens</li>
<li><strong>Specialized expertise</strong> - Custom system prompts for specific tasks</li>
<li><strong>Tool access control</strong> - Limited permissions for security</li>
<li><strong>Automatic selection</strong> - Claude picks appropriate agent for task</li>
</ul>
<h2 id="agent-types">Agent Types</h2>
<p><strong>Code Reviewer:</strong> Proactively reviews code quality and security
<strong>Debugger:</strong> Specializes in root cause analysis<br/>
<strong>Data Scientist:</strong> Focuses on SQL queries and data analysis</p>
<h2 id="when-to-use">When to Use</h2>
<ul>
<li>Complex codebase analysis</li>
<li>Multi-step refactoring plans</li>
<li>Performance investigations</li>
<li>Architecture planning</li>
<li>Systematic code reviews</li>
</ul>
<h2 id="best-practices">Best Practices</h2>
<ul>
<li><strong>Single responsibility</strong> - One focused purpose per agent</li>
<li><strong>Clear system prompts</strong> - Detailed instructions for agent behavior</li>
<li><strong>Limited tool access</strong> - Only necessary permissions</li>
<li><strong>Version control</strong> - Track project-level agents in git</li>
</ul>
<h2 id="example-usage">Example Usage</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;Use an agent to analyze the user onboarding flow&quot;</span></span>
<span class="line"><span>&quot;Use an agent to plan Redux to Zustand migration&quot;  </span></span>
<span class="line"><span>&quot;Use an agent to review payment processing security&quot;</span></span></code></pre>
<h2 id="working-with-results">Working with Results</h2>
<ul>
<li><strong>Review outputs</strong> - Subagent results may need refinement</li>
<li><strong>Break down plans</strong> - Convert analysis into actionable steps</li>
<li><strong>Chain agents</strong> - Use results for follow-up analysis</li>
</ul>
<h2 id="task-definition-tips">Task Definition Tips</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>❌ &quot;Use an agent to look at the code&quot;</span></span>
<span class="line"><span>✅ &quot;Use an agent to analyze authentication security and create modernization plan&quot;</span></span></code></pre>
<p><strong>Be specific:</strong></p>
<ul>
<li>Define scope and constraints</li>
<li>Set success criteria</li>
<li>Request actionable output</li>
</ul>
<h2 id="performance-benefits">Performance Benefits</h2>
<ul>
<li><strong>Context preservation</strong> - Don’t consume main conversation tokens</li>
<li><strong>Specialized analysis</strong> - Custom expertise for specific tasks</li>
<li><strong>Autonomous work</strong> - No need for step-by-step guidance</li>
<li><strong>Chain workflows</strong> - Connect multiple agents for complex tasks</li>
</ul>
<h2 id="when-not-to-use">When NOT to Use</h2>
<ul>
<li>Simple questions</li>
<li>Interactive debugging</li>
<li>Small changes</li>
<li>Tasks needing frequent input</li>
</ul>
<h2 id="getting-started">Getting Started</h2>
<ol>
<li>Use <code>/agents</code> to create specialized agents</li>
<li>Start with analysis tasks</li>
<li>Be specific about scope and goals</li>
<li>Review and iterate on results</li>
</ol>
<p>Subagents transform Claude into specialized AI analysts handling complex work autonomously.</p>
<hr/>
<h2 id="claude-code-blog-series">Claude Code Blog Series</h2>
<p><strong>Previous:</strong> <a href="./2025-08-03--claude-code-part-5-mcp-servers-tool-integration">Part 5 - MCP Servers and Tool Integration</a>
<strong>Next:</strong> <a href="./2025-08-05--claude-code-part-7-ide-integration-vscode-jetbrains">Part 7 - IDE Integration with VS Code and JetBrains</a></p>
<p><strong>Full Series:</strong></p>
<ol>
<li>Part 1 - Getting Started and Installation</li>
<li>Part 2 - CLAUDE.md Configuration Files</li>
<li>Part 3 - Conversation Management and Context</li>
<li>Part 4 - Slash Commands and Custom Commands</li>
<li>Part 5 - MCP Servers and Tool Integration</li>
<li>Part 6 - Subagents and Task Delegation (this post)</li>
<li>Part 7 - IDE Integration with VS Code and JetBrains</li>
<li>Part 8 - Hooks for Automated Quality Checks</li>
<li>Part 9 - Complete Development Workflows</li>
<li>Part 10 - Power User CLI Options and Scripting</li>
<li>Part 11 - Troubleshooting and Recovery</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Claude Code: Part 5 - MCP Servers and Tool Integration</title>
      <link>https://letanure.dev/writing/claude-code-part-5-mcp-servers-tool-integration/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/claude-code-part-5-mcp-servers-tool-integration/</guid>
      <pubDate>Sun, 03 Aug 2025 00:00:00 GMT</pubDate>
      <description>Stop switching between Claude Code, GitHub, Sentry, and other development tools. Learn how MCP (Model Context Protocol) servers create seamless workflows by connecting all your tools directly within Claude Code.</description>
      <content:encoded><![CDATA[<h1 id="claude-code-part-5---mcp-servers-and-tool-integration">Claude Code: Part 5 - MCP Servers and Tool Integration</h1>
<h2 id="the-problem">The Problem</h2>
<p>Your development workflow involves constant tool switching:</p>
<ul>
<li>Claude Code for development assistance</li>
<li>GitHub web interface for issues and PRs</li>
<li>Sentry dashboard for error monitoring</li>
<li>Database tools for query analysis</li>
<li>Slack for team communication</li>
<li>Linear/Jira for project management</li>
</ul>
<p>Each context switch breaks your flow. You’re helping Claude understand an issue, then jumping to Sentry to grab error details, back to Claude to explain the context, then to GitHub to check related issues. By the time you’ve gathered all the information, you’ve lost your problem-solving momentum.</p>
<h2 id="the-solution">The Solution</h2>
<p>MCP (Model Context Protocol) servers connect your external tools directly to Claude Code. Think of it as giving Claude direct access to your development toolchain - it can read GitHub issues, analyze Sentry errors, and query databases without you having to switch contexts manually.</p>
<h2 id="what-is-mcp">What is MCP?</h2>
<p>MCP (Model Context Protocol) is an open-source standard that connects Claude Code to external tools and services. Instead of manual copy-pasting, Claude accesses tools directly.</p>
<p><strong>Learn more:</strong> <a href="https://docs.anthropic.com/en/docs/claude-code/mcp">MCP Documentation</a></p>
<p><strong>Example:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>You: &quot;Analyze Sentry errors for authentication&quot;</span></span>
<span class="line"><span>Claude: [Queries Sentry directly, analyzes data, provides insights]</span></span></code></pre>
<h2 id="essential-mcp-servers">Essential MCP Servers</h2>
<h3 id="installation-methods">Installation Methods</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Add local server</span></span>
<span class="line"><span style="color:#B392F0">claude</span><span style="color:#9ECBFF"> mcp</span><span style="color:#9ECBFF"> add</span><span style="color:#9ECBFF"> server-name</span><span style="color:#9ECBFF"> /path/to/server</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Add remote SSE server (real-time)</span></span>
<span class="line"><span style="color:#B392F0">claude</span><span style="color:#9ECBFF"> mcp</span><span style="color:#9ECBFF"> add</span><span style="color:#79B8FF"> --transport</span><span style="color:#9ECBFF"> sse</span><span style="color:#9ECBFF"> name</span><span style="color:#9ECBFF"> https://server-url/sse</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Add remote HTTP server</span></span>
<span class="line"><span style="color:#B392F0">claude</span><span style="color:#9ECBFF"> mcp</span><span style="color:#9ECBFF"> add</span><span style="color:#79B8FF"> --transport</span><span style="color:#9ECBFF"> http</span><span style="color:#9ECBFF"> name</span><span style="color:#9ECBFF"> https://server-url/mcp</span></span></code></pre>
<h3 id="github-server">GitHub Server</h3>
<ul>
<li>Read issues, PRs, and discussions</li>
<li>Create issues and PRs</li>
<li>Analyze commits and code changes</li>
</ul>
<h3 id="sentry-server">Sentry Server</h3>
<ul>
<li>Analyze error trends and stack traces</li>
<li>Correlate errors with code changes</li>
<li>Suggest fixes based on context</li>
</ul>
<h3 id="other-popular-servers">Other Popular Servers</h3>
<ul>
<li><strong>Linear/Asana</strong> - Project management</li>
<li><strong>Notion</strong> - Documentation</li>
<li><strong>Stripe</strong> - Payment processing</li>
<li><strong>Figma</strong> - Design integration</li>
<li><strong>Airtable</strong> - Database/spreadsheets</li>
<li><strong>SQLite/PostgreSQL</strong> - Database querying</li>
</ul>
<h2 id="authentication">Authentication</h2>
<ul>
<li><strong>OAuth 2.0 support</strong> - Secure authentication</li>
<li><strong>Use <code>/mcp</code> to authenticate</strong> - Follow prompts</li>
<li><strong>Tokens refresh automatically</strong> - No manual renewal</li>
</ul>
<p>⚠️ <strong>Security Note:</strong> Use third-party MCP servers at your own risk. Verify trustworthiness before installing.</p>
<h2 id="managing-connections">Managing Connections</h2>
<p>Use <code>/mcp</code> to:</p>
<ul>
<li>View connected servers</li>
<li>Check authentication status</li>
<li>Reconnect or configure servers</li>
</ul>
<h2 id="example-workflows">Example Workflows</h2>
<p><strong>Bug investigation:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;Check Sentry for login errors, correlate with recent GitHub commits&quot;</span></span></code></pre>
<p><strong>PR review:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;Review PR #123, check for related Sentry errors and security issues&quot;</span></span></code></pre>
<p><strong>Release prep:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;List GitHub issues for v2.1.0, check critical Sentry errors&quot;</span></span></code></pre>
<h3 id="network-security">Network Security</h3>
<ul>
<li><strong>Firewall considerations</strong> - MCP servers make external API calls</li>
<li><strong>Corporate networks</strong> - May need proxy configuration</li>
<li><strong>Rate limiting</strong> - Respect service API limits</li>
</ul>
<h2 id="troubleshooting-mcp-issues">Troubleshooting MCP Issues</h2>
<h3 id="connection-problems">Connection Problems</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Check server status</span></span>
<span class="line"><span style="color:#B392F0">/mcp</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Verify installation</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> list</span><span style="color:#79B8FF"> -g</span><span style="color:#F97583"> |</span><span style="color:#B392F0"> grep</span><span style="color:#9ECBFF"> mcp</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Test authentication</span></span>
<span class="line"><span style="color:#6A737D"># Use service-specific test commands</span></span></code></pre>
<h3 id="authentication-failures">Authentication Failures</h3>
<ol>
<li><strong>Verify tokens</strong> are valid and not expired</li>
<li><strong>Check permissions</strong> - ensure tokens have necessary scopes</li>
<li><strong>Review network</strong> - firewalls might block connections</li>
<li><strong>Restart Claude</strong> to reload MCP configurations</li>
</ol>
<h3 id="performance-considerations">Performance Considerations</h3>
<ul>
<li><strong>MCP calls take time</strong> - External API requests add latency</li>
<li><strong>Batch requests</strong> when possible - ask for related data together</li>
<li><strong>Cache awareness</strong> - Some data might be cached by MCP servers</li>
</ul>
<h2 id="getting-started-with-mcp">Getting Started with MCP</h2>
<ol>
<li><strong>Start with GitHub</strong> - Most immediately useful for developers</li>
<li><strong>Add error monitoring</strong> - Sentry integration saves significant context switching</li>
<li><strong>Include security scanning</strong> - Socket.dev prevents supply chain issues</li>
<li><strong>Explore gradually</strong> - Add servers as you identify workflow gaps</li>
</ol>
<p><strong>Simple first test:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;Check our GitHub repository for any open issues tagged as &#39;bug&#39;&quot;</span></span></code></pre>
<p>MCP transforms Claude Code from an isolated assistant into a fully connected development partner that can access and analyze data from your entire toolchain.</p>
<hr/>
<h2 id="claude-code-blog-series">Claude Code Blog Series</h2>
<p><strong>Previous:</strong> <a href="./2025-08-02--claude-code-part-4-slash-commands-custom-commands">Part 4 - Slash Commands and Custom Commands</a>
<strong>Next:</strong> <a href="./2025-08-04--claude-code-part-6-subagents-task-delegation">Part 6 - Subagents and Task Delegation</a></p>
<p><strong>Full Series:</strong></p>
<ol>
<li>Part 1 - Getting Started and Installation</li>
<li>Part 2 - CLAUDE.md Configuration Files</li>
<li>Part 3 - Conversation Management and Context</li>
<li>Part 4 - Slash Commands and Custom Commands</li>
<li>Part 5 - MCP Servers and Tool Integration (this post)</li>
<li>Part 6 - Subagents and Task Delegation</li>
<li>Part 7 - IDE Integration with VS Code and JetBrains</li>
<li>Part 8 - Hooks for Automated Quality Checks</li>
<li>Part 9 - Complete Development Workflows</li>
<li>Part 10 - Power User CLI Options and Scripting</li>
<li>Part 11 - Troubleshooting and Recovery</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Claude Code: Part 4 - Slash Commands and Custom Commands</title>
      <link>https://letanure.dev/writing/claude-code-part-4-slash-commands-custom-commands/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/claude-code-part-4-slash-commands-custom-commands/</guid>
      <pubDate>Sat, 02 Aug 2025 00:00:00 GMT</pubDate>
      <description>Stop repeating the same instructions every day. Learn to use built-in slash commands and create custom commands that automate your most common Claude Code workflows and development tasks.</description>
      <content:encoded><![CDATA[<h1 id="claude-code-part-4---slash-commands-and-custom-commands">Claude Code: Part 4 - Slash Commands and Custom Commands</h1>
<h2 id="the-problem">The Problem</h2>
<p>You type the same instructions to Claude every day: “Run tests”, “Check TypeScript errors”, “Review changes”. Repetitive and wasteful.</p>
<h2 id="the-solution">The Solution</h2>
<p>Slash commands turn repeated instructions into shortcuts. <code>/test</code> replaces paragraphs of testing instructions.</p>
<h2 id="built-in-commands">Built-in Commands</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">/clear</span><span style="color:#6A737D">      # Fresh start</span></span>
<span class="line"><span style="color:#B392F0">/compact</span><span style="color:#6A737D">    # Compress history  </span></span>
<span class="line"><span style="color:#B392F0">/help</span><span style="color:#6A737D">       # Show commands</span></span>
<span class="line"><span style="color:#B392F0">/agents</span><span style="color:#6A737D">     # Manage subagents</span></span>
<span class="line"><span style="color:#B392F0">/add-dir</span><span style="color:#6A737D">    # Add working directory</span></span>
<span class="line"><span style="color:#B392F0">/bug</span><span style="color:#6A737D">        # Report bug</span></span>
<span class="line"><span style="color:#B392F0">/config</span><span style="color:#6A737D">     # Show configuration</span></span>
<span class="line"><span style="color:#B392F0">/mcp</span><span style="color:#6A737D">        # MCP servers</span></span>
<span class="line"><span style="color:#B392F0">/review</span><span style="color:#6A737D">     # Request code review</span></span>
<span class="line"><span style="color:#B392F0">/exit</span><span style="color:#6A737D">       # End session</span></span></code></pre>
<h2 id="custom-commands">Custom Commands</h2>
<p>Create <code>.claude/commands/test-all.md</code>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="markdown"><code><span class="line"><span style="color:#FFAB70">1.</span><span style="color:#E1E4E8"> Run pnpm type:check</span></span>
<span class="line"><span style="color:#FFAB70">2.</span><span style="color:#E1E4E8"> Run pnpm lint</span></span>
<span class="line"><span style="color:#FFAB70">3.</span><span style="color:#E1E4E8"> Run pnpm test</span></span>
<span class="line"><span style="color:#FFAB70">4.</span><span style="color:#E1E4E8"> Report issues</span></span></code></pre>
<p>Now <code>/test-all</code> runs everything.</p>
<h3 id="example-commands">Example Commands</h3>
<p><code>.claude/commands/morning.md</code>: Daily setup (git pull, tests, status)
<code>.claude/commands/ready.md</code>: Pre-commit checks
<code>.claude/commands/review.md</code>: PR preparation</p>
<h2 id="organization">Organization</h2>
<p>Group commands by phase (planning/, development/, deployment/) or domain (frontend/, backend/, testing/).</p>
<h2 id="best-practices">Best Practices</h2>
<ul>
<li>Be specific: “Check TypeScript errors in src/” not “Check code”</li>
<li>Include success criteria: “0 test failures, 80% coverage”</li>
<li>Keep commands under 10 steps</li>
<li>Use numbered lists for clarity</li>
</ul>
<h2 id="sharing-commands">Sharing Commands</h2>
<ul>
<li><strong>Team:</strong> Commit <code>.claude/commands/</code> to git</li>
<li><strong>Personal:</strong> Use <code>~/.claude/commands/</code> globally</li>
</ul>
<h2 id="advanced-features">Advanced Features</h2>
<p>Commands can include:</p>
<ul>
<li>Parameters: “Ask for feature name, create feature/[name]”</li>
<li>Conditionals: “If production, run security scan”</li>
<li>Context awareness: “Analyze current file”</li>
</ul>
<h2 id="getting-started">Getting Started</h2>
<ol>
<li>Identify what you repeat daily</li>
<li>Create <code>.claude/commands/[name].md</code></li>
<li>Keep instructions under 10 steps</li>
<li>Test and refine</li>
</ol>
<p>Slash commands eliminate repetitive instructions.</p>
<hr/>
<h2 id="claude-code-blog-series">Claude Code Blog Series</h2>
<p><strong>Previous:</strong> <a href="./2025-08-01--claude-code-part-3-conversation-management-context">Part 3 - Conversation Management and Context</a>
<strong>Next:</strong> <a href="./2025-08-03--claude-code-part-5-mcp-servers-tool-integration">Part 5 - MCP Servers and Tool Integration</a></p>
<p><strong>Full Series:</strong></p>
<ol>
<li>Part 1 - Getting Started and Installation</li>
<li>Part 2 - CLAUDE.md Configuration Files</li>
<li>Part 3 - Conversation Management and Context</li>
<li>Part 4 - Slash Commands and Custom Commands (this post)</li>
<li>Part 5 - MCP Servers and Tool Integration</li>
<li>Part 6 - Subagents and Task Delegation</li>
<li>Part 7 - IDE Integration with VS Code and JetBrains</li>
<li>Part 8 - Hooks for Automated Quality Checks</li>
<li>Part 9 - Complete Development Workflows</li>
<li>Part 10 - Power User CLI Options and Scripting</li>
<li>Part 11 - Troubleshooting and Recovery</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Claude Code: Part 3 - Conversation Management and Context</title>
      <link>https://letanure.dev/writing/claude-code-part-3-conversation-management-context/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/claude-code-part-3-conversation-management-context/</guid>
      <pubDate>Fri, 01 Aug 2025 00:00:00 GMT</pubDate>
      <description>Move beyond basic Claude Code usage to advanced features like conversation management, multi-step workflows, context optimization, and preview mode. Transform from casual user to power user.</description>
      <content:encoded><![CDATA[<h1 id="claude-code-part-3---conversation-management-and-context">Claude Code: Part 3 - Conversation Management and Context</h1>
<h2 id="the-problem">The Problem</h2>
<p>You’ve been using Claude Code for a few weeks now. The basic workflow is comfortable - ask questions, get code, make changes. But you’re starting to feel limited by treating Claude like a simple question-and-answer tool.</p>
<p>You have bigger ambitions: complex refactoring projects, multi-step feature implementations, and sophisticated analysis tasks. You want to move beyond “Hey Claude, fix this function” to “Claude, help me architect and implement this entire feature from scratch.”</p>
<p>The question is: how do you unlock Claude’s advanced capabilities for complex, multi-step development work?</p>
<h2 id="the-solution">The Solution</h2>
<p>Advanced Claude Code features let you handle sophisticated development tasks through multi-step workflows, conversation management, and intelligent context handling. Think of it as the difference between using Claude as a coding helper versus a true development partner.</p>
<h2 id="conversation-management">Conversation Management</h2>
<h3 id="the-clear-command">The <code>/clear</code> Command</h3>
<p>Start fresh when switching contexts:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">/clear</span></span></code></pre>
<p><strong>When to use:</strong></p>
<ul>
<li>Switching between different features</li>
<li>Moving from debugging to new development</li>
<li>When conversation gets too long and unfocused</li>
</ul>
<h3 id="the-compact-command">The <code>/compact</code> Command</h3>
<p>Summarize long conversations while preserving context:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">/compact</span></span></code></pre>
<p><strong>What it does:</strong></p>
<ul>
<li>Compresses conversation history</li>
<li>Keeps key decisions and context</li>
<li>Reduces token usage without losing information</li>
</ul>
<p><strong>Example:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>Before: 50 messages about implementing user authentication</span></span>
<span class="line"><span>After: Compact summary + recent conversation about email verification</span></span></code></pre>
<h3 id="resume-previous-sessions">Resume Previous Sessions</h3>
<p>Continue where you left off:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">claude</span><span style="color:#79B8FF"> --resume</span><span style="color:#6A737D">        # Interactive conversation picker</span></span>
<span class="line"><span style="color:#B392F0">claude</span><span style="color:#79B8FF"> --continue</span><span style="color:#6A737D">      # Resume most recent conversation</span></span></code></pre>
<h2 id="multi-step-workflows">Multi-Step Workflows</h2>
<h3 id="planning-complex-features">Planning Complex Features</h3>
<p>Instead of diving into code, start with comprehensive planning:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>I need to implement a real-time notification system for this React app.</span></span>
<span class="line"><span>Before writing any code, help me plan:</span></span>
<span class="line"><span></span></span>
<span class="line"><span>1. Architecture design considerations</span></span>
<span class="line"><span>2. Technology choices (WebSocket vs Server-Sent Events vs polling)</span></span>
<span class="line"><span>3. Database schema requirements</span></span>
<span class="line"><span>4. Component structure and data flow</span></span>
<span class="line"><span>5. Testing strategy</span></span>
<span class="line"><span>6. Performance and scalability considerations</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Break this down systematically.</span></span></code></pre>
<p>Claude will provide structured analysis before any implementation begins.</p>
<h3 id="iterative-development-approach">Iterative Development Approach</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>Let&#39;s build this notification system step by step:</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Phase 1: Create the basic WebSocket connection and message handling</span></span>
<span class="line"><span>Phase 2: Implement the UI components for displaying notifications</span></span>
<span class="line"><span>Phase 3: Add persistence and notification history</span></span>
<span class="line"><span>Phase 4: Implement real-time updates and optimistic UI</span></span>
<span class="line"><span>Phase 5: Add comprehensive testing</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Start with Phase 1. After each phase, I&#39;ll review and approve before moving forward.</span></span></code></pre>
<h3 id="complex-refactoring-projects">Complex Refactoring Projects</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>I need to refactor this legacy authentication system. Here&#39;s my approach:</span></span>
<span class="line"><span></span></span>
<span class="line"><span>1. First, analyze the current system and identify all dependencies</span></span>
<span class="line"><span>2. Create a migration plan that maintains backward compatibility</span></span>
<span class="line"><span>3. Implement the new system alongside the old one</span></span>
<span class="line"><span>4. Create a feature flag to switch between systems</span></span>
<span class="line"><span>5. Gradually migrate users and test thoroughly</span></span>
<span class="line"><span>6. Remove the old system once migration is complete</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Start with step 1 - comprehensive analysis of the current system.</span></span></code></pre>
<h2 id="context-management-techniques">Context Management Techniques</h2>
<h3 id="focused-sessions">Focused Sessions</h3>
<p>Keep conversations targeted to specific domains:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span># Authentication Session</span></span>
<span class="line"><span>&quot;I&#39;m working solely on authentication features today.</span></span>
<span class="line"><span>Only suggest changes related to auth, login, registration, and user management.&quot;</span></span>
<span class="line"><span></span></span>
<span class="line"><span># Performance Session</span></span>
<span class="line"><span>&quot;This session is focused on performance optimization.</span></span>
<span class="line"><span>Analyze bundle size, loading times, and runtime performance only.&quot;</span></span></code></pre>
<h3 id="reference-management">Reference Management</h3>
<p>Help Claude understand large codebases:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;The main authentication flow happens in these files:</span></span>
<span class="line"><span>- src/auth/AuthProvider.tsx (context setup)</span></span>
<span class="line"><span>- src/auth/hooks/useAuth.ts (auth logic)</span></span>
<span class="line"><span>- src/pages/login.tsx (login UI)</span></span>
<span class="line"><span>- api/auth/login.ts (backend logic)</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Reference these files when working on auth-related tasks.&quot;</span></span></code></pre>
<h3 id="incremental-context-building">Incremental Context Building</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;Let me give you context about our e-commerce platform:</span></span>
<span class="line"><span></span></span>
<span class="line"><span>1. We use Next.js with TypeScript</span></span>
<span class="line"><span>2. State management with Zustand</span></span>
<span class="line"><span>3. UI components with Radix + Tailwind</span></span>
<span class="line"><span>4. Database with Prisma + PostgreSQL</span></span>
<span class="line"><span>5. Payment processing with Stripe</span></span>
<span class="line"><span></span></span>
<span class="line"><span>I&#39;ll be asking you to work on various features within this context.&quot;</span></span></code></pre>
<h2 id="advanced-analysis-capabilities">Advanced Analysis Capabilities</h2>
<h3 id="codebase-architecture-analysis">Codebase Architecture Analysis</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;Analyze the overall architecture of this React application:</span></span>
<span class="line"><span></span></span>
<span class="line"><span>1. Component organization and hierarchy</span></span>
<span class="line"><span>2. State management patterns used</span></span>
<span class="line"><span>3. Data flow and communication patterns</span></span>
<span class="line"><span>4. Third-party integrations and dependencies</span></span>
<span class="line"><span>5. Testing strategy and coverage</span></span>
<span class="line"><span>6. Build and deployment setup</span></span>
<span class="line"><span>7. Potential architectural issues or technical debt</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Provide a comprehensive architectural overview.&quot;</span></span></code></pre>
<h3 id="performance-analysis">Performance Analysis</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;Conduct a performance analysis of this application:</span></span>
<span class="line"><span></span></span>
<span class="line"><span>1. Bundle size analysis and recommendations</span></span>
<span class="line"><span>2. Runtime performance bottlenecks</span></span>
<span class="line"><span>3. Database query optimization opportunities</span></span>
<span class="line"><span>4. API endpoint performance issues</span></span>
<span class="line"><span>5. Frontend rendering optimizations</span></span>
<span class="line"><span>6. Caching strategy improvements</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Focus on actionable performance improvements.&quot;</span></span></code></pre>
<h3 id="security-assessment">Security Assessment</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;Review this application for security vulnerabilities:</span></span>
<span class="line"><span></span></span>
<span class="line"><span>1. Authentication and authorization implementation</span></span>
<span class="line"><span>2. Input validation and sanitization</span></span>
<span class="line"><span>3. API endpoint security</span></span>
<span class="line"><span>4. Database query security (SQL injection prevention)</span></span>
<span class="line"><span>5. XSS and CSRF protection</span></span>
<span class="line"><span>6. Sensitive data handling</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Identify specific security improvements needed.&quot;</span></span></code></pre>
<h2 id="preview-mode">Preview Mode</h2>
<p>See what Claude will do before making changes:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;Show me exactly what changes you would make to implement user roles,</span></span>
<span class="line"><span>but don&#39;t make any changes yet. I want to review your plan first.&quot;</span></span></code></pre>
<p>Claude will outline:</p>
<ul>
<li>Files that need to be modified</li>
<li>New files that need to be created</li>
<li>Specific changes to existing code</li>
<li>Testing requirements</li>
<li>Potential breaking changes</li>
</ul>
<h2 id="advanced-problem-solving-patterns">Advanced Problem-Solving Patterns</h2>
<h3 id="root-cause-analysis">Root Cause Analysis</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;This React component is causing memory leaks. Don&#39;t just fix the symptom -</span></span>
<span class="line"><span>investigate the root cause:</span></span>
<span class="line"><span></span></span>
<span class="line"><span>1. Analyze the component lifecycle and cleanup</span></span>
<span class="line"><span>2. Check for subscription leaks and event listeners</span></span>
<span class="line"><span>3. Examine state management and data flow</span></span>
<span class="line"><span>4. Look for circular references or closures</span></span>
<span class="line"><span>5. Identify the fundamental issue causing the leak</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Provide both the analysis and the fix.&quot;</span></span></code></pre>
<h3 id="system-integration">System Integration</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;Help me integrate Stripe payments into this e-commerce app.</span></span>
<span class="line"><span>Consider the full integration:</span></span>
<span class="line"><span></span></span>
<span class="line"><span>1. Frontend payment component with proper UX</span></span>
<span class="line"><span>2. Backend webhook handling and security</span></span>
<span class="line"><span>3. Database schema for orders and payment tracking</span></span>
<span class="line"><span>4. Error handling and retry logic</span></span>
<span class="line"><span>5. Testing strategy for payment flows</span></span>
<span class="line"><span>6. Compliance and security requirements</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Design the complete integration, not just the payment form.&quot;</span></span></code></pre>
<h3 id="scalability-planning">Scalability Planning</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;This app currently handles 1,000 users. Help me prepare it for 100,000 users:</span></span>
<span class="line"><span></span></span>
<span class="line"><span>1. Database optimization and indexing</span></span>
<span class="line"><span>2. API rate limiting and caching</span></span>
<span class="line"><span>3. Frontend performance optimization</span></span>
<span class="line"><span>4. Infrastructure scaling considerations</span></span>
<span class="line"><span>5. Monitoring and alerting setup</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Create a scalability roadmap with specific implementation steps.&quot;</span></span></code></pre>
<h2 id="efficient-context-switching">Efficient Context Switching</h2>
<h3 id="project-templates">Project Templates</h3>
<p>Create reusable project contexts:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;Save this as my &#39;React + TypeScript Web App&#39; context:</span></span>
<span class="line"><span>- Next.js 13+ with TypeScript</span></span>
<span class="line"><span>- Tailwind CSS for styling</span></span>
<span class="line"><span>- Prisma for database</span></span>
<span class="line"><span>- NextAuth for authentication</span></span>
<span class="line"><span>- React Query for API calls</span></span>
<span class="line"><span>- Jest + React Testing Library for tests</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Use this context for all similar projects unless I specify otherwise.&quot;</span></span></code></pre>
<h3 id="domain-specific-sessions">Domain-Specific Sessions</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Database session</span></span>
<span class="line"><span style="color:#B392F0">claude</span><span style="color:#79B8FF"> --session=database</span></span>
<span class="line"><span style="color:#B392F0">&quot;Focus only on database schema, queries, and data modeling&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Frontend session</span></span>
<span class="line"><span style="color:#B392F0">claude</span><span style="color:#79B8FF"> --session=frontend</span></span>
<span class="line"><span style="color:#B392F0">&quot;Work only on React components, styling, and user interface&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># API session</span></span>
<span class="line"><span style="color:#B392F0">claude</span><span style="color:#79B8FF"> --session=api</span></span>
<span class="line"><span style="color:#B392F0">&quot;Handle only backend logic, API endpoints, and server-side code&quot;</span></span></code></pre>
<h2 id="advanced-debugging-workflows">Advanced Debugging Workflows</h2>
<h3 id="systematic-bug-investigation">Systematic Bug Investigation</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;This user registration is failing intermittently. Let&#39;s debug systematically:</span></span>
<span class="line"><span></span></span>
<span class="line"><span>1. Reproduce the issue in development</span></span>
<span class="line"><span>2. Add comprehensive logging to track the flow</span></span>
<span class="line"><span>3. Analyze potential race conditions</span></span>
<span class="line"><span>4. Check database constraints and validation</span></span>
<span class="line"><span>5. Review error handling and edge cases</span></span>
<span class="line"><span>6. Create a test that reproduces the bug</span></span>
<span class="line"><span>7. Fix the root cause</span></span>
<span class="line"><span>8. Verify the fix prevents regression</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Start with step 1 - let&#39;s reproduce this issue.&quot;</span></span></code></pre>
<h2 id="getting-started-with-advanced-features">Getting Started with Advanced Features</h2>
<ol>
<li><strong>Plan before coding</strong> - Use Claude for architectural planning</li>
<li><strong>Break down complex tasks</strong> - Multi-phase implementation approach</li>
<li><strong>Manage conversation context</strong> - Use <code>/clear</code> and <code>/compact</code> strategically</li>
<li><strong>Preview changes</strong> - Review plans before implementation</li>
<li><strong>Focus sessions</strong> - One domain per conversation when possible</li>
</ol>
<p>Advanced Claude Code usage transforms development from individual task assistance to comprehensive project partnership.</p>
<hr/>
<h2 id="claude-code-blog-series">Claude Code Blog Series</h2>
<p><strong>Previous:</strong> <a href="./2025-07-31--claude-code-part-2-claude-md-configuration">Part 2 - CLAUDE.md Configuration Files</a>
<strong>Next:</strong> <a href="./2025-08-02--claude-code-part-4-slash-commands-custom-commands">Part 4 - Slash Commands and Custom Commands</a></p>
<p><strong>Full Series:</strong></p>
<ol>
<li>Part 1 - Getting Started and Installation</li>
<li>Part 2 - CLAUDE.md Configuration Files</li>
<li>Part 3 - Conversation Management and Context (this post)</li>
<li>Part 4 - Slash Commands and Custom Commands</li>
<li>Part 5 - MCP Servers and Tool Integration</li>
<li>Part 6 - Subagents and Task Delegation</li>
<li>Part 7 - IDE Integration with VS Code and JetBrains</li>
<li>Part 8 - Hooks for Automated Quality Checks</li>
<li>Part 9 - Complete Development Workflows</li>
<li>Part 10 - Power User CLI Options and Scripting</li>
<li>Part 11 - Troubleshooting and Recovery</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Claude Code: Part 2 - CLAUDE.md Configuration Files</title>
      <link>https://letanure.dev/writing/claude-code-part-2-claude-md-configuration/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/claude-code-part-2-claude-md-configuration/</guid>
      <pubDate>Thu, 31 Jul 2025 00:00:00 GMT</pubDate>
      <description>Learn how to use CLAUDE.md files to guide Claude Code&apos;s behavior, set project rules, and create consistent development patterns. Includes memory hierarchy, multi-AI tool sharing, and team collaboration strategies.</description>
      <content:encoded><![CDATA[<h1 id="claude-code-part-2---claudemd-configuration-files">Claude Code: Part 2 - CLAUDE.md Configuration Files</h1>
<h2 id="the-problem">The Problem</h2>
<p>You’ve started using Claude Code, and it’s incredibly capable. Too capable. It suggests complex architectural changes when you wanted a simple bug fix. It writes elaborate documentation when you needed a quick comment. It refactors your entire component when you asked it to fix one function.</p>
<p>Claude is like an enthusiastic new team member who doesn’t yet understand your project’s constraints, coding standards, or the difference between “quick fix” and “complete rewrite.”</p>
<p>You need a way to teach Claude about your project’s specific context, rules, and boundaries.</p>
<h2 id="the-solution">The Solution</h2>
<p>CLAUDE.md files act as a persistent memory system and rule book for your project. Think of it as onboarding documentation that teaches Claude about your project’s specific needs, just like you’d brief a new human developer.</p>
<h2 id="how-claudemd-works">How CLAUDE.md Works</h2>
<p>Place a <code>CLAUDE.md</code> file in your project root with rules and context:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="markdown"><code><span class="line"><span style="color:#79B8FF;font-weight:bold"># Project: E-commerce Platform</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF;font-weight:bold">## Tech Stack</span></span>
<span class="line"><span style="color:#FFAB70">-</span><span style="color:#E1E4E8"> Next.js, TypeScript, Tailwind, Prisma</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF;font-weight:bold">## Rules</span></span>
<span class="line"><span style="color:#FFAB70">-</span><span style="color:#E1E4E8"> Use TypeScript strict mode</span></span>
<span class="line"><span style="color:#FFAB70">-</span><span style="color:#E1E4E8"> Follow patterns in src/components/</span></span>
<span class="line"><span style="color:#FFAB70">-</span><span style="color:#E1E4E8"> Functional components only</span></span></code></pre>
<p>Claude now follows your project-specific rules automatically.</p>
<h2 id="memory-hierarchy">Memory Hierarchy</h2>
<p>Claude Code respects a hierarchy of configuration files, with more specific files overriding general ones:</p>
<h3 id="configuration-hierarchy">Configuration Hierarchy</h3>
<ol>
<li><strong>Enterprise:</strong> System-wide policies (highest priority)</li>
<li><strong>Project:</strong> <code>./CLAUDE.md</code> - Team rules for this project</li>
<li><strong>User:</strong> <code>~/.claude/CLAUDE.md</code> - Personal preferences across projects</li>
<li><strong>Project Local:</strong> Personal project overrides (deprecated)</li>
</ol>
<p>Higher-level memories take precedence. Use <code>/memory</code> to edit memory files directly.</p>
<h2 id="multi-ai-tool-sharing">Multi-AI Tool Sharing</h2>
<p>Want to use Claude Code alongside other AI tools? The CLAUDE.md approach works for now, but there’s an initiative to create a universal standard called AGENT.md. Learn more at <a href="https://ampcode.com/AGENT.md">ampcode.com/AGENT.md</a>.</p>
<p>For now, you can create a symlink to share the same configuration:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Create shared memory file</span></span>
<span class="line"><span style="color:#B392F0">mkdir</span><span style="color:#9ECBFF"> ~/.ai-tools</span></span>
<span class="line"><span style="color:#B392F0">touch</span><span style="color:#9ECBFF"> ~/.ai-tools/shared-memory.md</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Link it as CLAUDE.md</span></span>
<span class="line"><span style="color:#B392F0">ln</span><span style="color:#79B8FF"> -s</span><span style="color:#9ECBFF"> ~/.ai-tools/shared-memory.md</span><span style="color:#9ECBFF"> ./CLAUDE.md</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Link for other AI tools</span></span>
<span class="line"><span style="color:#B392F0">ln</span><span style="color:#79B8FF"> -s</span><span style="color:#9ECBFF"> ~/.ai-tools/shared-memory.md</span><span style="color:#9ECBFF"> ./AI-CONTEXT.md</span></span>
<span class="line"><span style="color:#B392F0">ln</span><span style="color:#79B8FF"> -s</span><span style="color:#9ECBFF"> ~/.ai-tools/shared-memory.md</span><span style="color:#9ECBFF"> ./CURSOR-RULES.md</span></span></code></pre>
<p><strong>Benefits:</strong></p>
<ul>
<li>One source of truth for project context</li>
<li>Consistent behavior across AI tools</li>
<li>Easy maintenance and updates</li>
</ul>
<h2 id="writing-effective-rules">Writing Effective Rules</h2>
<p><strong>Be specific and concise:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="markdown"><code><span class="line"><span style="color:#E1E4E8">❌ &quot;Use good coding practices&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">✅ &quot;Functional components, TypeScript, max 200 lines&quot;</span></span></code></pre>
<p><strong>Set clear boundaries:</strong></p>
<ul>
<li>Never modify payment code without review</li>
<li>No new packages without approval</li>
<li>No breaking API changes</li>
</ul>
<h2 id="token-consumption-warning">Token Consumption Warning</h2>
<p>⚠️ <strong>Keep CLAUDE.md files under 100 lines!</strong> They’re included in every interaction.</p>
<p><strong>Write concisely:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="markdown"><code><span class="line"><span style="color:#E1E4E8">❌ &quot;Always ensure components use hooks rather than classes&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">✅ &quot;Functional components only&quot;</span></span></code></pre>
<h2 id="best-practices">Best Practices</h2>
<ul>
<li>Start with 5-10 essential rules</li>
<li>Remove outdated rules regularly</li>
<li>Test rules work: “Create a component following our patterns”</li>
<li>Review monthly, prune verbosity</li>
</ul>
<h2 id="getting-started">Getting Started</h2>
<ol>
<li>Create <code>CLAUDE.md</code> with 5-10 essential rules</li>
<li>Test it works</li>
<li>Keep it under 100 lines</li>
<li>Update monthly</li>
</ol>
<p>CLAUDE.md transforms Claude into a project-aware teammate.</p>
<hr/>
<h2 id="claude-code-blog-series">Claude Code Blog Series</h2>
<p><strong>Previous:</strong> <a href="./2025-07-30--claude-code-part-1-getting-started-installation">Part 1 - Getting Started and Installation</a>
<strong>Next:</strong> <a href="./2025-08-01--claude-code-part-3-conversation-management-context">Part 3 - Conversation Management and Context</a></p>
<p><strong>Full Series:</strong></p>
<ol>
<li>Part 1 - Getting Started and Installation</li>
<li>Part 2 - CLAUDE.md Configuration Files (this post)</li>
<li>Part 3 - Conversation Management and Context</li>
<li>Part 4 - Slash Commands and Custom Commands</li>
<li>Part 5 - MCP Servers and Tool Integration</li>
<li>Part 6 - Subagents and Task Delegation</li>
<li>Part 7 - IDE Integration with VS Code and JetBrains</li>
<li>Part 8 - Hooks for Automated Quality Checks</li>
<li>Part 9 - Complete Development Workflows</li>
<li>Part 10 - Power User CLI Options and Scripting</li>
<li>Part 11 - Troubleshooting and Recovery</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Claude Code: Part 1 - Getting Started and Installation</title>
      <link>https://letanure.dev/writing/claude-code-part-1-getting-started-installation/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/claude-code-part-1-getting-started-installation/</guid>
      <pubDate>Wed, 30 Jul 2025 00:00:00 GMT</pubDate>
      <description>Meet Claude Code, your brilliant but overeager AI teammate. Learn how to set up and start working with Claude Code for software development, from installation to your first productive coding session.</description>
      <content:encoded><![CDATA[<h1 id="claude-code-part-1---getting-started-and-installation">Claude Code: Part 1 - Getting Started and Installation</h1>
<h2 id="the-problem">The Problem</h2>
<p>You’ve heard about AI coding assistants, but every one you’ve tried feels like a disconnected chatbot. They can generate code snippets, but they don’t understand your project, follow your patterns, or integrate with your actual development workflow.</p>
<p>You need an AI teammate that works <em>with</em> you, not just for you - one that understands your codebase, follows your coding standards, and becomes a true development partner rather than just another code completion tool.</p>
<h2 id="meet-your-new-teammate">Meet Your New Teammate</h2>
<p>Claude Code is like having a genius junior developer who took too many Red Bulls. Brilliant, capable of incredible work, but needs guidance on your specific project and coding patterns. The difference is that this teammate learns your project inside and out and never gets tired.</p>
<p><strong>What makes Claude Code different:</strong></p>
<ul>
<li><strong>Full codebase understanding</strong> - Reads and comprehends your entire project</li>
<li><strong>Project-aware</strong> - Follows your existing patterns and conventions</li>
<li><strong>Tool integration</strong> - Works with your development tools and services</li>
<li><strong>Contextual memory</strong> - Remembers project-specific rules and preferences</li>
</ul>
<h2 id="installation">Installation</h2>
<p><strong>Prerequisites:</strong></p>
<ul>
<li>Node.js (version 18 or higher)</li>
<li>npm or yarn package manager</li>
</ul>
<p><strong>Install globally:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> -g</span><span style="color:#9ECBFF"> @anthropic-ai/claude-code</span></span></code></pre>
<p><strong>Verify installation:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">claude</span><span style="color:#79B8FF"> --version</span></span></code></pre>
<p><strong>Start Claude Code:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># In your project directory</span></span>
<span class="line"><span style="color:#79B8FF">cd</span><span style="color:#9ECBFF"> your-project</span></span>
<span class="line"><span style="color:#B392F0">claude</span></span></code></pre>
<h2 id="first-session-setup">First Session Setup</h2>
<p>When you first run Claude Code:</p>
<ol>
<li><strong>Authentication</strong> - Follow the prompts to sign in</li>
<li><strong>Project detection</strong> - Claude analyzes your current directory</li>
<li><strong>Initial conversation</strong> - Start with a simple task to test everything works</li>
</ol>
<p><strong>Example first interaction:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>You: &quot;Analyze this project and tell me what kind of application this is&quot;</span></span>
<span class="line"><span>Claude: [Examines your files and provides project overview]</span></span></code></pre>
<h2 id="key-features-overview">Key Features Overview</h2>
<h3 id="codebase-analysis">Codebase Analysis</h3>
<p>Claude can read and understand your entire project:</p>
<ul>
<li><strong>Architecture patterns</strong> - Identifies frameworks and structures</li>
<li><strong>Coding conventions</strong> - Learns your style preferences</li>
<li><strong>Dependencies</strong> - Understands your tech stack</li>
<li><strong>Project context</strong> - Knows what your application does</li>
</ul>
<h3 id="intelligent-code-generation">Intelligent Code Generation</h3>
<p>Goes beyond simple snippets:</p>
<ul>
<li><strong>Pattern matching</strong> - Follows your existing code patterns</li>
<li><strong>Context-aware</strong> - Considers surrounding code and architecture</li>
<li><strong>Integration-focused</strong> - Creates code that fits your project</li>
</ul>
<h3 id="development-workflow-integration">Development Workflow Integration</h3>
<p>Works with your existing tools:</p>
<ul>
<li><strong>Git integration</strong> - Understands version control context</li>
<li><strong>File operations</strong> - Reads, writes, and modifies files</li>
<li><strong>Build tools</strong> - Runs tests, builds, and other project commands</li>
<li><strong>IDE compatibility</strong> - Works alongside your favorite editor</li>
</ul>
<h2 id="your-first-productive-session">Your First Productive Session</h2>
<p><strong>Start with exploration:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;Walk me through the main components of this React application&quot;</span></span>
<span class="line"><span>&quot;Show me how authentication is currently handled&quot;</span></span>
<span class="line"><span>&quot;What testing patterns are used in this project?&quot;</span></span></code></pre>
<p><strong>Move to practical tasks:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;Add error handling to the user registration form&quot;</span></span>
<span class="line"><span>&quot;Create a new component for displaying user notifications&quot;</span></span>
<span class="line"><span>&quot;Fix the TypeScript errors in the payment module&quot;</span></span></code></pre>
<p><strong>Collaborate on bigger features:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>&quot;Help me plan and implement a user dashboard feature&quot;</span></span>
<span class="line"><span>&quot;Review and refactor the API service layer&quot;</span></span>
<span class="line"><span>&quot;Add comprehensive logging to the authentication flow&quot;</span></span></code></pre>
<h2 id="best-practices-for-new-users">Best Practices for New Users</h2>
<h3 id="start-small">Start Small</h3>
<ul>
<li>Begin with simple, isolated tasks</li>
<li>Test Claude’s understanding with questions</li>
<li>Gradually increase task complexity</li>
</ul>
<h3 id="provide-context">Provide Context</h3>
<ul>
<li>Explain your project’s purpose and users</li>
<li>Share relevant business requirements</li>
<li>Mention any constraints or preferences</li>
</ul>
<h3 id="review-everything">Review Everything</h3>
<ul>
<li>Always review generated code before using it</li>
<li>Test changes in development environment</li>
<li>Understand what Claude built, don’t just copy-paste</li>
</ul>
<h3 id="iterate-and-improve">Iterate and Improve</h3>
<ul>
<li>Ask follow-up questions for clarification</li>
<li>Request modifications when something isn’t quite right</li>
<li>Build on previous work in the same conversation</li>
</ul>
<h2 id="common-beginner-questions">Common Beginner Questions</h2>
<p><strong>Q: How much of my code can Claude see?</strong>
A: Claude can read any files in your project directory when needed, but only accesses files relevant to your current task.</p>
<p><strong>Q: Will Claude make changes without asking?</strong>
A: Claude asks for permission before modifying files and shows you exactly what changes it will make.</p>
<p><strong>Q: Can Claude learn my project’s specific patterns?</strong>
A: Yes! Claude learns your coding style, architecture patterns, and project conventions through analysis and your feedback.</p>
<p><strong>Q: Is my code sent to external servers?</strong>
A: Claude Code follows Anthropic’s privacy policies. Check the latest privacy documentation for specifics about data handling.</p>
<h2 id="troubleshooting-common-issues">Troubleshooting Common Issues</h2>
<p><strong>“Command not found” error:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Try using npx instead</span></span>
<span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> @anthropic-ai/claude-code</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Or check your PATH</span></span>
<span class="line"><span style="color:#79B8FF">echo</span><span style="color:#E1E4E8"> $PATH</span></span></code></pre>
<p><strong>Claude seems confused about my project:</strong></p>
<ul>
<li>Make sure you’re in the correct directory</li>
<li>Try asking specific questions about visible files</li>
<li>Provide more context about your project structure</li>
</ul>
<p><strong>Authentication issues:</strong></p>
<ul>
<li>Check your internet connection</li>
<li>Try logging out and back in: <code>claude logout</code> then <code>claude login</code></li>
</ul>
<h2 id="whats-next">What’s Next?</h2>
<p>Now that you have Claude Code running, you’re ready to explore deeper features:</p>
<ul>
<li><strong>Project Configuration</strong> - Learn how to customize Claude for your specific project</li>
<li><strong>Advanced Commands</strong> - Discover powerful built-in commands</li>
<li><strong>Workflow Integration</strong> - Connect Claude with your development tools</li>
</ul>
<p>The goal is to move from “Claude as a tool” to “Claude as a teammate” - an AI partner that understands your project deeply and helps you build better software faster.</p>
<hr/>
<h2 id="claude-code-blog-series">Claude Code Blog Series</h2>
<p>This is Part 1 of our comprehensive Claude Code guide series. Each post builds on the previous ones, taking you from beginner to power user.</p>
<p><strong>Next:</strong> <a href="./2025-07-31--claude-code-part-2-claude-md-configuration">Part 2 - CLAUDE.md Configuration Files</a></p>
<p><strong>Full Series:</strong></p>
<ol>
<li>Part 1 - Getting Started and Installation (this post)</li>
<li>Part 2 - CLAUDE.md Configuration Files</li>
<li>Part 3 - Conversation Management and Context</li>
<li>Part 4 - Slash Commands and Custom Commands</li>
<li>Part 5 - MCP Servers and Tool Integration</li>
<li>Part 6 - Subagents and Task Delegation</li>
<li>Part 7 - IDE Integration with VS Code and JetBrains</li>
<li>Part 8 - Hooks for Automated Quality Checks</li>
<li>Part 9 - Complete Development Workflows</li>
<li>Part 10 - Power User CLI Options and Scripting</li>
<li>Part 11 - Troubleshooting and Recovery</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Understand the Acronym Spaghetti: Part 3 - SOLID Principles</title>
      <link>https://letanure.dev/writing/understand-acronym-spaghetti-part-3-solid-principles/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/understand-acronym-spaghetti-part-3-solid-principles/</guid>
      <pubDate>Sun, 20 Jul 2025 00:00:00 GMT</pubDate>
      <description>Master the SOLID principles for clean architecture in React and Node.js. Learn Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion with practical examples.</description>
      <content:encoded><![CDATA[<h1 id="understand-the-acronym-spaghetti-part-3---solid-principles">Understand the Acronym Spaghetti: Part 3 - SOLID Principles</h1>
<h2 id="tldr">TLDR</h2>
<ul>
<li><strong>Single Responsibility</strong>: Each function should do one thing well</li>
<li><strong>Open/Closed</strong>: Add new features without changing existing code</li>
<li><strong>Liskov Substitution</strong>: Replacements should work the same way</li>
<li><strong>Interface Segregation</strong>: Don’t force unused dependencies</li>
<li><strong>Dependency Inversion</strong>: Depend on contracts, not implementations</li>
</ul>
<hr/>
<p>In <a href="./2025-07-18--understand-acronym-spaghetti-wtf-to-solid-code">Part 1</a>, we covered <strong>The Foundation</strong> - core principles, and in <a href="./2025-07-19--understand-acronym-spaghetti-part-2-quality-principles">Part 2</a>, we explored <strong>Code Quality &amp; Safety</strong> principles.</p>
<p><strong>SOLID Architecture</strong> principles are about the big picture - how to structure systems that can grow and evolve over time. While SOLID comes from object-oriented programming, these patterns apply to React components, Node.js modules, and modern JavaScript applications.</p>
<h2 id="solid-principles-deep-dive">SOLID Principles Deep Dive</h2>
<p>SOLID is the foundation of object-oriented architecture. These 5 principles work together to create flexible, maintainable systems.</p>
<h3 id="solid">SOLID</h3>
<p><em>Also known as: The 5 OOP Principles</em></p>
<p><strong>Definition:</strong> 5 OOP principles for clean architecture: <strong>S</strong>ingle Responsibility, <strong>O</strong>pen/Closed, <strong>L</strong>iskov Substitution, <strong>I</strong>nterface Segregation, <strong>D</strong>ependency Inversion.</p>
<p><strong>Why it matters:</strong> Creates flexible, maintainable systems that can evolve without breaking existing code.</p>
<p><strong>When to break this rule:</strong> Simple applications where the overhead of full SOLID compliance outweighs the benefits.</p>
<p><strong>Note:</strong> We covered <strong>S</strong>ingle Responsibility Principle in <a href="./2025-07-18--understand-acronym-spaghetti-wtf-to-solid-code">Part 1</a>. Here are the other 4 principles:</p>
<h4 id="openclosed-principle-ocp">Open/Closed Principle (OCP)</h4>
<p><em>Open for extension, closed for modification</em></p>
<p><strong>Simple explanation:</strong> You should be able to add new features without changing existing code.</p>
<p><strong>React component example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Must modify existing code to add new behavior</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> WelcomeNotification</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">user</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> getMessage</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    if</span><span style="color:#E1E4E8"> (user.type </span><span style="color:#F97583">===</span><span style="color:#9ECBFF"> &#39;premium&#39;</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">      return</span><span style="color:#9ECBFF"> &#39;Welcome Premium User!&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">    } </span><span style="color:#F97583">else</span><span style="color:#F97583"> if</span><span style="color:#E1E4E8"> (user.type </span><span style="color:#F97583">===</span><span style="color:#9ECBFF"> &#39;basic&#39;</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">      return</span><span style="color:#9ECBFF"> &#39;Welcome!&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#6A737D">    // To add &#39;enterprise&#39; - must modify this function</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;{</span><span style="color:#B392F0">getMessage</span><span style="color:#E1E4E8">()}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Can extend without modifying existing code</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> welcomeStrategies</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  premium</span><span style="color:#E1E4E8">: (</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#9ECBFF"> `Welcome ${</span><span style="color:#E1E4E8">user</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">name</span><span style="color:#9ECBFF">}! Enjoy your premium features.`</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#B392F0">  basic</span><span style="color:#E1E4E8">: (</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#9ECBFF"> `Welcome ${</span><span style="color:#E1E4E8">user</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">name</span><span style="color:#9ECBFF">}!`</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#B392F0">  enterprise</span><span style="color:#E1E4E8">: (</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#9ECBFF"> `Welcome ${</span><span style="color:#E1E4E8">user</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">name</span><span style="color:#9ECBFF">}! Your enterprise dashboard awaits.`</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> WelcomeNotification</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">user</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> strategy</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> welcomeStrategies[user.type] </span><span style="color:#F97583">||</span><span style="color:#E1E4E8"> welcomeStrategies.basic;</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;{</span><span style="color:#B392F0">strategy</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#E1E4E8">)}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Node.js API example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Must modify to add new user types</span></span>
<span class="line"><span style="color:#E1E4E8">app.</span><span style="color:#B392F0">post</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;/api/welcome&#39;</span><span style="color:#E1E4E8">, (</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">user</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> req.body;</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (user.type </span><span style="color:#F97583">===</span><span style="color:#9ECBFF"> &#39;premium&#39;</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#6A737D">    // Premium welcome logic</span></span>
<span class="line"><span style="color:#E1E4E8">  } </span><span style="color:#F97583">else</span><span style="color:#F97583"> if</span><span style="color:#E1E4E8"> (user.type </span><span style="color:#F97583">===</span><span style="color:#9ECBFF"> &#39;basic&#39;</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#6A737D">    // Basic welcome logic</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#6A737D">  // To add &#39;enterprise&#39; - must modify this endpoint</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Extensible without modification</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> welcomeHandlers</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  premium</span><span style="color:#E1E4E8">: </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    await</span><span style="color:#E1E4E8"> emailService.</span><span style="color:#B392F0">sendPremiumWelcome</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#B392F0">  basic</span><span style="color:#E1E4E8">: </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    await</span><span style="color:#E1E4E8"> emailService.</span><span style="color:#B392F0">sendBasicWelcome</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">app.</span><span style="color:#B392F0">post</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;/api/welcome&#39;</span><span style="color:#E1E4E8">, </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">user</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> req.body;</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> handler</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> welcomeHandlers[user.type] </span><span style="color:#F97583">||</span><span style="color:#E1E4E8"> welcomeHandlers.basic;</span></span>
<span class="line"><span style="color:#F97583">  await</span><span style="color:#B392F0"> handler</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"><span style="color:#E1E4E8">  res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">({ success: </span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<h4 id="liskov-substitution-principle-lsp">Liskov Substitution Principle (LSP)</h4>
<p><em>Subtypes must be substitutable for their base types</em></p>
<p><strong>Simple explanation:</strong> If you have different implementations of the same interface, you should be able to swap them without breaking anything.</p>
<p><strong>React component example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Different components with inconsistent interfaces</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> BasicButton</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">label</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">onClick</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">label</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">; </span><span style="color:#B392F0">onClick</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#79B8FF"> void</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">button</span><span style="color:#B392F0"> onClick</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">onClick</span><span style="color:#E1E4E8">}&gt;{label}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">button</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> PremiumButton</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span></span>
<span class="line"><span style="color:#E1E4E8">  label, </span></span>
<span class="line"><span style="color:#E1E4E8">  onClick, </span></span>
<span class="line"><span style="color:#E1E4E8">  theme </span></span>
<span class="line"><span style="color:#E1E4E8">}</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span></span>
<span class="line"><span style="color:#FFAB70">  label</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">; </span></span>
<span class="line"><span style="color:#B392F0">  onClick</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">event</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> any</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#79B8FF"> void</span><span style="color:#E1E4E8">; </span><span style="color:#6A737D">// Different signature!</span></span>
<span class="line"><span style="color:#FFAB70">  theme</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">; </span><span style="color:#6A737D">// Extra required prop!</span></span>
<span class="line"><span style="color:#E1E4E8">}) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">button</span><span style="color:#B392F0"> className</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">theme</span><span style="color:#E1E4E8">} </span><span style="color:#B392F0">onClick</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">onClick</span><span style="color:#E1E4E8">}&gt;{label}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">button</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Consistent interfaces - can be swapped freely</span></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> ButtonProps</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  label</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#B392F0">  onClick</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#79B8FF"> void</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  theme</span><span style="color:#F97583">?:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> BasicButton</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">label</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">onClick</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">theme</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> &#39;default&#39;</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#B392F0"> ButtonProps</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">button</span><span style="color:#B392F0"> className</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">theme</span><span style="color:#E1E4E8">} </span><span style="color:#B392F0">onClick</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">onClick</span><span style="color:#E1E4E8">}&gt;{label}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">button</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> PremiumButton</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">label</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">onClick</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">theme</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> &#39;premium&#39;</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#B392F0"> ButtonProps</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">button</span><span style="color:#B392F0"> className</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">theme</span><span style="color:#E1E4E8">} </span><span style="color:#B392F0">onClick</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">onClick</span><span style="color:#E1E4E8">}&gt;{label}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">button</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Node.js service example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Services with inconsistent interfaces</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> basicEmailService</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  send</span><span style="color:#E1E4E8">: (</span><span style="color:#FFAB70">to</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">subject</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">body</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">    // Send basic email</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> premiumEmailService</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  send</span><span style="color:#E1E4E8">: (</span><span style="color:#FFAB70">to</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">subject</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">body</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">priority</span><span style="color:#F97583">:</span><span style="color:#9ECBFF"> &#39;high&#39;</span><span style="color:#F97583"> |</span><span style="color:#9ECBFF"> &#39;low&#39;</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">    // Requires extra parameter - breaks substitution</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Consistent interfaces - can be swapped freely</span></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> EmailService</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  send</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">to</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">subject</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">body</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">options</span><span style="color:#F97583">?:</span><span style="color:#79B8FF"> any</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#79B8FF">void</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> basicEmailService</span><span style="color:#F97583">:</span><span style="color:#B392F0"> EmailService</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  send</span><span style="color:#E1E4E8">: </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">to</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">subject</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">body</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">    // Send basic email</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> premiumEmailService</span><span style="color:#F97583">:</span><span style="color:#B392F0"> EmailService</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  send</span><span style="color:#E1E4E8">: </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">to</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">subject</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">body</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">options</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {}) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">    // Send premium email with optional features</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<h4 id="interface-segregation-principle-isp">Interface Segregation Principle (ISP)</h4>
<p><em>Clients shouldn’t depend on interfaces they don’t use</em></p>
<p><strong>Simple explanation:</strong> Don’t force a component or function to depend on methods it doesn’t need. Make small, focused interfaces instead of big ones.</p>
<p><strong>React component example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Fat interface - component forced to depend on methods it doesn&#39;t use</span></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> UserService</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  getUser</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">User</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#B392F0">  createUser</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">data</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> any</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">User</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#B392F0">  deleteUser</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#79B8FF">void</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#B392F0">  generateReport</span><span style="color:#E1E4E8">()</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#79B8FF">string</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#B392F0">  sendNotifications</span><span style="color:#E1E4E8">()</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#79B8FF">void</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> UserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ userId, userService }: { </span></span>
<span class="line"><span style="color:#E1E4E8">  userId: string; </span></span>
<span class="line"><span style="color:#E1E4E8">  userService: UserService; </span><span style="color:#6A737D">// Depends on methods it doesn&#39;t need</span></span>
<span class="line"><span style="color:#E1E4E8">}) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">user</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setUser</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">null</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#B392F0">  useEffect</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">    userService.</span><span style="color:#B392F0">getUser</span><span style="color:#E1E4E8">(userId).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(setUser); </span><span style="color:#6A737D">// Only uses getUser</span></span>
<span class="line"><span style="color:#E1E4E8">  }, [userId]);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;{user?.name}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Focused interfaces - components only depend on what they need</span></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> UserReader</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  getUser</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">User</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> UserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ userId, userReader }: { </span></span>
<span class="line"><span style="color:#E1E4E8">  userId: string; </span></span>
<span class="line"><span style="color:#E1E4E8">  userReader: UserReader; </span><span style="color:#6A737D">// Only depends on reading</span></span>
<span class="line"><span style="color:#E1E4E8">}) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">user</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setUser</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">null</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#B392F0">  useEffect</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">    userReader.</span><span style="color:#B392F0">getUser</span><span style="color:#E1E4E8">(userId).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(setUser); </span><span style="color:#6A737D">// Clear dependency</span></span>
<span class="line"><span style="color:#E1E4E8">  }, [userId]);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;{user?.name}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Node.js API example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Fat service interface</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> userController</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  getProfile</span><span style="color:#E1E4E8">: </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">userService</span><span style="color:#F97583">:</span><span style="color:#B392F0"> UserService</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> userService.</span><span style="color:#B392F0">getUser</span><span style="color:#E1E4E8">(req.params.id); </span><span style="color:#6A737D">// Only needs getUser</span></span>
<span class="line"><span style="color:#E1E4E8">    res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Focused service dependencies</span></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> UserReader</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  getUser</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">User</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> UserWriter</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  createUser</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">data</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> any</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">User</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#B392F0">  updateUser</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">data</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> any</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">User</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> userController</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  getProfile</span><span style="color:#E1E4E8">: </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">userReader</span><span style="color:#F97583">:</span><span style="color:#B392F0"> UserReader</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> userReader.</span><span style="color:#B392F0">getUser</span><span style="color:#E1E4E8">(req.params.id);</span></span>
<span class="line"><span style="color:#E1E4E8">    res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#B392F0">  updateProfile</span><span style="color:#E1E4E8">: </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">userWriter</span><span style="color:#F97583">:</span><span style="color:#B392F0"> UserWriter</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> userWriter.</span><span style="color:#B392F0">updateUser</span><span style="color:#E1E4E8">(req.params.id, req.body);</span></span>
<span class="line"><span style="color:#E1E4E8">    res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<h4 id="dependency-inversion-principle-dip">Dependency Inversion Principle (DIP)</h4>
<p><em>Depend on abstractions, not concretions</em></p>
<p><strong>Simple explanation:</strong> Don’t depend on specific implementations. Depend on interfaces so you can easily swap out different implementations.</p>
<p><strong>Why “inversion”?</strong> Traditionally, high-level modules (business logic) depend on low-level modules (database, file system). DIP inverts this - both should depend on abstractions.</p>
<p><strong>Node.js service example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Traditional dependency flow - high-level depends on low-level</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserService</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> saveUser</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">    // Direct dependency on specific implementations</span></span>
<span class="line"><span style="color:#F97583">    await</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;/api/mysql/users&#39;</span><span style="color:#E1E4E8">, { </span><span style="color:#6A737D">// Hard-coded to MySQL API</span></span>
<span class="line"><span style="color:#E1E4E8">      method: </span><span style="color:#9ECBFF">&#39;POST&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">      body: </span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">(user)</span></span>
<span class="line"><span style="color:#E1E4E8">    });</span></span>
<span class="line"><span style="color:#E1E4E8">    </span></span>
<span class="line"><span style="color:#E1E4E8">    console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;User saved&#39;</span><span style="color:#E1E4E8">); </span><span style="color:#6A737D">// Hard-coded to console logging</span></span>
<span class="line"><span style="color:#6A737D">    // Hard to test, hard to change database or logger</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> { saveUser };</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Inverted dependencies - both depend on abstractions</span></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> Database</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  save</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#79B8FF">void</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> Logger</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  log</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">message</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> void</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> createUserService</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">db</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Database</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">logger</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Logger</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> saveUser</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    await</span><span style="color:#E1E4E8"> db.</span><span style="color:#B392F0">save</span><span style="color:#E1E4E8">(user); </span><span style="color:#6A737D">// Depends on abstraction</span></span>
<span class="line"><span style="color:#E1E4E8">    logger.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;User saved&#39;</span><span style="color:#E1E4E8">); </span><span style="color:#6A737D">// Depends on abstraction</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> { saveUser };</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// Easy to test with mocks, easy to swap implementations</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> userService</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> createUserService</span><span style="color:#E1E4E8">(mysqlDatabase, consoleLogger);</span></span></code></pre>
<p><strong>React component example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Component with hard-coded dependencies</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserForm</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">user</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setUser</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">({});</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> handleSubmit</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">    // Direct dependency on specific API endpoint</span></span>
<span class="line"><span style="color:#F97583">    await</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;/api/users&#39;</span><span style="color:#E1E4E8">, {</span></span>
<span class="line"><span style="color:#E1E4E8">      method: </span><span style="color:#9ECBFF">&#39;POST&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">      body: </span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">(user)</span></span>
<span class="line"><span style="color:#E1E4E8">    });</span></span>
<span class="line"><span style="color:#E1E4E8">    </span></span>
<span class="line"><span style="color:#6A737D">    // Direct dependency on specific analytics service</span></span>
<span class="line"><span style="color:#B392F0">    gtag</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;event&#39;</span><span style="color:#E1E4E8">, </span><span style="color:#9ECBFF">&#39;user_created&#39;</span><span style="color:#E1E4E8">, { user_id: user.id });</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">form</span><span style="color:#B392F0"> onSubmit</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">handleSubmit</span><span style="color:#E1E4E8">}&gt;</span><span style="color:#F97583">...&lt;/</span><span style="color:#E1E4E8">form</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Component depends on abstractions</span></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> UserService</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  saveUser</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#79B8FF">void</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> Analytics</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  track</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">event</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">data</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> any</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> void</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> UserForm</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ userService, analytics }: { </span></span>
<span class="line"><span style="color:#E1E4E8">  userService: UserService;</span></span>
<span class="line"><span style="color:#E1E4E8">  analytics: Analytics;</span></span>
<span class="line"><span style="color:#E1E4E8">}) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">user</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setUser</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">({});</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> handleSubmit</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    await</span><span style="color:#E1E4E8"> userService.</span><span style="color:#B392F0">saveUser</span><span style="color:#E1E4E8">(user); </span><span style="color:#6A737D">// Depends on abstraction</span></span>
<span class="line"><span style="color:#E1E4E8">    analytics.</span><span style="color:#B392F0">track</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;user_created&#39;</span><span style="color:#E1E4E8">, { user_id: user.id }); </span><span style="color:#6A737D">// Depends on abstraction</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">form</span><span style="color:#B392F0"> onSubmit</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">handleSubmit</span><span style="color:#E1E4E8">}&gt;</span><span style="color:#F97583">...&lt;/</span><span style="color:#E1E4E8">form</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Benefits:</strong></p>
<ul>
<li><strong>Testability</strong>: Inject mocks for testing</li>
<li><strong>Flexibility</strong>: Swap implementations without changing business logic</li>
<li><strong>Maintainability</strong>: Changes to low-level modules don’t affect high-level modules</li>
</ul>
<p><strong>Common Pitfall:</strong> Trying to apply all SOLID principles at once instead of gradually refactoring towards them as the system grows.</p>
<hr/>
<h2 id="summary">Summary</h2>
<p><strong>SOLID principles</strong> are the foundation of good object-oriented design. They work together to create systems that are:</p>
<ul>
<li><strong>Flexible</strong>: Easy to extend and modify</li>
<li><strong>Testable</strong>: Components can be tested in isolation</li>
<li><strong>Maintainable</strong>: Changes don’t ripple through the entire system</li>
</ul>
<p>Start with <strong>Single Responsibility</strong> and <strong>Dependency Inversion</strong> - these give you the biggest bang for your buck.</p>
<p><strong>Coming next:</strong> <a href="./2025-07-21--understand-acronym-spaghetti-part-4-cqrs-and-hexagonal">Part 4</a> covers <strong>System Architecture</strong> patterns like CQRS and Hexagonal Architecture, and <a href="./2025-07-22--understand-acronym-spaghetti-part-5-advanced-principles">Part 5</a> explores <strong>Advanced Principles</strong> for elegant code.</p>
<p>Remember: <strong>good architecture is not about following every pattern - it’s about making intentional choices that serve your specific needs.</strong></p>]]></content:encoded>
    </item>
    <item>
      <title>Understand the Acronym Spaghetti: Part 4 - CQRS and Hexagonal Architecture</title>
      <link>https://letanure.dev/writing/understand-acronym-spaghetti-part-4-cqrs-and-hexagonal/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/understand-acronym-spaghetti-part-4-cqrs-and-hexagonal/</guid>
      <pubDate>Sun, 20 Jul 2025 00:00:00 GMT</pubDate>
      <description>Apply CQRS and Hexagonal Architecture in React and Node.js. Learn when to separate queries from commands and how to structure frontend applications for maintainability.</description>
      <content:encoded><![CDATA[<h1 id="understand-the-acronym-spaghetti-part-4---cqrs-and-hexagonal-architecture">Understand the Acronym Spaghetti: Part 4 - CQRS and Hexagonal Architecture</h1>
<h2 id="tldr">TLDR</h2>
<ul>
<li><strong>CQRS</strong>: Separate read/write operations for better performance</li>
<li><strong>Hexagonal Architecture</strong>: Isolate business logic from external services</li>
</ul>
<hr/>
<p>In <a href="./2025-07-20--understand-acronym-spaghetti-part-3-solid-principles">Part 3</a>, we covered <strong>SOLID Architecture</strong> principles. Now let’s explore <strong>System Architecture</strong> patterns that help you build systems that can scale and evolve.</p>
<h2 id="system-architecture-patterns">System Architecture Patterns</h2>
<p>These patterns help you structure React applications and Node.js APIs, moving beyond single components to system-wide organization.</p>
<h3 id="cqrs-command-query-responsibility-segregation">CQRS (Command Query Responsibility Segregation)</h3>
<p><strong>Definition:</strong> Separate read operations (queries) from write operations (commands). In React/Node.js, this means different hooks, API endpoints, and state management for reading vs writing data.</p>
<p><strong>Simple explanation:</strong> Don’t use the same code path for getting data and changing data. They have different needs and performance requirements.</p>
<p><strong>Why it matters:</strong> Read and write operations have different performance characteristics, caching needs, and error handling. Separating them allows each to be optimized independently.</p>
<p><strong>When to use:</strong></p>
<ul>
<li>Complex forms with heavy validation</li>
<li>Different permissions for reading vs writing</li>
<li>Performance-critical apps where reads and writes need different optimization</li>
<li>Large teams where query logic and mutation logic change at different rates</li>
</ul>
<p><strong>When NOT to use:</strong></p>
<ul>
<li>Simple CRUD operations where read/write are basically the same</li>
<li>Small applications where the separation adds unnecessary complexity</li>
<li>Prototypes or MVPs where you need to move fast</li>
</ul>
<p><strong>React custom hook example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Mixed read/write operations - same hook for everything</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> useUser</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">userId</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">user</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setUser</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">null</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">loading</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setLoading</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">false</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> fetchUser</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">    setLoading</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#6A737D">    // Complex query with joins and calculations</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> response</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#9ECBFF">      `/api/users/${</span><span style="color:#E1E4E8">userId</span><span style="color:#9ECBFF">}?include=profile,stats,preferences`</span></span>
<span class="line"><span style="color:#E1E4E8">    );</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> userData</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> response.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#B392F0">    setUser</span><span style="color:#E1E4E8">(userData);</span></span>
<span class="line"><span style="color:#B392F0">    setLoading</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">false</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> updateUser</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">data</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> any</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">    setLoading</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#6A737D">    // Uses same complex endpoint for simple updates</span></span>
<span class="line"><span style="color:#F97583">    await</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`/api/users/${</span><span style="color:#E1E4E8">userId</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">, {</span></span>
<span class="line"><span style="color:#E1E4E8">      method: </span><span style="color:#9ECBFF">&quot;PUT&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">      body: </span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">(data),</span></span>
<span class="line"><span style="color:#E1E4E8">    });</span></span>
<span class="line"><span style="color:#6A737D">    // Re-fetches complex data after simple update</span></span>
<span class="line"><span style="color:#F97583">    await</span><span style="color:#B392F0"> fetchUser</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#B392F0">    setLoading</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">false</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> { user, loading, updateUser, fetchUser };</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Separated read and write hooks</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> useUserQuery</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">userId</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#B392F0"> useQuery</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">    queryKey: [</span><span style="color:#9ECBFF">&quot;user&quot;</span><span style="color:#E1E4E8">, userId],</span></span>
<span class="line"><span style="color:#B392F0">    queryFn</span><span style="color:#E1E4E8">: () </span><span style="color:#F97583">=&gt;</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`/api/users/${</span><span style="color:#E1E4E8">userId</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">()),</span></span>
<span class="line"><span style="color:#E1E4E8">  });</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> useUserMutation</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#B392F0"> useMutation</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#B392F0">    mutationFn</span><span style="color:#E1E4E8">: ({ </span><span style="color:#FFAB70">userId</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">data</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">userId</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">; </span><span style="color:#FFAB70">data</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> any</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span></span>
<span class="line"><span style="color:#B392F0">      fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`/api/users/${</span><span style="color:#E1E4E8">userId</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">, {</span></span>
<span class="line"><span style="color:#E1E4E8">        method: </span><span style="color:#9ECBFF">&quot;PUT&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">        body: </span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">(data),</span></span>
<span class="line"><span style="color:#E1E4E8">      }).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">()),</span></span>
<span class="line"><span style="color:#E1E4E8">  });</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>React component example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Component with mixed concerns</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">userId</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">userId</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">user</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">loading</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">updateUser</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useUser</span><span style="color:#E1E4E8">(userId);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> handleNameChange</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">newName</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">    // Heavy operation for simple field update</span></span>
<span class="line"><span style="color:#F97583">    await</span><span style="color:#B392F0"> updateUser</span><span style="color:#E1E4E8">({ name: newName });</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (loading) </span><span style="color:#F97583">return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;Loading</span><span style="color:#F97583">...&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#B392F0">h1</span><span style="color:#E1E4E8">&gt;{user.name}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">h1</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#B392F0">p</span><span style="color:#E1E4E8">&gt;</span><span style="color:#FFAB70">Followers</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> {</span><span style="color:#B392F0">user</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stats</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">followers</span><span style="color:#E1E4E8">}&lt;/</span><span style="color:#B392F0">p</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#F97583">      &lt;</span><span style="color:#E1E4E8">button onClick</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{() =&gt; </span><span style="color:#B392F0">handleNameChange</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;New Name&quot;</span><span style="color:#E1E4E8">)}</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">Change Name</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">button</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#F97583">    &lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Component with separated concerns</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">userId</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">userId</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">data</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">user</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">isLoading</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useUserQuery</span><span style="color:#E1E4E8">(userId);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> updateUser</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> useUserMutation</span><span style="color:#E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> handleNameChange</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">newName</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">    updateUser.</span><span style="color:#B392F0">mutate</span><span style="color:#E1E4E8">({ userId, data: { name: newName } });</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (isLoading) </span><span style="color:#F97583">return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;Loading</span><span style="color:#F97583">...&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#B392F0">h1</span><span style="color:#E1E4E8">&gt;{user.name}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">h1</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#F97583">      &lt;</span><span style="color:#E1E4E8">button onClick</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{() =&gt; </span><span style="color:#B392F0">handleNameChange</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;New Name&quot;</span><span style="color:#E1E4E8">)}</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">Change Name</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">button</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#F97583">    &lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Node.js API example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Same endpoint for different needs</span></span>
<span class="line"><span style="color:#E1E4E8">app.</span><span style="color:#B392F0">get</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;/api/users/:id&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">  // Heavy query for display</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> db.</span><span style="color:#B392F0">getUserWithStats</span><span style="color:#E1E4E8">(req.params.id);</span></span>
<span class="line"><span style="color:#E1E4E8">  res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">app.</span><span style="color:#B392F0">put</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;/api/users/:id&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">  // Simple update but uses heavy query for validation</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> db.</span><span style="color:#B392F0">getUserWithStats</span><span style="color:#E1E4E8">(req.params.id);</span></span>
<span class="line"><span style="color:#F97583">  await</span><span style="color:#E1E4E8"> db.</span><span style="color:#B392F0">updateUser</span><span style="color:#E1E4E8">(req.params.id, req.body);</span></span>
<span class="line"><span style="color:#E1E4E8">  res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">({ success: </span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Separated by concern</span></span>
<span class="line"><span style="color:#6A737D">// Read endpoint - optimized for display</span></span>
<span class="line"><span style="color:#E1E4E8">app.</span><span style="color:#B392F0">get</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;/api/users/:id/profile&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> db.</span><span style="color:#B392F0">getUserWithStats</span><span style="color:#E1E4E8">(req.params.id);</span></span>
<span class="line"><span style="color:#E1E4E8">  res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// Write endpoint - optimized for updates</span></span>
<span class="line"><span style="color:#E1E4E8">app.</span><span style="color:#B392F0">put</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;/api/users/:id&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> exists</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> db.</span><span style="color:#B392F0">userExists</span><span style="color:#E1E4E8">(req.params.id);</span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">exists) {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">status</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">404</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">({ error: </span><span style="color:#9ECBFF">&quot;User not found&quot;</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  await</span><span style="color:#E1E4E8"> db.</span><span style="color:#B392F0">updateUser</span><span style="color:#E1E4E8">(req.params.id, req.body);</span></span>
<span class="line"><span style="color:#E1E4E8">  res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">({ success: </span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<p><strong>Benefits:</strong></p>
<ul>
<li><strong>Performance</strong>: Reads and writes can be optimized independently</li>
<li><strong>Maintainability</strong>: Query logic and mutation logic can evolve separately</li>
<li><strong>Team Collaboration</strong>: Different developers can work on reads vs writes</li>
</ul>
<p><strong>Common Pitfall:</strong> Over-engineering simple forms where read/write are basically the same operation.</p>
<hr/>
<h3 id="hexagonal-architecture-ports--adapters">Hexagonal Architecture (Ports &amp; Adapters)</h3>
<p><strong>Definition:</strong> Keep business logic separate from external services (databases, APIs). Use interfaces to connect them.</p>
<p><strong>Simple explanation:</strong> Your core logic shouldn’t care where data comes from - database, file, or API.</p>
<p><strong>When to use:</strong> Complex business rules that need testing independently.
<strong>When NOT to use:</strong> Simple CRUD apps or prototypes.</p>
<p><strong>Node.js API tightly coupled to external services</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Business logic mixed with infrastructure</span></span>
<span class="line"><span style="color:#E1E4E8">app.</span><span style="color:#B392F0">post</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;/api/register&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">name</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">email</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> req.body;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">email.</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;@&quot;</span><span style="color:#E1E4E8">)) {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">status</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">400</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">({ error: </span><span style="color:#9ECBFF">&quot;Invalid email&quot;</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">  // Direct dependencies - hard to test</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> existing</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> db.</span><span style="color:#B392F0">findUser</span><span style="color:#E1E4E8">(email);</span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (existing) {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">status</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">409</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">({ error: </span><span style="color:#9ECBFF">&quot;User exists&quot;</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  await</span><span style="color:#E1E4E8"> db.</span><span style="color:#B392F0">createUser</span><span style="color:#E1E4E8">(name, email);</span></span>
<span class="line"><span style="color:#F97583">  await</span><span style="color:#E1E4E8"> emailService.</span><span style="color:#B392F0">sendWelcome</span><span style="color:#E1E4E8">(email);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">  res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">({ success: </span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Core business logic separated from infrastructure</span></span>
<span class="line"><span style="color:#6A737D">// Define interfaces (ports)</span></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> UserRepo</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  findByEmail</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">email</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">User</span><span style="color:#F97583"> |</span><span style="color:#79B8FF"> null</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#B392F0">  save</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">User</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> EmailService</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  sendWelcome</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#79B8FF">void</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// Pure business logic</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> createUserService</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">userRepo</span><span style="color:#F97583">:</span><span style="color:#B392F0"> UserRepo</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">emailService</span><span style="color:#F97583">:</span><span style="color:#B392F0"> EmailService</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> registerUser</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">userData</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">name</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">; </span><span style="color:#FFAB70">email</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    if</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">userData.email.</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;@&quot;</span><span style="color:#E1E4E8">)) {</span></span>
<span class="line"><span style="color:#F97583">      return</span><span style="color:#E1E4E8"> { success: </span><span style="color:#79B8FF">false</span><span style="color:#E1E4E8">, error: </span><span style="color:#9ECBFF">&quot;Invalid email&quot;</span><span style="color:#E1E4E8"> };</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> existing</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> userRepo.</span><span style="color:#B392F0">findByEmail</span><span style="color:#E1E4E8">(userData.email);</span></span>
<span class="line"><span style="color:#F97583">    if</span><span style="color:#E1E4E8"> (existing) {</span></span>
<span class="line"><span style="color:#F97583">      return</span><span style="color:#E1E4E8"> { success: </span><span style="color:#79B8FF">false</span><span style="color:#E1E4E8">, error: </span><span style="color:#9ECBFF">&quot;User exists&quot;</span><span style="color:#E1E4E8"> };</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> userRepo.</span><span style="color:#B392F0">save</span><span style="color:#E1E4E8">(userData);</span></span>
<span class="line"><span style="color:#F97583">    await</span><span style="color:#E1E4E8"> emailService.</span><span style="color:#B392F0">sendWelcome</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> { success: </span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8">, user };</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> { registerUser };</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// HTTP adapter</span></span>
<span class="line"><span style="color:#E1E4E8">app.</span><span style="color:#B392F0">post</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;/api/register&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> userService</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> createUserService</span><span style="color:#E1E4E8">(userRepo, emailService);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> result</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> userService.</span><span style="color:#B392F0">registerUser</span><span style="color:#E1E4E8">(req.body);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (result.success) {</span></span>
<span class="line"><span style="color:#E1E4E8">    res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">({ user: result.user });</span></span>
<span class="line"><span style="color:#E1E4E8">  } </span><span style="color:#F97583">else</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">    res.</span><span style="color:#B392F0">status</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">400</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">({ error: result.error });</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<p><strong>Benefits:</strong></p>
<ul>
<li><strong>Testability</strong>: Test business logic with mocks</li>
<li><strong>Flexibility</strong>: Easy to swap databases or email services</li>
<li><strong>Maintainability</strong>: Business logic isolated from infrastructure</li>
</ul>
<p><strong>Common Pitfall:</strong> Over-architecting simple applications.</p>
<h2 id="summary">Summary</h2>
<p><strong>CQRS and Hexagonal Architecture</strong> are powerful patterns for structuring React and Node.js applications. They help you build systems that can scale, evolve, and remain testable as they grow.</p>
<p><strong>CQRS</strong> helps you optimize reads and writes independently - perfect for React Query patterns and API design.</p>
<p><strong>Hexagonal Architecture</strong> keeps your business logic pure and testable - ideal for complex applications with multiple integrations.</p>
<p>Both patterns build on the SOLID principles from <a href="./2025-07-20--understand-acronym-spaghetti-part-3-solid-principles">Part 3</a> and help you create systems that can adapt to future needs without major rewrites.</p>
<p><strong>Coming next:</strong> <a href="./2025-07-22--understand-acronym-spaghetti-part-5-advanced-principles">Part 5</a> covers <strong>Advanced Principles</strong> - the subtle patterns that separate good developers from great ones.</p>
<p>Remember: <strong>architecture is about trade-offs - choose patterns that solve your specific problems, not just because they’re trendy.</strong></p>]]></content:encoded>
    </item>
    <item>
      <title>Understand the Acronym Spaghetti: Part 5 - Advanced Principles</title>
      <link>https://letanure.dev/writing/understand-acronym-spaghetti-part-5-advanced-principles/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/understand-acronym-spaghetti-part-5-advanced-principles/</guid>
      <pubDate>Sun, 20 Jul 2025 00:00:00 GMT</pubDate>
      <description>Master the final set of programming principles: Law of Demeter, Composition over Inheritance, Tell Don&apos;t Ask, Convention over Configuration, and Principle of Least Astonishment. Advanced patterns for React and...</description>
      <content:encoded><![CDATA[<h1 id="understand-the-acronym-spaghetti-part-5---advanced-principles">Understand the Acronym Spaghetti: Part 5 - Advanced Principles</h1>
<h2 id="tldr">TLDR</h2>
<ul>
<li><strong>Law of Demeter</strong>: Avoid deep object chaining</li>
<li><strong>Composition over Inheritance</strong>: Combine small parts instead of extending classes</li>
<li><strong>Tell Don’t Ask</strong>: Let objects manage their own state</li>
<li><strong>Convention over Configuration</strong>: Smart defaults over explicit setup</li>
<li><strong>Principle of Least Astonishment</strong>: Behave as users expect</li>
</ul>
<hr/>
<p>We’ve covered <strong>The Foundation</strong> in <a href="./2025-07-18--understand-acronym-spaghetti-wtf-to-solid-code">Part 1</a>, <strong>Code Quality &amp; Safety</strong> in <a href="./2025-07-19--understand-acronym-spaghetti-part-2-quality-principles">Part 2</a>, <strong>SOLID Architecture</strong> in <a href="./2025-07-20--understand-acronym-spaghetti-part-3-solid-principles">Part 3</a>, and <strong>System Architecture</strong> in <a href="./2025-07-21--understand-acronym-spaghetti-part-4-cqrs-and-hexagonal">Part 4</a>.</p>
<p><strong>Advanced Principles</strong> are the subtle patterns that separate good developers from great ones. These make code truly elegant and maintainable.</p>
<h2 id="advanced-principles">Advanced Principles</h2>
<p>These principles help you write code that’s not just functional, but intuitive and pleasant to work with.</p>
<h3 id="law-of-demeter-dont-talk-to-strangers">Law of Demeter (Don’t Talk to Strangers)</h3>
<p><strong>Definition:</strong> A function should only talk to its immediate friends - don’t reach through objects to talk to their friends.</p>
<p><strong>Simple explanation:</strong> Avoid chaining calls like <code>user.profile.settings.theme.color</code>. Each object should only know about its direct dependencies.</p>
<p><strong>Why it matters:</strong> Reduces coupling, makes code less fragile to changes, and prevents the “breaking chain” problem where changes deep in the structure break code far away.</p>
<p><strong>When to use:</strong></p>
<ul>
<li>Complex object hierarchies</li>
<li>API design where you want to prevent tight coupling</li>
<li>Component props design to avoid props drilling</li>
</ul>
<p><strong>When NOT to use:</strong></p>
<ul>
<li>Simple utility functions or data transformations</li>
<li>Well-established patterns like <code>array.map().filter()</code></li>
<li>Configuration objects where chaining is expected</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Violates Law of Demeter - too much chaining</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">user</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#B392F0">h1</span><span style="color:#E1E4E8">&gt;{user.profile.name}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">h1</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#F97583">      &lt;</span><span style="color:#E1E4E8">p style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{ </span><span style="color:#B392F0">color</span><span style="color:#E1E4E8">: user.settings.theme.color }}</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#FFAB70">        Posts</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> {</span><span style="color:#B392F0">user</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">profile</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stats</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">posts</span><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#F97583">      &lt;/</span><span style="color:#E1E4E8">p</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#F97583">    &lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Follows Law of Demeter - service handles deep access</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> getUserDisplayData</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">    name: user.</span><span style="color:#B392F0">getName</span><span style="color:#E1E4E8">(),</span></span>
<span class="line"><span style="color:#E1E4E8">    textColor: user.</span><span style="color:#B392F0">getThemeColor</span><span style="color:#E1E4E8">(),</span></span>
<span class="line"><span style="color:#E1E4E8">    postCount: user.</span><span style="color:#B392F0">getPostCount</span><span style="color:#E1E4E8">(),</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">user</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">name</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">textColor</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">postCount</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#B392F0"> getUserDisplayData</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#B392F0">h1</span><span style="color:#E1E4E8">&gt;{name}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">h1</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#F97583">      &lt;</span><span style="color:#E1E4E8">p style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{ </span><span style="color:#B392F0">color</span><span style="color:#E1E4E8">: textColor }}</span><span style="color:#F97583">&gt;</span><span style="color:#FFAB70">Posts</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> {</span><span style="color:#FFAB70">postCount</span><span style="color:#E1E4E8">}&lt;/</span><span style="color:#B392F0">p</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#F97583">    &lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Benefits:</strong></p>
<ul>
<li><strong>Maintainability</strong>: Changes to deep objects don’t break surface code</li>
<li><strong>Testability</strong>: Easier to mock and test components</li>
</ul>
<p><strong>Common Pitfall:</strong> Creating unnecessary wrapper functions for simple property access.</p>
<hr/>
<h3 id="composition-over-inheritance">Composition over Inheritance</h3>
<p><strong>Definition:</strong> Build complex functionality by combining simple components rather than creating complex inheritance hierarchies.</p>
<p><strong>Simple explanation:</strong> Instead of creating a “BaseComponent” that others extend, create small, focused components that can be combined in different ways.</p>
<p><strong>Why it matters:</strong> More flexible, easier to test, and avoids the “fragile base class” problem where changes to parent classes break child classes.</p>
<p><strong>When to use:</strong></p>
<ul>
<li>React component design patterns</li>
<li>Building reusable UI components</li>
<li>Creating flexible API interfaces</li>
<li>When you need multiple behaviors that can be mixed and matched</li>
</ul>
<p><strong>When NOT to use:</strong></p>
<ul>
<li>Simple cases where inheritance is clearer</li>
<li>Well-established patterns (like extending Error classes)</li>
<li>When you need polymorphism with shared behavior</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Inheritance-heavy approach</span></span>
<span class="line"><span style="color:#F97583">class</span><span style="color:#B392F0"> BaseButton</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  constructor</span><span style="color:#E1E4E8">(</span><span style="color:#F97583">protected</span><span style="color:#FFAB70"> text</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) {}</span></span>
<span class="line"><span style="color:#B392F0">  render</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#9ECBFF"> `&lt;button&gt;${</span><span style="color:#79B8FF">this</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">text</span><span style="color:#9ECBFF">}&lt;/button&gt;`</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">class</span><span style="color:#B392F0"> PrimaryButton</span><span style="color:#F97583"> extends</span><span style="color:#B392F0"> BaseButton</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  render</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#9ECBFF"> `&lt;button class=&quot;primary&quot;&gt;${</span><span style="color:#79B8FF">this</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">text</span><span style="color:#9ECBFF">}&lt;/button&gt;`</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">class</span><span style="color:#B392F0"> LoadingButton</span><span style="color:#F97583"> extends</span><span style="color:#B392F0"> BaseButton</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  constructor</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">text</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#F97583">private</span><span style="color:#FFAB70"> loading</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> boolean</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#79B8FF">    super</span><span style="color:#E1E4E8">(text);</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#B392F0">  render</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#9ECBFF"> `&lt;button disabled=&quot;${</span><span style="color:#79B8FF">this</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">loading</span><span style="color:#9ECBFF">}&quot;&gt;${</span></span>
<span class="line"><span style="color:#79B8FF">      this</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">loading</span><span style="color:#F97583"> ?</span><span style="color:#9ECBFF"> &quot;Loading...&quot;</span><span style="color:#F97583"> :</span><span style="color:#79B8FF"> this</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">text</span></span>
<span class="line"><span style="color:#9ECBFF">    }&lt;/button&gt;`</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ❌ What if we need LoadingPrimaryButton? Multiple inheritance problem!</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Composition approach</span></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> ButtonProps</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  text</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  variant</span><span style="color:#F97583">?:</span><span style="color:#9ECBFF"> &quot;primary&quot;</span><span style="color:#F97583"> |</span><span style="color:#9ECBFF"> &quot;secondary&quot;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  loading</span><span style="color:#F97583">?:</span><span style="color:#79B8FF"> boolean</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#B392F0">  onClick</span><span style="color:#F97583">?:</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#79B8FF"> void</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> Button</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({</span></span>
<span class="line"><span style="color:#E1E4E8">  text,</span></span>
<span class="line"><span style="color:#E1E4E8">  variant </span><span style="color:#F97583">=</span><span style="color:#9ECBFF"> &quot;secondary&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  loading,</span></span>
<span class="line"><span style="color:#E1E4E8">  onClick,</span></span>
<span class="line"><span style="color:#E1E4E8">}</span><span style="color:#F97583">:</span><span style="color:#B392F0"> ButtonProps</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#F97583">    &lt;</span><span style="color:#FFAB70">button</span></span>
<span class="line"><span style="color:#E1E4E8">      className</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#9ECBFF">`button ${</span><span style="color:#E1E4E8">variant</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#E1E4E8">      onClick</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{onClick}</span></span>
<span class="line"><span style="color:#E1E4E8">      disabled</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{loading}</span></span>
<span class="line"><span style="color:#F97583">    &gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      {</span><span style="color:#FFAB70">loading</span><span style="color:#E1E4E8"> ? </span><span style="color:#9ECBFF">&quot;Loading...&quot;</span><span style="color:#E1E4E8"> : </span><span style="color:#FFAB70">text</span><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#F97583">    &lt;/</span><span style="color:#E1E4E8">button</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Easy to combine behaviors</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> PrimaryButton</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">props</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Omit</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">ButtonProps</span><span style="color:#E1E4E8">, </span><span style="color:#9ECBFF">&quot;variant&quot;</span><span style="color:#E1E4E8">&gt;) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#F97583">  &lt;</span><span style="color:#E1E4E8">Button {</span><span style="color:#F97583">...</span><span style="color:#FFAB70">props</span><span style="color:#E1E4E8">} variant</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">&quot;primary&quot;</span><span style="color:#F97583"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> LoadingPrimaryButton</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#FFAB70">  props</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Omit</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">ButtonProps</span><span style="color:#E1E4E8">, </span><span style="color:#9ECBFF">&quot;variant&quot;</span><span style="color:#F97583"> |</span><span style="color:#9ECBFF"> &quot;loading&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">Button</span><span style="color:#E1E4E8"> {</span><span style="color:#F97583">...</span><span style="color:#B392F0">props</span><span style="color:#E1E4E8">} </span><span style="color:#B392F0">variant</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;primary&quot;</span><span style="color:#B392F0"> loading</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">true</span><span style="color:#E1E4E8">} /&gt;;</span></span></code></pre>
<p><strong>Benefits:</strong></p>
<ul>
<li><strong>Flexibility</strong>: Mix and match behaviors as needed</li>
<li><strong>Testability</strong>: Easy to test individual behaviors</li>
</ul>
<p><strong>Common Pitfall:</strong> Creating too many small components when a simple solution would work better.</p>
<hr/>
<h3 id="tell-dont-ask">Tell, Don’t Ask</h3>
<p><strong>Definition:</strong> Objects should tell other objects what to do, not ask them for data and make decisions for them.</p>
<p><strong>Simple explanation:</strong> Instead of asking an object for its data and then deciding what to do, tell the object what you want done and let it handle the details.</p>
<p><strong>Why it matters:</strong> Encapsulates logic where it belongs, reduces coupling, and makes code more maintainable by keeping related logic together.</p>
<p><strong>When to use:</strong></p>
<ul>
<li>State management where logic belongs with the data</li>
<li>API design where you want to encapsulate business rules</li>
<li>React components that should manage their own state</li>
<li>Reducing prop drilling and state management complexity</li>
</ul>
<p><strong>When NOT to use:</strong></p>
<ul>
<li>Simple data structures without behavior</li>
<li>When you genuinely need raw data for multiple purposes</li>
<li>Pure calculation functions that transform data</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Asking for data and making decisions externally</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> ShoppingCart</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">cart</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setCart</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">({ items: [], discount: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> handleCheckout</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">    // Asking for data and calculating externally</span></span>
<span class="line"><span style="color:#F97583">    let</span><span style="color:#E1E4E8"> total </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">    cart.items.</span><span style="color:#B392F0">forEach</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">item</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">      total </span><span style="color:#F97583">+=</span><span style="color:#E1E4E8"> item.price </span><span style="color:#F97583">*</span><span style="color:#E1E4E8"> item.quantity;</span></span>
<span class="line"><span style="color:#E1E4E8">    });</span></span>
<span class="line"><span style="color:#B392F0">    checkout</span><span style="color:#E1E4E8">(total);</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">button</span><span style="color:#B392F0"> onClick</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">handleCheckout</span><span style="color:#E1E4E8">}&gt;Checkout</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">button</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Tell objects what to do</span></span>
<span class="line"><span style="color:#F97583">class</span><span style="color:#B392F0"> ShoppingCartModel</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  private</span><span style="color:#FFAB70"> items</span><span style="color:#F97583">:</span><span style="color:#B392F0"> CartItem</span><span style="color:#E1E4E8">[] </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> [];</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">  calculateTotal</span><span style="color:#E1E4E8">()</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> number</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.items.</span><span style="color:#B392F0">reduce</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#E1E4E8">      (</span><span style="color:#FFAB70">sum</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">item</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> sum </span><span style="color:#F97583">+</span><span style="color:#E1E4E8"> item.price </span><span style="color:#F97583">*</span><span style="color:#E1E4E8"> item.quantity,</span></span>
<span class="line"><span style="color:#79B8FF">      0</span></span>
<span class="line"><span style="color:#E1E4E8">    );</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">  checkout</span><span style="color:#E1E4E8">()</span><span style="color:#F97583">:</span><span style="color:#B392F0"> CheckoutData</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> { items: </span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">.items, total: </span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">calculateTotal</span><span style="color:#E1E4E8">() };</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ React component tells the cart what to do</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> ShoppingCart</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">cart</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> ShoppingCartModel</span><span style="color:#E1E4E8">());</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> handleCheckout</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> checkoutData</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> cart.</span><span style="color:#B392F0">checkout</span><span style="color:#E1E4E8">(); </span><span style="color:#6A737D">// Tell the cart to checkout</span></span>
<span class="line"><span style="color:#B392F0">    processCheckout</span><span style="color:#E1E4E8">(checkoutData);</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">button</span><span style="color:#B392F0"> onClick</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">handleCheckout</span><span style="color:#E1E4E8">}&gt;Checkout</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">button</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Benefits:</strong></p>
<ul>
<li><strong>Encapsulation</strong>: Business logic stays with the data</li>
<li><strong>Maintainability</strong>: Changes to rules happen in one place</li>
</ul>
<p><strong>Common Pitfall:</strong> Creating overly complex objects when simple data structures would suffice.</p>
<hr/>
<h3 id="convention-over-configuration">Convention over Configuration</h3>
<p><strong>Definition:</strong> Provide sensible defaults and follow established patterns so developers don’t have to configure everything explicitly.</p>
<p><strong>Simple explanation:</strong> Make the common case easy by having smart defaults. Only require configuration for the uncommon cases.</p>
<p><strong>Why it matters:</strong> Reduces boilerplate, speeds up development, and makes codebases more predictable by following established patterns.</p>
<p><strong>When to use:</strong></p>
<ul>
<li>Folder structure organization</li>
<li>API endpoint naming</li>
<li>Component file naming and organization</li>
<li>State management patterns</li>
<li>Default configurations</li>
</ul>
<p><strong>When NOT to use:</strong></p>
<ul>
<li>When your needs genuinely differ from conventions</li>
<li>When conventions would confuse your team</li>
<li>When explicit configuration improves clarity</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Everything requires explicit configuration</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> routes</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  users: {</span></span>
<span class="line"><span style="color:#E1E4E8">    list: { path: </span><span style="color:#9ECBFF">&quot;/api/users&quot;</span><span style="color:#E1E4E8">, method: </span><span style="color:#9ECBFF">&quot;GET&quot;</span><span style="color:#E1E4E8">, handler: </span><span style="color:#9ECBFF">&quot;UserController.list&quot;</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#E1E4E8">    create: {</span></span>
<span class="line"><span style="color:#E1E4E8">      path: </span><span style="color:#9ECBFF">&quot;/api/users&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">      method: </span><span style="color:#9ECBFF">&quot;POST&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">      handler: </span><span style="color:#9ECBFF">&quot;UserController.create&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    },</span></span>
<span class="line"><span style="color:#E1E4E8">    get: {</span></span>
<span class="line"><span style="color:#E1E4E8">      path: </span><span style="color:#9ECBFF">&quot;/api/users/:id&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">      method: </span><span style="color:#9ECBFF">&quot;GET&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">      handler: </span><span style="color:#9ECBFF">&quot;UserController.get&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    },</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ❌ Manual API client configuration</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> apiClient</span><span style="color:#F97583"> =</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> ApiClient</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">  baseURL: </span><span style="color:#9ECBFF">&quot;https://api.example.com&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  timeout: </span><span style="color:#79B8FF">5000</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  headers: { </span><span style="color:#9ECBFF">&quot;Content-Type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;application/json&quot;</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#B392F0">  errorHandler</span><span style="color:#E1E4E8">: (</span><span style="color:#FFAB70">error</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">    /* custom error handling */</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Convention-based routing</span></span>
<span class="line"><span style="color:#6A737D">// File: routes/users.ts - framework maps methods to RESTful routes</span></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  async</span><span style="color:#B392F0"> index</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#6A737D">    /* GET /api/users */</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#F97583">  async</span><span style="color:#B392F0"> create</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#6A737D">    /* POST /api/users */</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#F97583">  async</span><span style="color:#B392F0"> show</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#6A737D">    /* GET /api/users/:id */</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ API client with smart defaults</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> apiClient</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> createApiClient</span><span style="color:#E1E4E8">(); </span><span style="color:#6A737D">// Works out of the box</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// Only configure what&#39;s different</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> customApiClient</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> createApiClient</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">  baseURL: process.env.</span><span style="color:#79B8FF">API_URL</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<p><strong>Benefits:</strong></p>
<ul>
<li><strong>Productivity</strong>: Less boilerplate, faster development</li>
<li><strong>Consistency</strong>: Everyone follows the same patterns</li>
<li><strong>Discoverability</strong>: Easy to find things in predictable locations</li>
<li><strong>Onboarding</strong>: New developers understand the structure quickly</li>
</ul>
<p><strong>Common Pitfall:</strong> Following conventions blindly when they don’t fit your use case.</p>
<hr/>
<h3 id="principle-of-least-astonishment">Principle of Least Astonishment</h3>
<p><strong>Definition:</strong> Software should behave in a way that least surprises users and developers. The behavior should match expectations based on common patterns and naming.</p>
<p><strong>Simple explanation:</strong> If most developers would expect something to work a certain way, it should work that way. Don’t be clever at the expense of being predictable.</p>
<p><strong>Note:</strong> This is similar to “Principle of Least Surprise” from <a href="./understand-acronym-spaghetti-part-2-quality-principles">Part 2</a>, but focuses more on API design and system behavior rather than code readability.</p>
<p><strong>Why it matters:</strong> Reduces cognitive load, prevents bugs from misunderstood behavior, and makes systems easier to learn and use.</p>
<p><strong>When to use:</strong></p>
<ul>
<li>API response formats</li>
<li>Error handling patterns</li>
<li>State management behavior</li>
<li>Component lifecycle and side effects</li>
<li>Function naming and behavior</li>
</ul>
<p><strong>When NOT to use:</strong></p>
<ul>
<li>When breaking expectations provides significant value</li>
<li>When following patterns would compromise security</li>
<li>When domain requirements genuinely differ from common patterns</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Astonishing API behavior</span></span>
<span class="line"><span style="color:#E1E4E8">app.</span><span style="color:#B392F0">get</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;/api/users/:id&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> User.</span><span style="color:#B392F0">findById</span><span style="color:#E1E4E8">(req.params.id);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">user) {</span></span>
<span class="line"><span style="color:#6A737D">    // Surprising: Returns 200 with special format instead of 404</span></span>
<span class="line"><span style="color:#E1E4E8">    res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">({ error: </span><span style="color:#9ECBFF">&quot;NOT_FOUND&quot;</span><span style="color:#E1E4E8">, data: </span><span style="color:#79B8FF">null</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">  } </span><span style="color:#F97583">else</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">    res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">({ error: </span><span style="color:#79B8FF">null</span><span style="color:#E1E4E8">, data: user });</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Predictable API behavior</span></span>
<span class="line"><span style="color:#E1E4E8">app.</span><span style="color:#B392F0">get</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;/api/users/:id&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#F97583">async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> User.</span><span style="color:#B392F0">findById</span><span style="color:#E1E4E8">(req.params.id);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">user) {</span></span>
<span class="line"><span style="color:#6A737D">    // Expected: 404 for not found</span></span>
<span class="line"><span style="color:#E1E4E8">    res.</span><span style="color:#B392F0">status</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">404</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">({ error: </span><span style="color:#9ECBFF">&quot;User not found&quot;</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">  } </span><span style="color:#F97583">else</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">    // Expected: 200 with user data</span></span>
<span class="line"><span style="color:#E1E4E8">    res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Function with surprising behavior</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> saveUserData</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">userData</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> any</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">  // Surprising: Function named &#39;save&#39; also sends emails</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> database.</span><span style="color:#B392F0">save</span><span style="color:#E1E4E8">(userData);</span></span>
<span class="line"><span style="color:#F97583">  await</span><span style="color:#E1E4E8"> emailService.</span><span style="color:#B392F0">sendWelcome</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> user;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Function with predictable behavior</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> saveUser</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">userData</span><span style="color:#F97583">:</span><span style="color:#B392F0"> UserData</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">User</span><span style="color:#E1E4E8">&gt; </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">  // Function only saves, as the name suggests</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> database.</span><span style="color:#B392F0">save</span><span style="color:#E1E4E8">(userData);</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> createUser</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">userData</span><span style="color:#F97583">:</span><span style="color:#B392F0"> UserData</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">User</span><span style="color:#E1E4E8">&gt; </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">  // Separate function for the full creation flow</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> saveUser</span><span style="color:#E1E4E8">(userData);</span></span>
<span class="line"><span style="color:#F97583">  await</span><span style="color:#E1E4E8"> emailService.</span><span style="color:#B392F0">sendWelcome</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> user; </span><span style="color:#6A737D">// Always returns the same type</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Benefits:</strong></p>
<ul>
<li><strong>Reduced Errors</strong>: Developers make fewer mistakes when behavior matches expectations</li>
<li><strong>Faster Development</strong>: Less time spent understanding quirks</li>
</ul>
<p><strong>Common Pitfall:</strong> Being too clever or trying to “improve” on established patterns without clear benefit.</p>
<hr/>
<h2 id="summary">Summary</h2>
<p>These <strong>Advanced Principles</strong> help you write code that’s not just functional, but elegant and maintainable. They’re the difference between code that works and code that’s a joy to work with.</p>
<p><strong>Advanced principles covered:</strong></p>
<ul>
<li><strong>Law of Demeter</strong>: Don’t reach through objects - keep interactions local</li>
<li><strong>Composition over Inheritance</strong>: Build complexity from simple, composable parts</li>
<li><strong>Tell, Don’t Ask</strong>: Let objects manage their own state and behavior</li>
<li><strong>Convention over Configuration</strong>: Smart defaults make the common case easy</li>
<li><strong>Principle of Least Astonishment</strong>: Behavior should match expectations</li>
</ul>
<p>Together with the principles from <a href="./2025-07-18--understand-acronym-spaghetti-wtf-to-solid-code">Part 1</a>, <a href="./2025-07-19--understand-acronym-spaghetti-part-2-quality-principles">Part 2</a>, <a href="./2025-07-20--understand-acronym-spaghetti-part-3-solid-principles">Part 3</a>, and <a href="./2025-07-21--understand-acronym-spaghetti-part-4-cqrs-and-hexagonal">Part 4</a>, you now have a complete toolkit for writing clean, maintainable code in React and Node.js.</p>
<p>Remember: <strong>mastery comes from knowing when to apply these principles and when to break them for the sake of simplicity.</strong></p>]]></content:encoded>
    </item>
    <item>
      <title>Understand the Acronym Spaghetti: Part 2 - The Quality Principles</title>
      <link>https://letanure.dev/writing/understand-acronym-spaghetti-part-2-quality-principles/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/understand-acronym-spaghetti-part-2-quality-principles/</guid>
      <pubDate>Sat, 19 Jul 2025 00:00:00 GMT</pubDate>
      <description>Level up your code quality with principles like Pure Functions, Immutability, and Principle of Least Surprise. The second part of our programming principles series.</description>
      <content:encoded><![CDATA[<h1 id="understand-the-acronym-spaghetti-part-2---the-quality-principles">Understand the Acronym Spaghetti: Part 2 - The Quality Principles</h1>
<h2 id="tldr">TLDR</h2>
<ul>
<li><strong>Pure Functions</strong>: Same input always gives same output</li>
<li><strong>Immutability</strong>: Create new objects instead of changing existing ones</li>
<li><strong>Principle of Least Surprise</strong>: Code should behave as expected</li>
<li><strong>Design by Contract</strong>: Define clear input/output rules</li>
<li><strong>Explicit is better than Implicit</strong>: Be clear, not clever</li>
</ul>
<hr/>
<p>In <a href="./2025-07-18--understand-acronym-spaghetti-wtf-to-solid-code">Part 1</a>, we covered <strong>The Foundation</strong> - the core principles: SRP, DRY, KISS, YAGNI, Fail Fast, GIGO, and Separation of Concerns.</p>
<p><strong>Code Quality &amp; Safety</strong> principles take your code quality from “it works” to “it works well.”</p>
<h2 id="code-quality--safety">Code Quality &amp; Safety</h2>
<p>These are best practices that make your code more predictable, testable, and maintainable.</p>
<h3 id="pure-functions">Pure Functions</h3>
<p><strong>Definition:</strong> A function that always returns the same output for the same input and has no side effects.</p>
<p><strong>Why it matters:</strong> Predictable, testable, and easy to reason about. No hidden dependencies or surprises.</p>
<p><strong>When to break this rule:</strong> When you need to interact with the outside world (APIs, files, databases) or when performance requires caching/memoization.</p>
<p><strong>Simple calculation function</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Function with side effects and external dependencies</span></span>
<span class="line"><span style="color:#F97583">let</span><span style="color:#E1E4E8"> counter </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> addToCounter</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">value</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> number</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  counter </span><span style="color:#F97583">+=</span><span style="color:#E1E4E8"> value; </span><span style="color:#6A737D">// Side effect - modifies external state</span></span>
<span class="line"><span style="color:#E1E4E8">  console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;Added:&#39;</span><span style="color:#E1E4E8">, value); </span><span style="color:#6A737D">// Side effect - I/O operation</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> counter; </span><span style="color:#6A737D">// Output depends on external state</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same functionality, but pure</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> add</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">a</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> number</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">b</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> number</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> number</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> a </span><span style="color:#F97583">+</span><span style="color:#E1E4E8"> b; </span><span style="color:#6A737D">// Same input always produces same output</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>React component with calculations</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Component with impure calculations</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> ProductCard</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">product</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">product</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Product</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">clickCount</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setClickCount</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> calculateDiscount</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> now</span><span style="color:#F97583"> =</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Date</span><span style="color:#E1E4E8">(); </span><span style="color:#6A737D">// Non-deterministic - depends on current time</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> isWeekend</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> now.</span><span style="color:#B392F0">getDay</span><span style="color:#E1E4E8">() </span><span style="color:#F97583">===</span><span style="color:#79B8FF"> 0</span><span style="color:#F97583"> ||</span><span style="color:#E1E4E8"> now.</span><span style="color:#B392F0">getDay</span><span style="color:#E1E4E8">() </span><span style="color:#F97583">===</span><span style="color:#79B8FF"> 6</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#B392F0">    setClickCount</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">prev</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> prev </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">); </span><span style="color:#6A737D">// Side effect - modifies state</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> isWeekend </span><span style="color:#F97583">?</span><span style="color:#79B8FF"> 0.2</span><span style="color:#F97583"> :</span><span style="color:#79B8FF"> 0.1</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;Price: ${product.price * (</span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8"> - calculateDiscount())}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same component, but with pure calculations</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> ProductCard</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">product</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">isWeekend</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">product</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Product</span><span style="color:#E1E4E8">; </span><span style="color:#FFAB70">isWeekend</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> boolean</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> calculateDiscount</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">isWeekend</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> boolean</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> isWeekend </span><span style="color:#F97583">?</span><span style="color:#79B8FF"> 0.2</span><span style="color:#F97583"> :</span><span style="color:#79B8FF"> 0.1</span><span style="color:#E1E4E8">; </span><span style="color:#6A737D">// Pure - same input, same output</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> discountedPrice</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> product.price </span><span style="color:#F97583">*</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">1</span><span style="color:#F97583"> -</span><span style="color:#B392F0"> calculateDiscount</span><span style="color:#E1E4E8">(isWeekend));</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;Price: ${discountedPrice}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>User name formatting function</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Function with external dependencies and side effects</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> formatUserName</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> settings</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> getGlobalSettings</span><span style="color:#E1E4E8">(); </span><span style="color:#6A737D">// External dependency</span></span>
<span class="line"><span style="color:#E1E4E8">  localStorage.</span><span style="color:#B392F0">setItem</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;lastUser&#39;</span><span style="color:#E1E4E8">, user.id); </span><span style="color:#6A737D">// Side effect</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> settings.showFullName </span></span>
<span class="line"><span style="color:#F97583">    ?</span><span style="color:#9ECBFF"> `${</span><span style="color:#E1E4E8">user</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">firstName</span><span style="color:#9ECBFF">} ${</span><span style="color:#E1E4E8">user</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">lastName</span><span style="color:#9ECBFF">}`</span></span>
<span class="line"><span style="color:#F97583">    :</span><span style="color:#E1E4E8"> user.firstName;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same functionality, but pure with explicit dependencies</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> formatUserName</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">showFullName</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> boolean</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> showFullName </span></span>
<span class="line"><span style="color:#F97583">    ?</span><span style="color:#9ECBFF"> `${</span><span style="color:#E1E4E8">user</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">firstName</span><span style="color:#9ECBFF">} ${</span><span style="color:#E1E4E8">user</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">lastName</span><span style="color:#9ECBFF">}`</span></span>
<span class="line"><span style="color:#F97583">    :</span><span style="color:#E1E4E8"> user.firstName;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// Side effects handled separately</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> saveUserAction</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">userId</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  localStorage.</span><span style="color:#B392F0">setItem</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;lastUser&#39;</span><span style="color:#E1E4E8">, userId);</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Common Pitfall:</strong> Mixing pure logic with I/O operations, making functions hard to test and unpredictable.</p>
<hr/>
<h3 id="immutability">Immutability</h3>
<p><strong>Definition:</strong> Don’t mutate objects — return new ones instead. Data structures should not be changed after creation.</p>
<p><strong>Why it matters:</strong> Prevents bugs from unexpected changes, makes code easier to reason about, enables better performance optimizations.</p>
<p><strong>When to break this rule:</strong> Performance-critical code where creating new objects is too expensive, or when working with large datasets where mutation is necessary.</p>
<p><strong>Add item to cart function</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Function that mutates input array</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> addItemToCart</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">cart</span><span style="color:#F97583">:</span><span style="color:#B392F0"> CartItem</span><span style="color:#E1E4E8">[], </span><span style="color:#FFAB70">item</span><span style="color:#F97583">:</span><span style="color:#B392F0"> CartItem</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  cart.</span><span style="color:#B392F0">push</span><span style="color:#E1E4E8">(item); </span><span style="color:#6A737D">// Mutates the original array</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> cart;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same functionality, but returns new array</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> addItemToCart</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">cart</span><span style="color:#F97583">:</span><span style="color:#B392F0"> CartItem</span><span style="color:#E1E4E8">[], </span><span style="color:#FFAB70">item</span><span style="color:#F97583">:</span><span style="color:#B392F0"> CartItem</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> CartItem</span><span style="color:#E1E4E8">[] </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> [</span><span style="color:#F97583">...</span><span style="color:#E1E4E8">cart, item]; </span><span style="color:#6A737D">// Creates new array</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>React shopping cart component</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Component with direct state mutation</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> ShoppingCart</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">cart</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setCart</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">CartItem</span><span style="color:#E1E4E8">[]&gt;([]);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> addItem</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">item</span><span style="color:#F97583">:</span><span style="color:#B392F0"> CartItem</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">    cart.</span><span style="color:#B392F0">push</span><span style="color:#E1E4E8">(item); </span><span style="color:#6A737D">// Mutates state directly</span></span>
<span class="line"><span style="color:#B392F0">    setCart</span><span style="color:#E1E4E8">(cart); </span><span style="color:#6A737D">// React won&#39;t detect the change</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> updateQuantity</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">itemId</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">quantity</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> number</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> item</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> cart.</span><span style="color:#B392F0">find</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">i</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> i.id </span><span style="color:#F97583">===</span><span style="color:#E1E4E8"> itemId);</span></span>
<span class="line"><span style="color:#F97583">    if</span><span style="color:#E1E4E8"> (item) {</span></span>
<span class="line"><span style="color:#E1E4E8">      item.quantity </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> quantity; </span><span style="color:#6A737D">// Mutates nested object</span></span>
<span class="line"><span style="color:#B392F0">      setCart</span><span style="color:#E1E4E8">(cart);</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;{cart.map(</span><span style="color:#FFAB70">item</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">CartItem</span><span style="color:#B392F0"> key</span><span style="color:#E1E4E8">={</span><span style="color:#B392F0">item</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">id</span><span style="color:#E1E4E8">} </span><span style="color:#B392F0">item</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">item</span><span style="color:#E1E4E8">} /&gt;)}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same component, but with immutable state updates</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> ShoppingCart</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">cart</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setCart</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">CartItem</span><span style="color:#E1E4E8">[]&gt;([]);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> addItem</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">item</span><span style="color:#F97583">:</span><span style="color:#B392F0"> CartItem</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">    setCart</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">prevCart</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> [</span><span style="color:#F97583">...</span><span style="color:#E1E4E8">prevCart, item]); </span><span style="color:#6A737D">// Creates new array</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> updateQuantity</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">itemId</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">quantity</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> number</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">    setCart</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">prevCart</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> </span></span>
<span class="line"><span style="color:#E1E4E8">      prevCart.</span><span style="color:#B392F0">map</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">item</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> </span></span>
<span class="line"><span style="color:#E1E4E8">        item.id </span><span style="color:#F97583">===</span><span style="color:#E1E4E8"> itemId </span></span>
<span class="line"><span style="color:#F97583">          ?</span><span style="color:#E1E4E8"> { </span><span style="color:#F97583">...</span><span style="color:#E1E4E8">item, quantity } </span><span style="color:#6A737D">// Creates new object</span></span>
<span class="line"><span style="color:#F97583">          :</span><span style="color:#E1E4E8"> item</span></span>
<span class="line"><span style="color:#E1E4E8">      )</span></span>
<span class="line"><span style="color:#E1E4E8">    );</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;{cart.map(</span><span style="color:#FFAB70">item</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">CartItem</span><span style="color:#B392F0"> key</span><span style="color:#E1E4E8">={</span><span style="color:#B392F0">item</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">id</span><span style="color:#E1E4E8">} </span><span style="color:#B392F0">item</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">item</span><span style="color:#E1E4E8">} /&gt;)}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>User profile update function</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Function that mutates user object</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> updateUserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">updates</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Partial</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">User</span><span style="color:#E1E4E8">&gt;) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  user.name </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> updates.name </span><span style="color:#F97583">||</span><span style="color:#E1E4E8"> user.name; </span><span style="color:#6A737D">// Mutates original</span></span>
<span class="line"><span style="color:#E1E4E8">  user.email </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> updates.email </span><span style="color:#F97583">||</span><span style="color:#E1E4E8"> user.email; </span><span style="color:#6A737D">// Mutates original</span></span>
<span class="line"><span style="color:#E1E4E8">  user.updatedAt </span><span style="color:#F97583">=</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Date</span><span style="color:#E1E4E8">(); </span><span style="color:#6A737D">// Mutates original</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> user;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same functionality, but returns new user object</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> updateUserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">updates</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Partial</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">User</span><span style="color:#E1E4E8">&gt;)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    ...</span><span style="color:#E1E4E8">user,</span></span>
<span class="line"><span style="color:#F97583">    ...</span><span style="color:#E1E4E8">updates,</span></span>
<span class="line"><span style="color:#E1E4E8">    updatedAt: </span><span style="color:#F97583">new</span><span style="color:#B392F0"> Date</span><span style="color:#E1E4E8">()</span></span>
<span class="line"><span style="color:#E1E4E8">  }; </span><span style="color:#6A737D">// Creates completely new object</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Common Pitfall:</strong> Thinking immutability means you can’t change data at all, instead of creating new versions of data structures.</p>
<hr/>
<h3 id="principle-of-least-surprise">Principle of Least Surprise</h3>
<p><strong>Definition:</strong> Code should behave as people intuitively expect. Functions, variables, interfaces, and folder structures should do what their names suggest.</p>
<p><strong>Why it matters:</strong> Reduces cognitive load, makes code self-documenting, prevents bugs from misunderstanding.</p>
<p><strong>When to break this rule:</strong> When following domain-specific conventions that might seem unusual but are standard in that field.</p>
<p><strong>User data fetching function</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Function with misleading name and hidden side effects</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> getUser</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> database.</span><span style="color:#B392F0">findUser</span><span style="color:#E1E4E8">(id);</span></span>
<span class="line"><span style="color:#E1E4E8">  user.lastAccessed </span><span style="color:#F97583">=</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Date</span><span style="color:#E1E4E8">(); </span><span style="color:#6A737D">// Surprise! It modifies data</span></span>
<span class="line"><span style="color:#E1E4E8">  analytics.</span><span style="color:#B392F0">track</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;user_accessed&#39;</span><span style="color:#E1E4E8">, { userId: id }); </span><span style="color:#6A737D">// Surprise! It tracks events</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> user;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same functionality, but explicit and separated</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> getUser</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> database.</span><span style="color:#B392F0">findUser</span><span style="color:#E1E4E8">(id); </span><span style="color:#6A737D">// Just gets the user</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// Side effects are separate and explicit</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> trackUserAccess</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">userId</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  analytics.</span><span style="color:#B392F0">track</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;user_accessed&#39;</span><span style="color:#E1E4E8">, { userId });</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> updateUserLastAccessed</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">userId</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  database.</span><span style="color:#B392F0">updateUser</span><span style="color:#E1E4E8">(userId, { lastAccessed: </span><span style="color:#F97583">new</span><span style="color:#B392F0"> Date</span><span style="color:#E1E4E8">() });</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>React user list component</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Component with unexpected mutations during filtering</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserList</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">users</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">users</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">[] }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">searchTerm</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setSearchTerm</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> filteredUsers</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> users.</span><span style="color:#B392F0">filter</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">    // Surprise! Filtering also sorts and modifies original data</span></span>
<span class="line"><span style="color:#E1E4E8">    user.displayName </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> user.firstName </span><span style="color:#F97583">+</span><span style="color:#9ECBFF"> &#39; &#39;</span><span style="color:#F97583"> +</span><span style="color:#E1E4E8"> user.lastName;</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> user.name.</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(searchTerm);</span></span>
<span class="line"><span style="color:#E1E4E8">  }).</span><span style="color:#B392F0">sort</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">a</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">b</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> a.name.</span><span style="color:#B392F0">localeCompare</span><span style="color:#E1E4E8">(b.name));</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#F97583">      &lt;</span><span style="color:#E1E4E8">input onChange</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#FFAB70">e</span><span style="color:#F97583"> =&gt;</span><span style="color:#B392F0"> setSearchTerm</span><span style="color:#E1E4E8">(e.target.value)} </span><span style="color:#F97583">/&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      {</span><span style="color:#FFAB70">filteredUsers</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">map</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#B392F0"> key</span><span style="color:#E1E4E8">={</span><span style="color:#B392F0">user</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">id</span><span style="color:#E1E4E8">}&gt;{user.displayName}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">)}</span></span>
<span class="line"><span style="color:#F97583">    &lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same component, but clear and predictable</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserList</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">users</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">users</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">[] }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">searchTerm</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setSearchTerm</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> filteredUsers</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> users</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">filter</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> user.name.</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(searchTerm))</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">map</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> ({</span></span>
<span class="line"><span style="color:#F97583">      ...</span><span style="color:#E1E4E8">user,</span></span>
<span class="line"><span style="color:#E1E4E8">      displayName: </span><span style="color:#9ECBFF">`${</span><span style="color:#E1E4E8">user</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">firstName</span><span style="color:#9ECBFF">} ${</span><span style="color:#E1E4E8">user</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">lastName</span><span style="color:#9ECBFF">}`</span></span>
<span class="line"><span style="color:#E1E4E8">    }))</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">sort</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">a</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">b</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> a.name.</span><span style="color:#B392F0">localeCompare</span><span style="color:#E1E4E8">(b.name));</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#F97583">      &lt;</span><span style="color:#E1E4E8">input onChange</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#FFAB70">e</span><span style="color:#F97583"> =&gt;</span><span style="color:#B392F0"> setSearchTerm</span><span style="color:#E1E4E8">(e.target.value)} </span><span style="color:#F97583">/&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      {</span><span style="color:#FFAB70">filteredUsers</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">map</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#B392F0"> key</span><span style="color:#E1E4E8">={</span><span style="color:#B392F0">user</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">id</span><span style="color:#E1E4E8">}&gt;{user.displayName}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">)}</span></span>
<span class="line"><span style="color:#F97583">    &lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>User status checking function</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Function with confusing boolean logic</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> isUserActive</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> boolean</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">  // Surprise! Returns false for active users</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> user.status </span><span style="color:#F97583">===</span><span style="color:#9ECBFF"> &#39;inactive&#39;</span><span style="color:#F97583"> ||</span><span style="color:#E1E4E8"> user.lastLogin </span><span style="color:#F97583">&lt;</span><span style="color:#E1E4E8"> Date.</span><span style="color:#B392F0">now</span><span style="color:#E1E4E8">() </span><span style="color:#F97583">-</span><span style="color:#79B8FF"> 30</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> 24</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> 60</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> 60</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> 1000</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same functionality, but clear boolean logic</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> isUserActive</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> boolean</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> user.status </span><span style="color:#F97583">===</span><span style="color:#9ECBFF"> &#39;active&#39;</span><span style="color:#F97583"> &amp;&amp;</span><span style="color:#E1E4E8"> user.lastLogin </span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8"> Date.</span><span style="color:#B392F0">now</span><span style="color:#E1E4E8">() </span><span style="color:#F97583">-</span><span style="color:#79B8FF"> 30</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> 24</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> 60</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> 60</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> 1000</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Folder structure organization</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>❌ Misleading folder organization</span></span>
<span class="line"><span>src/</span></span>
<span class="line"><span>├── helpers/</span></span>
<span class="line"><span>│   ├── userValidation.ts  // Actually business logic, not helpers</span></span>
<span class="line"><span>│   ├── paymentService.ts  // Actually a service, not a helper</span></span>
<span class="line"><span>│   └── Button.tsx         // Surprise! UI component in helpers</span></span>
<span class="line"><span>├── utils/</span></span>
<span class="line"><span>│   ├── ApiClient.ts       // Actually a service, not a utility</span></span>
<span class="line"><span>│   ├── formatDate.ts      // Actually a utility ✓</span></span>
<span class="line"><span>│   └── UserModel.ts       // Actually a model, not a utility</span></span>
<span class="line"><span>├── app/</span></span>
<span class="line"><span>│   ├── LoginPage.tsx      // Surprise! Page component in app folder</span></span>
<span class="line"><span>│   └── database.ts        // Surprise! Infrastructure in app folder</span></span>
<span class="line"><span>└── pages/</span></span>
<span class="line"><span>    ├── userHelpers.ts     // Surprise! Helper functions in pages</span></span>
<span class="line"><span>    └── api.ts             // Surprise! API client in pages</span></span>
<span class="line"><span></span></span>
<span class="line"><span>✅ Clear folder organization</span></span>
<span class="line"><span>src/</span></span>
<span class="line"><span>├── components/</span></span>
<span class="line"><span>│   ├── UserList.tsx</span></span>
<span class="line"><span>│   └── Button.tsx</span></span>
<span class="line"><span>├── services/</span></span>
<span class="line"><span>│   ├── paymentService.ts</span></span>
<span class="line"><span>│   ├── userService.ts</span></span>
<span class="line"><span>│   └── apiClient.ts</span></span>
<span class="line"><span>├── utils/</span></span>
<span class="line"><span>│   ├── dateHelpers.ts</span></span>
<span class="line"><span>│   └── formatters.ts</span></span>
<span class="line"><span>├── models/</span></span>
<span class="line"><span>│   └── UserModel.ts</span></span>
<span class="line"><span>├── business/</span></span>
<span class="line"><span>│   └── userValidation.ts</span></span>
<span class="line"><span>└── pages/</span></span>
<span class="line"><span>    └── LoginPage.tsx</span></span></code></pre>
<p><strong>Common Pitfall:</strong> Using names that don’t accurately describe what the code actually does.</p>
<hr/>
<h3 id="design-by-contract">Design by Contract</h3>
<p><strong>Definition:</strong> Define input/output conditions clearly. Specify what a function expects (preconditions) and what it guarantees (postconditions).</p>
<p><strong>Why it matters:</strong> Makes function behavior explicit, catches bugs early, improves documentation and testing.</p>
<p><strong>When to break this rule:</strong> Simple, obvious functions where the contract is self-evident from the name and types.</p>
<p><strong>Price discount calculation function</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Function with unclear contract</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> calculateDiscount</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">price</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> any</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">userType</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> any</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">  // What happens if price is negative? What userTypes are valid?</span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (userType </span><span style="color:#F97583">===</span><span style="color:#9ECBFF"> &#39;premium&#39;</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">return</span><span style="color:#E1E4E8"> price </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 0.8</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (userType </span><span style="color:#F97583">===</span><span style="color:#9ECBFF"> &#39;regular&#39;</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">return</span><span style="color:#E1E4E8"> price </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 0.9</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> price; </span><span style="color:#6A737D">// Silent fallback - no indication this can happen</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same functionality, but explicit contract</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> calculateDiscount</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">price</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> number</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">userType</span><span style="color:#F97583">:</span><span style="color:#9ECBFF"> &#39;premium&#39;</span><span style="color:#F97583"> |</span><span style="color:#9ECBFF"> &#39;regular&#39;</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> number</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">  // Preconditions: price &gt;= 0, userType must be &#39;premium&#39; or &#39;regular&#39;</span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (price </span><span style="color:#F97583">&lt;</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">throw</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Error</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;Price must be non-negative&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#6A737D">  // Postconditions: returns discounted price (0.8x for premium, 0.9x for regular)</span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (userType </span><span style="color:#F97583">===</span><span style="color:#9ECBFF"> &#39;premium&#39;</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">return</span><span style="color:#E1E4E8"> price </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 0.8</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (userType </span><span style="color:#F97583">===</span><span style="color:#9ECBFF"> &#39;regular&#39;</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">return</span><span style="color:#E1E4E8"> price </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 0.9</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#6A737D">  // This line should never be reached due to TypeScript types</span></span>
<span class="line"><span style="color:#F97583">  throw</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Error</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`Invalid user type: ${</span><span style="color:#E1E4E8">userType</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>React user profile component</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Component with unclear expectations</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">user</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> any</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">  // What if user is null? What properties are required?</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#B392F0">h1</span><span style="color:#E1E4E8">&gt;{user.name}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">h1</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#B392F0">p</span><span style="color:#E1E4E8">&gt;{user.email}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">p</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#B392F0">p</span><span style="color:#E1E4E8">&gt;Member </span><span style="color:#FFAB70">since</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> {</span><span style="color:#B392F0">user</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">joinDate</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">toLocaleDateString</span><span style="color:#E1E4E8">()}&lt;/</span><span style="color:#B392F0">p</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#F97583">    &lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same component, but clear interface</span></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> UserProfileProps</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  user</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">    name</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">    email</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">    joinDate</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Date</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">user</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#B392F0"> UserProfileProps</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">  // Contract: user object must have name, email, and joinDate</span></span>
<span class="line"><span style="color:#6A737D">  // Guarantees: renders user information or throws error</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#B392F0">h1</span><span style="color:#E1E4E8">&gt;{user.name}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">h1</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#B392F0">p</span><span style="color:#E1E4E8">&gt;{user.email}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">p</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#B392F0">p</span><span style="color:#E1E4E8">&gt;Member </span><span style="color:#FFAB70">since</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> {</span><span style="color:#B392F0">user</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">joinDate</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">toLocaleDateString</span><span style="color:#E1E4E8">()}&lt;/</span><span style="color:#B392F0">p</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#F97583">    &lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>API update function</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ API function with vague contract</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> updateUser</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">data</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> any</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">  // What fields can be updated? What errors can occur?</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> response</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`/api/users/${</span><span style="color:#E1E4E8">id</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">, {</span></span>
<span class="line"><span style="color:#E1E4E8">    method: </span><span style="color:#9ECBFF">&#39;PUT&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    body: </span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">(data)</span></span>
<span class="line"><span style="color:#E1E4E8">  });</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> response.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same functionality, but explicit contract</span></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> UpdateUserData</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  name</span><span style="color:#F97583">?:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  email</span><span style="color:#F97583">?:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> updateUser</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">data</span><span style="color:#F97583">:</span><span style="color:#B392F0"> UpdateUserData</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">User</span><span style="color:#E1E4E8">&gt; </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">id) </span><span style="color:#F97583">throw</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Error</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;User ID is required&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> response</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`/api/users/${</span><span style="color:#E1E4E8">id</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">, {</span></span>
<span class="line"><span style="color:#E1E4E8">    method: </span><span style="color:#9ECBFF">&#39;PUT&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    headers: { </span><span style="color:#9ECBFF">&#39;Content-Type&#39;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&#39;application/json&#39;</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#E1E4E8">    body: </span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">(data)</span></span>
<span class="line"><span style="color:#E1E4E8">  });</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">response.ok) </span><span style="color:#F97583">throw</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Error</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;Failed to update user&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> response.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Common Pitfall:</strong> Assuming callers will know what inputs are valid and what outputs to expect without explicit documentation.</p>
<hr/>
<h3 id="explicit-is-better-than-implicit">Explicit is better than implicit</h3>
<p><strong>Definition:</strong> Be clear rather than clever. Make your intentions obvious instead of relying on hidden assumptions or magic.</p>
<p><strong>Why it matters:</strong> Code is read more often than it’s written. Explicit code is easier to understand, debug, and maintain.</p>
<p><strong>When to break this rule:</strong> When well-established conventions make implicit behavior clearer than explicit (like <code>map</code> or <code>filter</code> operations).</p>
<p><strong>User processing function</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Function with implicit business logic</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> processUsers</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">users</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">[]) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> users</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">filter</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">u</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> u.active </span><span style="color:#F97583">&amp;&amp;</span><span style="color:#E1E4E8"> u.level </span><span style="color:#F97583">&gt;</span><span style="color:#79B8FF"> 2</span><span style="color:#E1E4E8">) </span><span style="color:#6A737D">// What does level &gt; 2 mean?</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">map</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">u</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> ({ </span><span style="color:#F97583">...</span><span style="color:#E1E4E8">u, bonus: u.sales </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 0.1</span><span style="color:#E1E4E8"> })) </span><span style="color:#6A737D">// Why 0.1? What&#39;s the logic?</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">sort</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">a</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">b</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> b.bonus </span><span style="color:#F97583">-</span><span style="color:#E1E4E8"> a.bonus); </span><span style="color:#6A737D">// Implicit descending sort</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same functionality, but explicit business logic</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> SENIOR_USER_LEVEL</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 2</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> COMMISSION_RATE</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 0.1</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> processUsers</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">users</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">[]) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> users</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">filter</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> user.active </span><span style="color:#F97583">&amp;&amp;</span><span style="color:#E1E4E8"> user.level </span><span style="color:#F97583">&gt;</span><span style="color:#79B8FF"> SENIOR_USER_LEVEL</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">map</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> ({ </span><span style="color:#F97583">...</span><span style="color:#E1E4E8">user, bonus: user.sales </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> COMMISSION_RATE</span><span style="color:#E1E4E8"> }))</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">sort</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">a</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">b</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> b.bonus </span><span style="color:#F97583">-</span><span style="color:#E1E4E8"> a.bonus);</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>React component with magic numbers</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Component with magic numbers and implicit logic</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> ProductList</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">products</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">products</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Product</span><span style="color:#E1E4E8">[] }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      {</span><span style="color:#FFAB70">products</span></span>
<span class="line"><span style="color:#E1E4E8">        .</span><span style="color:#FFAB70">filter</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">p</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> p.price </span><span style="color:#F97583">&gt;</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">) </span><span style="color:#6A737D">// Implicit business rule</span></span>
<span class="line"><span style="color:#E1E4E8">        .</span><span style="color:#FFAB70">map</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">p</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#F97583">          &lt;</span><span style="color:#E1E4E8">div key</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{p.id}</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">            &lt;</span><span style="color:#B392F0">h3</span><span style="color:#E1E4E8">&gt;{p.name}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">h3</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">            &lt;</span><span style="color:#B392F0">p</span><span style="color:#E1E4E8">&gt;${p.price}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">p</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">            {</span><span style="color:#FFAB70">p</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">stock</span><span style="color:#E1E4E8"> &lt; 5 &amp;&amp; &lt;</span><span style="color:#FFAB70">span</span><span style="color:#E1E4E8">&gt;</span><span style="color:#FFAB70">Low</span><span style="color:#FFAB70"> stock</span><span style="color:#E1E4E8">!&lt;/</span><span style="color:#FFAB70">span</span><span style="color:#E1E4E8">&gt;} {</span><span style="color:#6A737D">/* Magic number */</span><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#F97583">          &lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">        ))}</span></span>
<span class="line"><span style="color:#F97583">    &lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same component, but explicit constants</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> LOW_STOCK_THRESHOLD</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 5</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> ProductList</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">products</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">products</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Product</span><span style="color:#E1E4E8">[] }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> availableProducts</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> products.</span><span style="color:#B392F0">filter</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">p</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> p.price </span><span style="color:#F97583">&gt;</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      {</span><span style="color:#FFAB70">availableProducts</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">map</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">product</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#F97583">        &lt;</span><span style="color:#E1E4E8">div key</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{product.id}</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">          &lt;</span><span style="color:#B392F0">h3</span><span style="color:#E1E4E8">&gt;{product.name}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">h3</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">          &lt;</span><span style="color:#B392F0">p</span><span style="color:#E1E4E8">&gt;${product.price}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">p</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">          {</span><span style="color:#FFAB70">product</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">stock</span><span style="color:#E1E4E8"> &lt; </span><span style="color:#FFAB70">LOW_STOCK_THRESHOLD</span><span style="color:#E1E4E8"> &amp;&amp; (</span></span>
<span class="line"><span style="color:#E1E4E8">            &lt;</span><span style="color:#FFAB70">span</span><span style="color:#E1E4E8">&gt;</span><span style="color:#FFAB70">Low</span><span style="color:#FFAB70"> stock</span><span style="color:#E1E4E8">!&lt;/</span><span style="color:#FFAB70">span</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">          )}</span></span>
<span class="line"><span style="color:#F97583">        &lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      ))}</span></span>
<span class="line"><span style="color:#F97583">    &lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>API configuration</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Configuration with magic numbers</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> API_CONFIG</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  baseUrl: process.env.</span><span style="color:#79B8FF">API_URL</span><span style="color:#F97583"> ||</span><span style="color:#9ECBFF"> &#39;https://api.example.com&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  timeout: </span><span style="color:#79B8FF">5000</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// Magic number - why 5000?</span></span>
<span class="line"><span style="color:#E1E4E8">  retries: </span><span style="color:#79B8FF">3</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// Magic number - why 3?</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same configuration, but explicit with documentation</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> API_CONFIG</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  baseUrl: process.env.</span><span style="color:#79B8FF">API_URL</span><span style="color:#F97583"> ||</span><span style="color:#9ECBFF"> &#39;https://api.example.com&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  timeout: </span><span style="color:#79B8FF">5000</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// 5 seconds - balance between user experience and server load</span></span>
<span class="line"><span style="color:#E1E4E8">  retries: </span><span style="color:#79B8FF">3</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// 3 attempts - enough to handle transient failures without overloading</span></span>
<span class="line"><span style="color:#E1E4E8">  retryDelay: </span><span style="color:#79B8FF">1000</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// 1 second between retries</span></span>
<span class="line"><span style="color:#E1E4E8">} </span><span style="color:#F97583">as</span><span style="color:#F97583"> const</span><span style="color:#E1E4E8">;</span></span></code></pre>
<p><strong>Common Pitfall:</strong> Using magic numbers, unexplained business rules, or clever one-liners that require mental parsing to understand.</p>
<hr/>
<h2 id="summary">Summary</h2>
<p><strong>Code Quality &amp; Safety</strong> principles help you write code that’s not just functional, but robust and reliable. They’re the difference between code that works today and code that works in six months when you (or someone else) needs to modify it.</p>
<p><strong>Coming next:</strong> <a href="./2025-07-20--understand-acronym-spaghetti-part-3-solid-principles">Part 3</a> covers <strong>SOLID Architecture</strong> principles, and <a href="./2025-07-21--understand-acronym-spaghetti-part-4-cqrs-and-hexagonal">Part 4</a> explores <strong>System Architecture</strong> patterns.</p>
<p>Remember: <strong>good code is not about showing off how smart you are - it’s about making life easier for the next person who reads it (including future you).</strong></p>]]></content:encoded>
    </item>
    <item>
      <title>Understand the Acronym Spaghetti: From WTF to SOLID Code</title>
      <link>https://letanure.dev/writing/understand-acronym-spaghetti-wtf-to-solid-code/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/understand-acronym-spaghetti-wtf-to-solid-code/</guid>
      <pubDate>Fri, 18 Jul 2025 00:00:00 GMT</pubDate>
      <description>A developer&apos;s guide to programming principles and acronyms that matter - from core concepts like DRY and KISS to architectural patterns like SOLID. Stop drowning in alphabet soup and start writing better code.</description>
      <content:encoded><![CDATA[<h1 id="understand-the-acronym-spaghetti-from-wtf-to-solid-code">Understand the Acronym Spaghetti: From WTF to SOLID Code</h1>
<h2 id="tldr">TLDR</h2>
<ul>
<li><strong>SRP</strong>: One responsibility per function</li>
<li><strong>DRY</strong>: Don’t repeat code</li>
<li><strong>KISS</strong>: Keep it simple</li>
<li><strong>YAGNI</strong>: Don’t build what you don’t need</li>
<li><strong>Fail Fast</strong>: Catch errors early</li>
<li><strong>GIGO</strong>: Bad input = bad output</li>
<li><strong>Separation of Concerns</strong>: Keep different logic apart</li>
</ul>
<hr/>
<p>Programming is full of acronyms. DRY, KISS, YAGNI, SOLID… it’s like alphabet soup. But these aren’t just fancy buzzwords - they’re battle-tested principles that can transform your code from spaghetti mess to clean, maintainable software.</p>
<p>Let’s break down the most important ones, sorted by how common they are, how important they are, and how hard they are to apply well.</p>
<h2 id="the-foundation--core-principles">The Foundation — Core Principles</h2>
<p>These are the fundamentals. Use them everywhere.</p>
<h3 id="srp-single-responsibility-principle">SRP (Single Responsibility Principle)</h3>
<p><strong>Definition:</strong> Each function, class, or module should have only one reason to change.</p>
<p><strong>Why it matters:</strong> Easier to test, maintain, and reuse.</p>
<p><strong>When to break this rule:</strong> Very small, tightly coupled responsibilities can sometimes stay together. Don’t create separate classes for every tiny operation.</p>
<p><strong>Simple function example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Does validation, saving, email, and logging all in one</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> processUser</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">userData</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">userData.email.</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;@&#39;</span><span style="color:#E1E4E8">)) </span><span style="color:#F97583">throw</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Error</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;Invalid email&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> database.</span><span style="color:#B392F0">save</span><span style="color:#E1E4E8">(userData);</span></span>
<span class="line"><span style="color:#E1E4E8">  emailService.</span><span style="color:#B392F0">sendWelcome</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"><span style="color:#E1E4E8">  logger.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;User processed&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> user;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same functionality, but each function has one job</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> processUser</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">userData</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  validateUser</span><span style="color:#E1E4E8">(userData);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> saveUser</span><span style="color:#E1E4E8">(userData);</span></span>
<span class="line"><span style="color:#B392F0">  notifyUser</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> user;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>React component example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Component handles data fetching, validation, and rendering</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">userId</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">user</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setUser</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">null</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">loading</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setLoading</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#B392F0">  useEffect</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">    fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`/api/users/${</span><span style="color:#E1E4E8">userId</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">res</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">()).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(setUser);</span></span>
<span class="line"><span style="color:#B392F0">    setLoading</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">false</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  }, [userId]);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">user?.email?.</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;@&#39;</span><span style="color:#E1E4E8">)) </span><span style="color:#F97583">return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;Invalid user</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;{user.name}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same component, but separated concerns</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">userId</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">user</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">loading</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">error</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useUser</span><span style="color:#E1E4E8">(userId);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (loading) </span><span style="color:#F97583">return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;Loading</span><span style="color:#F97583">...&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (error) </span><span style="color:#F97583">return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;Error: {error}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;{user.name}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Common Pitfall:</strong> “Utility” classes that do everything.</p>
<hr/>
<h3 id="dry-dont-repeat-yourself">DRY (Don’t Repeat Yourself)</h3>
<p><strong>Definition:</strong> Every piece of knowledge should have a single, authoritative representation.</p>
<p><strong>Why it matters:</strong> Fix bugs in one place, not ten. Consistency across your codebase.</p>
<p><strong>When to break this rule:</strong> Some repetition is okay for organization (like page structure). General rule: if you have more than 2 copies, consider abstraction.</p>
<p><strong>Email validation example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Same validation logic repeated in different places</span></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> validateEmail</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">email</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> boolean</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> email.</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;@&#39;</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">&amp;&amp;</span><span style="color:#E1E4E8"> email.</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;.&#39;</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">&amp;&amp;</span><span style="color:#E1E4E8"> email.</span><span style="color:#79B8FF">length</span><span style="color:#F97583"> &gt;</span><span style="color:#79B8FF"> 5</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> validateUserEmail</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> boolean</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> user.email.</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;@&#39;</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">&amp;&amp;</span><span style="color:#E1E4E8"> user.email.</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;.&#39;</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">&amp;&amp;</span><span style="color:#E1E4E8"> user.email.</span><span style="color:#79B8FF">length</span><span style="color:#F97583"> &gt;</span><span style="color:#79B8FF"> 5</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Single source of truth, reused everywhere</span></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> isValidEmail</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">email</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> boolean</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> email.</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;@&#39;</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">&amp;&amp;</span><span style="color:#E1E4E8"> email.</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;.&#39;</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">&amp;&amp;</span><span style="color:#E1E4E8"> email.</span><span style="color:#79B8FF">length</span><span style="color:#F97583"> &gt;</span><span style="color:#79B8FF"> 5</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> validateUserEmail</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> boolean</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#B392F0"> isValidEmail</span><span style="color:#E1E4E8">(user.email);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p><strong>Common Pitfall:</strong> Copy-paste programming instead of extracting functions.</p>
<hr/>
<h3 id="kiss-keep-it-simple-stupid">KISS (Keep It Simple, Stupid)</h3>
<p><em>Also known as: Keep It Simple, Sweetie | Keep It Short and Simple</em></p>
<p><strong>Definition:</strong> Choose the simplest solution that works. Avoid unnecessary complexity.</p>
<p><strong>Why it matters:</strong> Simple code is easier to understand, debug, and maintain.</p>
<p><strong>User search example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Overly complex with unnecessary state management</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserList</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">users</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">filteredUsers</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setFilteredUsers</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">([]);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">searchTerm</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setSearchTerm</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#B392F0">  useEffect</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> filtered</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> users.</span><span style="color:#B392F0">filter</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> </span></span>
<span class="line"><span style="color:#E1E4E8">      user.name.</span><span style="color:#B392F0">toLowerCase</span><span style="color:#E1E4E8">().</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(searchTerm.</span><span style="color:#B392F0">toLowerCase</span><span style="color:#E1E4E8">()) </span><span style="color:#F97583">||</span></span>
<span class="line"><span style="color:#E1E4E8">      user.email.</span><span style="color:#B392F0">toLowerCase</span><span style="color:#E1E4E8">().</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(searchTerm.</span><span style="color:#B392F0">toLowerCase</span><span style="color:#E1E4E8">())</span></span>
<span class="line"><span style="color:#E1E4E8">    );</span></span>
<span class="line"><span style="color:#B392F0">    setFilteredUsers</span><span style="color:#E1E4E8">(filtered);</span></span>
<span class="line"><span style="color:#E1E4E8">  }, [users, searchTerm]);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#F97583">      &lt;</span><span style="color:#E1E4E8">input onChange</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#FFAB70">e</span><span style="color:#F97583"> =&gt;</span><span style="color:#B392F0"> setSearchTerm</span><span style="color:#E1E4E8">(e.target.value)} </span><span style="color:#F97583">/&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      {</span><span style="color:#FFAB70">filteredUsers</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">map</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">UserCard</span><span style="color:#B392F0"> key</span><span style="color:#E1E4E8">={</span><span style="color:#B392F0">user</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">id</span><span style="color:#E1E4E8">} </span><span style="color:#B392F0">user</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">user</span><span style="color:#E1E4E8">} /&gt;)}</span></span>
<span class="line"><span style="color:#F97583">    &lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Simple, direct solution</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserList</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">users</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">search</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setSearch</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> filteredUsers</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> users.</span><span style="color:#B392F0">filter</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583"> =&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    user.name.</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(search) </span><span style="color:#F97583">||</span><span style="color:#E1E4E8"> user.email.</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(search)</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#F97583">      &lt;</span><span style="color:#E1E4E8">input onChange</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#FFAB70">e</span><span style="color:#F97583"> =&gt;</span><span style="color:#B392F0"> setSearch</span><span style="color:#E1E4E8">(e.target.value)} </span><span style="color:#F97583">/&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      {</span><span style="color:#FFAB70">filteredUsers</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">map</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">UserCard</span><span style="color:#B392F0"> key</span><span style="color:#E1E4E8">={</span><span style="color:#B392F0">user</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">id</span><span style="color:#E1E4E8">} </span><span style="color:#B392F0">user</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">user</span><span style="color:#E1E4E8">} /&gt;)}</span></span>
<span class="line"><span style="color:#F97583">    &lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Common Pitfall:</strong> Over-engineering solutions before you understand the real requirements.</p>
<hr/>
<h3 id="yagni-you-arent-gonna-need-it">YAGNI (You Aren’t Gonna Need It)</h3>
<p><strong>Definition:</strong> Don’t build features or abstractions until you actually need them.</p>
<p><strong>Why it matters:</strong> Prevents wasted effort and keeps code simple. Requirements change.</p>
<p><strong>Bad Example:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Building for imaginary future requirements</span></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  name</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  email</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#6A737D">  // &quot;Maybe we&#39;ll need these later&quot;</span></span>
<span class="line"><span style="color:#FFAB70">  phoneNumber</span><span style="color:#F97583">?:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  address</span><span style="color:#F97583">?:</span><span style="color:#B392F0"> Address</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  preferences</span><span style="color:#F97583">?:</span><span style="color:#B392F0"> UserPreferences</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  socialLinks</span><span style="color:#F97583">?:</span><span style="color:#B392F0"> SocialLink</span><span style="color:#E1E4E8">[];</span></span>
<span class="line"><span style="color:#FFAB70">  customFields</span><span style="color:#F97583">?:</span><span style="color:#B392F0"> Record</span><span style="color:#E1E4E8">&lt;</span><span style="color:#79B8FF">string</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">any</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> UserService</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  getUser</span><span style="color:#E1E4E8">: (</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> { </span><span style="color:#6A737D">/* fetch user */</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#B392F0">  getUserWithProfile</span><span style="color:#E1E4E8">: (</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> { </span><span style="color:#6A737D">/* complex join */</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#B392F0">  getUserWithPreferences</span><span style="color:#E1E4E8">: (</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> { </span><span style="color:#6A737D">/* another join */</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#B392F0">  getUserWithEverything</span><span style="color:#E1E4E8">: (</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> { </span><span style="color:#6A737D">/* kitchen sink */</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#6A737D">  // ... 15 more &quot;just in case&quot; methods</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Good Example:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ✅ Build only what you need now</span></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  name</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  email</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> UserService</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  getUser</span><span style="color:#E1E4E8">: (</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> { </span><span style="color:#6A737D">/* fetch user */</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#B392F0">  updateUser</span><span style="color:#E1E4E8">: (</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">data</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Partial</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">User</span><span style="color:#E1E4E8">&gt;) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> { </span><span style="color:#6A737D">/* update user */</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#6A737D">  // Add more methods when actually needed</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Common Pitfall:</strong> Adding configuration options, abstraction layers, or features “because we might need them someday.”</p>
<hr/>
<h3 id="fail-fast">Fail Fast</h3>
<p><strong>Definition:</strong> Detect and report errors as early as possible in the execution flow.</p>
<p><strong>Why it matters:</strong> Easier debugging, prevents corruption, clearer error messages.</p>
<p><strong>Division function example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Returns Infinity or NaN instead of failing clearly</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> divide</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">a</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">b</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> a </span><span style="color:#F97583">/</span><span style="color:#E1E4E8"> b; </span><span style="color:#6A737D">// Silent failure - hard to debug</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same function, but fails fast with clear error</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> divide</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">a</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">b</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (b </span><span style="color:#F97583">===</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">throw</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Error</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;Division by zero&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> a </span><span style="color:#F97583">/</span><span style="color:#E1E4E8"> b;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>React component example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Component silently does nothing when userId is invalid</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">userId</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">user</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setUser</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">null</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#B392F0">  useEffect</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    if</span><span style="color:#E1E4E8"> (userId) { </span><span style="color:#6A737D">// Silently skips if invalid</span></span>
<span class="line"><span style="color:#B392F0">      fetchUser</span><span style="color:#E1E4E8">(userId).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(setUser);</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#E1E4E8">  }, [userId]);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;{user?.name || </span><span style="color:#9ECBFF">&#39;Loading...&#39;</span><span style="color:#E1E4E8">}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">; </span><span style="color:#6A737D">// Misleading</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same component, but fails fast with clear error</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">userId</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">userId) </span><span style="color:#F97583">throw</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Error</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;UserProfile requires a valid userId&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">user</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setUser</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">null</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">error</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setError</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">null</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#B392F0">  useEffect</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">    fetchUser</span><span style="color:#E1E4E8">(userId).</span><span style="color:#B392F0">catch</span><span style="color:#E1E4E8">(setError);</span></span>
<span class="line"><span style="color:#E1E4E8">  }, [userId]);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (error) </span><span style="color:#F97583">return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;Error: {error.message}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;{user?.name || </span><span style="color:#9ECBFF">&#39;Loading...&#39;</span><span style="color:#E1E4E8">}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Common Pitfall:</strong> Using default values or ignoring validation errors instead of failing fast.</p>
<hr/>
<h3 id="gigo-garbage-in-garbage-out">GIGO (Garbage In, Garbage Out)</h3>
<p><strong>Definition:</strong> The quality of your output is fundamentally limited by the quality of your input. Poor data leads to poor results.</p>
<p><strong>Why it matters:</strong> You can’t fix bad data with good code. Focus on data quality at the source.</p>
<p><strong>When to break this rule:</strong> Sometimes you need to work with imperfect data and clean it as best you can rather than rejecting it.</p>
<p><strong>The validation dilemma:</strong> Should a function validate its inputs or trust the caller? <strong>Rule of thumb: “Validate at boundaries, trust within boundaries.”</strong> Public APIs and external interfaces should validate. Internal functions can trust that data has been cleaned upstream.</p>
<p><strong>The GIGO perspective:</strong> Validating inside functions can violate GIGO if you’re masking data quality problems instead of fixing them, silently correcting bad data without alerting anyone, or adding complexity to handle edge cases that shouldn’t exist.</p>
<p><strong>Average calculation example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Processes bad data, returns wrong results</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> calculateAverage</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">numbers</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> numbers.</span><span style="color:#B392F0">reduce</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">sum</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">n</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> sum </span><span style="color:#F97583">+</span><span style="color:#E1E4E8"> n, </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">/</span><span style="color:#E1E4E8"> numbers.</span><span style="color:#79B8FF">length</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#6A737D">  // Returns NaN if array contains null, undefined, or strings</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same function, but handles data quality</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> calculateAverage</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">numbers</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> validNumbers</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> numbers.</span><span style="color:#B392F0">filter</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">n</span><span style="color:#F97583"> =&gt;</span><span style="color:#F97583"> typeof</span><span style="color:#E1E4E8"> n </span><span style="color:#F97583">===</span><span style="color:#9ECBFF"> &#39;number&#39;</span><span style="color:#F97583"> &amp;&amp;</span><span style="color:#F97583"> !</span><span style="color:#B392F0">isNaN</span><span style="color:#E1E4E8">(n));</span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (validNumbers.</span><span style="color:#79B8FF">length</span><span style="color:#F97583"> ===</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">return</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> validNumbers.</span><span style="color:#B392F0">reduce</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">sum</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">n</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> sum </span><span style="color:#F97583">+</span><span style="color:#E1E4E8"> n, </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">/</span><span style="color:#E1E4E8"> validNumbers.</span><span style="color:#79B8FF">length</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>React component example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Component displays misleading results from bad data</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserStats</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">users</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> totalAge</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> users.</span><span style="color:#B392F0">reduce</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">sum</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">user</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> sum </span><span style="color:#F97583">+</span><span style="color:#E1E4E8"> user.age, </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> averageAge</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> totalAge </span><span style="color:#F97583">/</span><span style="color:#E1E4E8"> users.</span><span style="color:#79B8FF">length</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;Average age: {averageAge}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">; </span></span>
<span class="line"><span style="color:#6A737D">  // Shows &quot;NaN&quot; or wrong number if some users have age: null</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same component, but handles data quality issues</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserStats</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">users</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> usersWithValidAge</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> users.</span><span style="color:#B392F0">filter</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">user</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> </span></span>
<span class="line"><span style="color:#F97583">    typeof</span><span style="color:#E1E4E8"> user.age </span><span style="color:#F97583">===</span><span style="color:#9ECBFF"> &#39;number&#39;</span><span style="color:#F97583"> &amp;&amp;</span><span style="color:#E1E4E8"> user.age </span><span style="color:#F97583">&gt;</span><span style="color:#79B8FF"> 0</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (usersWithValidAge.</span><span style="color:#79B8FF">length</span><span style="color:#F97583"> ===</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;No valid age data available</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> averageAge</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> calculateAverage</span><span style="color:#E1E4E8">(usersWithValidAge.</span><span style="color:#B392F0">map</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">u</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> u.age));</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;Average age: {averageAge.toFixed(</span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">)} ({usersWithValidAge.length} users)</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">div</span><span style="color:#F97583">&gt;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Common Pitfall:</strong> Thinking you can fix fundamental data quality issues with clever algorithms instead of addressing the root cause.</p>
<hr/>
<h3 id="separation-of-concerns">Separation of Concerns</h3>
<p><strong>Definition:</strong> Keep different responsibilities isolated from each other. Each part of your system should handle one distinct concern.</p>
<p><strong>Why it matters:</strong> Easier to understand, test, and modify each part independently.</p>
<p><strong>When to break this rule:</strong> Very small applications or prototypes where the overhead of separation isn’t worth it yet.</p>
<p><strong>User profile function example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Mixes data access, business logic, and formatting</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> getUserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">userId</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> database.</span><span style="color:#B392F0">query</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;SELECT * FROM users WHERE id = ?&#39;</span><span style="color:#E1E4E8">, [userId]);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> fullName</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> user.firstName </span><span style="color:#F97583">+</span><span style="color:#9ECBFF"> &#39; &#39;</span><span style="color:#F97583"> +</span><span style="color:#E1E4E8"> user.lastName;</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> isAdult</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> user.age </span><span style="color:#F97583">&gt;=</span><span style="color:#79B8FF"> 18</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">    name: fullName,</span></span>
<span class="line"><span style="color:#E1E4E8">    email: user.email,</span></span>
<span class="line"><span style="color:#E1E4E8">    canVote: isAdult,</span></span>
<span class="line"><span style="color:#E1E4E8">    displayColor: isAdult </span><span style="color:#F97583">?</span><span style="color:#9ECBFF"> &#39;green&#39;</span><span style="color:#F97583"> :</span><span style="color:#9ECBFF"> &#39;red&#39;</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same functionality, but separated concerns</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> getUserProfile</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">userId</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> userRepository.</span><span style="color:#B392F0">findById</span><span style="color:#E1E4E8">(userId);</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> userService.</span><span style="color:#B392F0">buildUserProfile</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// Each service handles one concern</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> userRepository</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  findById</span><span style="color:#E1E4E8">: (</span><span style="color:#FFAB70">id</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> database.</span><span style="color:#B392F0">query</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;SELECT * FROM users WHERE id = ?&#39;</span><span style="color:#E1E4E8">, [id])</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> userService</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  buildUserProfile</span><span style="color:#E1E4E8">: (</span><span style="color:#FFAB70">user</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> ({</span></span>
<span class="line"><span style="color:#E1E4E8">    name: </span><span style="color:#9ECBFF">`${</span><span style="color:#E1E4E8">user</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">firstName</span><span style="color:#9ECBFF">} ${</span><span style="color:#E1E4E8">user</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">lastName</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    email: user.email,</span></span>
<span class="line"><span style="color:#E1E4E8">    canVote: user.age </span><span style="color:#F97583">&gt;=</span><span style="color:#79B8FF"> 18</span></span>
<span class="line"><span style="color:#E1E4E8">  })</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>React component example</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// ❌ Component handles data fetching, business logic, and UI</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> UserDashboard</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">userId</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">user</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setUser</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">null</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">notifications</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setNotifications</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">([]);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#B392F0">  useEffect</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">    fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`/api/users/${</span><span style="color:#E1E4E8">userId</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">res</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">()).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(setUser);</span></span>
<span class="line"><span style="color:#B392F0">    fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`/api/notifications/${</span><span style="color:#E1E4E8">userId</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">res</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">()).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(setNotifications);</span></span>
<span class="line"><span style="color:#E1E4E8">    </span></span>
<span class="line"><span style="color:#F97583">    if</span><span style="color:#E1E4E8"> (user?.lastLogin </span><span style="color:#F97583">&lt;</span><span style="color:#E1E4E8"> Date.</span><span style="color:#B392F0">now</span><span style="color:#E1E4E8">() </span><span style="color:#F97583">-</span><span style="color:#79B8FF"> 30</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> 24</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> 60</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> 60</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> 1000</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#B392F0">      sendReactivationEmail</span><span style="color:#E1E4E8">(user);</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#E1E4E8">  }, [userId]);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#F97583">    &lt;</span><span style="color:#E1E4E8">div style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{{ </span><span style="color:#B392F0">backgroundColor</span><span style="color:#E1E4E8">: user?.isPremium </span><span style="color:#F97583">?</span><span style="color:#9ECBFF"> &#39;gold&#39;</span><span style="color:#F97583"> :</span><span style="color:#9ECBFF"> &#39;white&#39;</span><span style="color:#E1E4E8"> }}</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#B392F0">h1</span><span style="color:#E1E4E8">&gt;{user?.firstName} {</span><span style="color:#FFAB70">user</span><span style="color:#E1E4E8">?.</span><span style="color:#FFAB70">lastName</span><span style="color:#E1E4E8">}</span><span style="color:#F97583">&lt;/</span><span style="color:#E1E4E8">h1</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#B392F0">p</span><span style="color:#E1E4E8">&gt;</span><span style="color:#FFAB70">Status</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> {</span><span style="color:#B392F0">user</span><span style="color:#E1E4E8">?.</span><span style="color:#B392F0">age</span><span style="color:#E1E4E8"> &gt;= </span><span style="color:#79B8FF">18</span><span style="color:#F97583"> ?</span><span style="color:#9ECBFF"> &#39;Adult&#39;</span><span style="color:#F97583"> :</span><span style="color:#9ECBFF"> &#39;Minor&#39;</span><span style="color:#E1E4E8">}&lt;/</span><span style="color:#B392F0">p</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#B392F0">div</span><span style="color:#E1E4E8">&gt;{notifications.map(</span><span style="color:#FFAB70">n</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">p</span><span style="color:#B392F0"> key</span><span style="color:#E1E4E8">={</span><span style="color:#B392F0">n</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">id</span><span style="color:#E1E4E8">}&gt;{n.message}</span><span style="color:#F97583">&lt;</span><span style="color:#9ECBFF">/</span><span style="color:#DBEDFF">p&gt;)}&lt;</span><span style="color:#9ECBFF">/</span><span style="color:#F97583">div</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/div&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// ✅ Same component, but separated concerns</span></span>
<span class="line"><span style="color:#E1E4E8">const </span><span style="color:#B392F0">UserDashboard</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> ({ </span><span style="color:#FFAB70">userId</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">user</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">loading</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useUser</span><span style="color:#E1E4E8">(userId);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">notifications</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useNotifications</span><span style="color:#E1E4E8">(userId);</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (loading) </span><span style="color:#F97583">return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">LoadingSpinner</span><span style="color:#E1E4E8"> /&gt;;</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#B392F0">UserProfile</span><span style="color:#B392F0"> user</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">user</span><span style="color:#E1E4E8">} </span><span style="color:#B392F0">notifications</span><span style="color:#E1E4E8">={</span><span style="color:#FFAB70">notifications</span><span style="color:#E1E4E8">} /&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Common Pitfall:</strong> Creating too many layers of separation for simple operations, making code harder to follow.</p>
<hr/>
<h2 id="summary">Summary</h2>
<p>That’s <strong>The Foundation</strong> - the core principles every developer should master. These fundamentals will take you far in writing clean, maintainable code.</p>
<p><strong>Coming next:</strong> <a href="./2025-07-19--understand-acronym-spaghetti-part-2-quality-principles">Part 2</a> covers <strong>Code Quality &amp; Safety</strong> principles, and <a href="./2025-07-20--understand-acronym-spaghetti-part-3-solid-principles">Part 3</a> dives into <strong>SOLID Architecture</strong> patterns.</p>
<p>Remember: <strong>good code is not about showing off how smart you are - it’s about making life easier for the next person who reads it (including future you).</strong></p>]]></content:encoded>
    </item>
    <item>
      <title>Building a CLI to Automate Etsy Listings with AI and Fetch Hacks</title>
      <link>https://letanure.dev/writing/ai-powered-etsy-pipeline-claude-nodejs/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/ai-powered-etsy-pipeline-claude-nodejs/</guid>
      <pubDate>Sun, 13 Jul 2025 00:00:00 GMT</pubDate>
      <description>I built an AI-powered CLI to help my girlfriend publish 80+ handmade tattoo artworks on Etsy, skipping the forms, API delays, and automation traps.</description>
      <content:encoded><![CDATA[<h1 id="building-a-cli-to-automate-etsy-listings-with-ai-and-fetch-hacks">Building a CLI to Automate Etsy Listings with AI and Fetch Hacks</h1>
<p>My GF is a tattoo artist that paints and creates several art objects. She had around 140 product photos and needed some help to put her products on Etsy, but there were too many products, and the forms are complex.</p>
<p>So I decided to help. This was the perfect opportunity to leverage AI tools - Claude Code as my pair programmer, OpenAI’s vision models for product analysis, and MCP tools for context management.</p>
<p>What started as “maybe I can automate this” turned into a full AI-powered CLI that orchestrates multiple AI services: Claude Code helped me architect the solution, GPT-4 Vision analyzed product images, and custom MCP tools ensured consistent Etsy-compliant data generation.</p>
<p>2 days of AI-assisted development. Here’s how I solved it.</p>
<h2 id="the-plan-that-didnt-work">The plan (that didn’t work)</h2>
<p>My plan was to use the Etsy API. Applied for the API key, but they are slow to answer.</p>
<p>So I first generated some JSON with the data, but the content was not good, varying too much.</p>
<p>I tried some approaches to group images of the same product, but wasn’t happy with the coding solutions or AI solutions, so I abandoned that for this phase.</p>
<h2 id="ai-powered-structured-data-generation">AI-powered structured data generation</h2>
<p>This is where AI really shined. Instead of fighting inconsistent text generation, I turned to the AI SDK with structured output - letting the AI do what it does best while constraining it to exactly what I needed.</p>
<p>I changed my approach, used node ai-sdk + zod schemas to pass a predetermined JSON format. This was classic problem-solving: the AI was giving me the right content, but in the wrong format. So I gave it structure.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { z } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &quot;zod&quot;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { generateObject } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &quot;ai&quot;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> ProductSchema</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> z.</span><span style="color:#B392F0">object</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">  title: z.</span><span style="color:#B392F0">string</span><span style="color:#E1E4E8">().</span><span style="color:#B392F0">max</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">140</span><span style="color:#E1E4E8">),</span></span>
<span class="line"><span style="color:#E1E4E8">  description: z.</span><span style="color:#B392F0">string</span><span style="color:#E1E4E8">().</span><span style="color:#B392F0">max</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">1000</span><span style="color:#E1E4E8">),</span></span>
<span class="line"><span style="color:#E1E4E8">  tags: z.</span><span style="color:#B392F0">array</span><span style="color:#E1E4E8">(z.</span><span style="color:#B392F0">string</span><span style="color:#E1E4E8">()).</span><span style="color:#B392F0">max</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">13</span><span style="color:#E1E4E8">),</span></span>
<span class="line"><span style="color:#E1E4E8">  category: z.</span><span style="color:#B392F0">string</span><span style="color:#E1E4E8">(),</span></span>
<span class="line"><span style="color:#E1E4E8">  materials: z.</span><span style="color:#B392F0">array</span><span style="color:#E1E4E8">(z.</span><span style="color:#B392F0">string</span><span style="color:#E1E4E8">()),</span></span>
<span class="line"><span style="color:#E1E4E8">  style: z.</span><span style="color:#B392F0">string</span><span style="color:#E1E4E8">(),</span></span>
<span class="line"><span style="color:#E1E4E8">  price: z.</span><span style="color:#B392F0">number</span><span style="color:#E1E4E8">(),</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> result</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> generateObject</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">  model: </span><span style="color:#B392F0">openai</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;gpt-4&quot;</span><span style="color:#E1E4E8">),</span></span>
<span class="line"><span style="color:#E1E4E8">  schema: ProductSchema,</span></span>
<span class="line"><span style="color:#E1E4E8">  prompt: </span><span style="color:#9ECBFF">`Generate Etsy product data for this image: ${</span><span style="color:#E1E4E8">imageData</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<p>But I had the problem of the specific values. I tried to send them to the OpenAI API, but the model was losing context, so I used the tool / MCP to give the possible values to the API.</p>
<p>This is where my problem-solving approach with AI really paid off. Instead of cramming everything into prompts and hoping the AI would remember Etsy’s specific categories and materials, I built MCP tools that could provide that context on-demand. The AI could now ask for valid options when it needed them.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// MCP tool to get valid Etsy categories</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> getCategoriesFunction</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  name: </span><span style="color:#9ECBFF">&quot;getValidCategories&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  description: </span><span style="color:#9ECBFF">&quot;Get valid Etsy category options&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  parameters: { type: </span><span style="color:#9ECBFF">&quot;object&quot;</span><span style="color:#E1E4E8">, properties: {} },</span></span>
<span class="line"><span style="color:#B392F0">  execute</span><span style="color:#E1E4E8">: () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> etsy_categories,</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// Now the AI could ask for valid options</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> prompt</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> `</span></span>
<span class="line"><span style="color:#9ECBFF">Generate product data for this image.</span></span>
<span class="line"><span style="color:#9ECBFF">Use the getValidCategories tool to ensure correct category selection.</span></span>
<span class="line"><span style="color:#9ECBFF">`</span><span style="color:#E1E4E8">;</span></span></code></pre>
<p>After several iterations, refining the tone, what to describe, checking best practices for titles, tags, descriptions, I got a good version of text, and with the MCP, the values like style, materials, to generate a good JSON with all the data.</p>
<p>This iterative approach with AI is crucial - you don’t get perfect results on the first try. Each iteration taught me something new about how to prompt the AI, how to structure the data, and what constraints were actually needed. The AI became more useful the more I understood how to work with it.</p>
<h2 id="puppeteer-was-a-trap">Puppeteer was a trap</h2>
<p>My plan was to use puppeteer to fill the data, but after some tries, I discovered that Etsy is really good at blocking puppeteer automation… and to make puppeteer fill the form in the right way, was giving too much work, adjusting sequence, ids, selectors…</p>
<p>I was planning to go for a browser Claude controlled to fill the data, but decided for a simpler approach.</p>
<p>This is where good problem-solving beats brute force automation. Instead of fighting Etsy’s anti-bot measures, I stepped back and thought: what’s actually happening when someone creates a product? I created a fake draft product, inspected the network to see the request, and found that it was all created in a single request. Gotcha!</p>
<p>Sometimes the best solution is the simplest one - and AI helped me generate clean, working fetch scripts instead of battling complex browser automation.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="javascript"><code><span class="line"><span style="color:#6A737D">// Generated fetch script</span></span>
<span class="line"><span style="color:#B392F0">fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;/api/v3/application/shops/12345/listings&quot;</span><span style="color:#E1E4E8">, {</span></span>
<span class="line"><span style="color:#E1E4E8">  method: </span><span style="color:#9ECBFF">&quot;POST&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  headers: {</span></span>
<span class="line"><span style="color:#9ECBFF">    &quot;Content-Type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;application/json&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#9ECBFF">    &quot;X-Requested-With&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;XMLHttpRequest&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#E1E4E8">  body: </span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">    title: </span><span style="color:#9ECBFF">&quot;Handmade Abstract Canvas Art&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    description: </span><span style="color:#9ECBFF">&quot;...&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    tags: [</span><span style="color:#9ECBFF">&quot;abstract&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#9ECBFF">&quot;canvas&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#9ECBFF">&quot;art&quot;</span><span style="color:#E1E4E8">],</span></span>
<span class="line"><span style="color:#6A737D">    // ... all the AI-generated data</span></span>
<span class="line"><span style="color:#E1E4E8">  })</span></span>
<span class="line"><span style="color:#E1E4E8">})</span></span>
<span class="line"><span style="color:#E1E4E8">  .</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">r</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> r.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">())</span></span>
<span class="line"><span style="color:#E1E4E8">  .</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">d</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;Created:&quot;</span><span style="color:#E1E4E8">, d.listing_id));</span></span></code></pre>
<p>I decided to just generate fetch scripts that I can copy paste to the dev tools console and create products, no worries about login, CORS, etc.</p>
<p>Worked like a charm since the first version (just some minor adjustments in the script to avoid some nulls and malformed strings).</p>
<h2 id="adding-photoroom-integration">Adding photoroom integration</h2>
<p>One thing that I decided to add, was some image generation too.</p>
<p>2 weeks ago I created a photoroom CLI tool to remove background for images, and I decided to integrate this in the flow, generating liveshoot images, images without backgrounds and a clear, standard view for all photos across products.</p>
<p><strong>For each image:</strong></p>
<ol>
<li>Resize to low-quality for AI analysis (save tokens)</li>
<li>Resize to 2000x2000 for Photoroom processing</li>
<li>Generate product data with AI</li>
<li>Create image variants with Photoroom</li>
<li>Save everything to organized folders</li>
</ol>
<h2 id="the-final-ai-orchestrated-pipeline">The final AI-orchestrated pipeline</h2>
<p>This is where all the AI pieces came together beautifully. What started as a manual problem became a fully automated AI pipeline:</p>
<p>Drop a lot of images in a folder, run a terminal script.</p>
<p>My AI-powered app will read all images, and for each one:</p>
<ul>
<li>Resize the image to low quality, to send to OpenAI, saving tokens</li>
<li>Resize to a 2000x2000 px to send to photoroom, to generate one snapshot, one live photo, one image without background</li>
<li>Send the smallest image to OpenAI, generate the specific data with Zod format, validated</li>
<li>Send the image and generate the final versions</li>
<li>Save all, images, script to insert, JSON data, a text version, to an output folder, one folder for each product, with SKU as folder name, the SKU was generated based on the product data, using an MCP tool. All with logs.</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">node</span><span style="color:#9ECBFF"> generate-products.js</span></span>
<span class="line"><span style="color:#6A737D"># Outputs:</span></span>
<span class="line"><span style="color:#6A737D"># ./output/SKU-ART-001/</span></span>
<span class="line"><span style="color:#6A737D">#   ├── images/</span></span>
<span class="line"><span style="color:#6A737D">#   ├── product-data.json</span></span>
<span class="line"><span style="color:#6A737D">#   ├── etsy-script.js</span></span>
<span class="line"><span style="color:#6A737D">#   ├── description.txt</span></span>
<span class="line"><span style="color:#6A737D">#   └── logs.txt</span></span></code></pre>
<p>After generating all, around 80 products, got nice, cleaner, consistent product descriptions. Happy dev, happy girlfriend. Just checking the products, probably will be published tomorrow.</p>
<p>Ahh… one last idea I added.</p>
<p>I decided to use the generated images to create some image-to-videos, but was not happy with any API, so I added one extra info in the generated txt, a small video prompt, that matches the product and defined style, to generate the videos, after some tries, got really good videos, but was not possible to generate for all, because expired tokens on Veo 3.</p>
<h2 id="what-worked">What worked</h2>
<ul>
<li><strong>2 days</strong> replaced what would have been a month+ of manual work</li>
<li><strong>Around 80 products</strong> from 140 images</li>
<li><strong>Consistent descriptions</strong> and tone</li>
<li><strong>Professional image variants</strong> for each product</li>
<li><strong>Copy-paste automation</strong> that actually works</li>
<li><strong>Happy girlfriend</strong> (most important metric)</li>
</ul>
<h2 id="what-i-will-do-different-in-the-future">What I will do different in the future?</h2>
<ul>
<li>Some pre-classification of the images, sometimes the AI got wrong about size, materials</li>
<li>Store in a database, not files, but was ok for an exploration project</li>
</ul>
<h2 id="what-i-learned-about-ai-assisted-problem-solving">What I learned about AI-assisted problem solving</h2>
<ul>
<li><strong>AI works best with constraints</strong>: Free-form AI output is inconsistent. Structured output with Zod schemas gives you the power of AI with the reliability of typed data.</li>
<li><strong>MCP tools are game-changers</strong>: Instead of bloating prompts with context, give AI tools to fetch what it needs. This scales much better and keeps prompts focused.</li>
<li><strong>Claude Code as a pair programmer</strong>: Having an AI that understands your codebase and can suggest architectural decisions speeds up development significantly.</li>
<li><strong>Iterative AI refinement</strong>: The first AI output is never perfect. Plan for multiple iterations to tune prompts, constraints, and data structures.</li>
<li><strong>Simple solutions beat complex automation</strong>: Sometimes the best approach is to step back, understand the problem differently, and let AI generate the simple solution.</li>
<li><strong>Real problems make the best AI projects</strong>: When you’re solving actual pain points, you iterate faster and build more useful tools.</li>
</ul>
<h2 id="tech-stack">Tech stack</h2>
<p>Node.js, AI SDK, Zod, Photoroom API, ImageMagick, Claude Code, MCP tools, bash.</p>
<hr/>
<p>I was planning to go even further, make a single script that will get the data for each one, so I run one time and fill one at a time automagically, but sounded too much… the copy paste was not a problem for a one time (maybe) job, and I can always evolve later.</p>
<p>This project reinforced something important about working with AI: the goal isn’t to build the most technically impressive solution. It’s to solve the problem efficiently. AI helped me build exactly what was needed, nothing more.</p>
<p>Sometimes the simple AI-generated solution wins.</p>
<p>Products go live tomorrow.</p>]]></content:encoded>
    </item>
    <item>
      <title>Building photoroom-cli with Claude Code: From API to NPM in 3 Days</title>
      <link>https://letanure.dev/writing/building-photoroom-cli-with-claude-code/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/building-photoroom-cli-with-claude-code/</guid>
      <pubDate>Thu, 10 Jul 2025 00:00:00 GMT</pubDate>
      <description>How I built photoroom-cli using Claude Code as my pair programmer. Lessons about AI-assisted development, balancing speed with quality, and the art of guided coding.</description>
      <content:encoded><![CDATA[<h1 id="building-a-cli-tool-with-claude-code-from-api-to-npm-in-3-days">Building a CLI Tool with Claude Code: From API to NPM in 3 Days</h1>
<p>I wanted to practice pair programming with Claude Code—but I needed a real project. Not a todo app. Not a playground. Something small, useful, and publishable.</p>
<p>Photoroom has a clean, AI-powered API for image editing—but no CLI. That was the gap. It’s a useful service, the docs are great, and the scope felt just right for a solo dev experiment.</p>
<p><img src="https://raw.githubusercontent.com/letanure/photoroom-cli/main/docs/demo.gif" alt="photoroom-cli demo"/></p>
<h2 id="figuring-out-what-to-build">Figuring out what to build</h2>
<p>The real challenge wasn’t coding—it was design.</p>
<p>After a rough first draft of the main commands, I started building a minimal TUI—separating it into clear use cases: background removal, AI-generated backgrounds, and API key setup.</p>
<p>Most of the endpoints are straightforward, but the image editing one has a lot of parameters. Some of them should just appear if another one has a specific value. Trying to reduce this complexity to a simple TUI interface was one of the biggest challenges, and it wasn’t about coding only, but about how to organize the info and make it simple for the user.</p>
<h2 id="working-with-claude-code">Working with Claude Code</h2>
<p>Claude helped me explore different ways to implement TUI interfaces quickly. When Claude generated disorganized code, first I let it go. After repetition, I started iterating to find useful and good abstractions and patterns.</p>
<p>This became the rhythm: let Claude explore, then I’d reorganize and extract reusable components.</p>
<h2 id="claude-code-is-fasttoo-fast">Claude Code is Fast—Too Fast</h2>
<p>Claude Code works fast. Too fast.</p>
<p>Lots of times, Claude was implementing full features, without thinking about reusing parts or patterns. On refactorings and code analysis, I was moving parts, reorganizing stuff, and forcing Claude to reuse in other parts.</p>
<p>This taught me something important: working with Claude, the coding skills need to be used differently. More guiding, reviewing, defining rules.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// Claude&#39;s first attempt - works but not reusable</span></span>
<span class="line"><span style="color:#F97583">async</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> removeBackground</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">imagePath</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> questions</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> [</span></span>
<span class="line"><span style="color:#E1E4E8">    { type: </span><span style="color:#9ECBFF">&quot;input&quot;</span><span style="color:#E1E4E8">, name: </span><span style="color:#9ECBFF">&quot;output&quot;</span><span style="color:#E1E4E8">, message: </span><span style="color:#9ECBFF">&quot;Output filename?&quot;</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#E1E4E8">    { type: </span><span style="color:#9ECBFF">&quot;list&quot;</span><span style="color:#E1E4E8">, name: </span><span style="color:#9ECBFF">&quot;format&quot;</span><span style="color:#E1E4E8">, choices: [</span><span style="color:#9ECBFF">&quot;png&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#9ECBFF">&quot;jpg&quot;</span><span style="color:#E1E4E8">] },</span></span>
<span class="line"><span style="color:#E1E4E8">  ];</span></span>
<span class="line"><span style="color:#6A737D">  // ... implementation</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// After refactoring - reusable question patterns</span></span>
<span class="line"><span style="color:#F97583">async</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> askQuestions</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">T</span><span style="color:#E1E4E8">&gt;(</span><span style="color:#FFAB70">config</span><span style="color:#F97583">:</span><span style="color:#B392F0"> QuestionConfig</span><span style="color:#E1E4E8">[])</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">T</span><span style="color:#E1E4E8">&gt; {</span></span>
<span class="line"><span style="color:#6A737D">  // Generic question handler that all features can use</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>I learned to establish patterns early and force consistency across modules. The AI is incredibly productive, but human oversight ensures the code remains maintainable.</p>
<h2 id="making-it-simple-for-users">Making it simple for users</h2>
<p>I started as simple as possible: a menu for each endpoint, asking all the parameters. Later, I grouped them better, focused on the most important, used, required ones, and put the others as optional.</p>
<p>“Do you want to edit the background?” to avoid forcing the user to answer all params that they don’t need most of the time.</p>
<p>After that, I added validation and complex TUI interfaces, like file selection.</p>
<p>The biggest challenge wasn’t coding—it was information architecture.</p>
<h2 id="security-and-polish-with-ai">Security and Polish with AI</h2>
<p>Claude Code helped implement sophisticated features I might have skipped:</p>
<p><strong>Encrypted API Key Management:</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// AI helped design secure key storage</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> encrypt</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">text</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">key</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Buffer</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> EncryptedData</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> iv</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> crypto.</span><span style="color:#B392F0">randomBytes</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">16</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> cipher</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> crypto.</span><span style="color:#B392F0">createCipher</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;aes-256-gcm&quot;</span><span style="color:#E1E4E8">, key);</span></span>
<span class="line"><span style="color:#6A737D">  // ... secure implementation</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p><strong>Error Handling:</strong>
Claude generated comprehensive error scenarios I hadn’t considered. The AI’s systematic approach to edge cases made the tool more robust than I would have built alone.</p>
<p><strong>CI/CD Pipeline:</strong>
Setting up automated testing, releases, and even Claude Code Review integration in the CI pipeline. The AI helped configure modern tooling I was less familiar with.</p>
<h2 id="what-i-learned">What I learned</h2>
<p>One quote I kept thinking about during this build:</p>
<blockquote>
<p>“AI makes 80% of my coding skills almost useless,<br/>
but makes the other 20% 80× more important.”</p>
</blockquote>
<p>So, it’s not about typing code anymore, but saying what to create, defining a good architecture, evaluating the results, having more freedom to explore paths, go forward or rollback when necessary.</p>
<p>Coding with Claude isn’t about typing—it’s about reviewing, refactoring, and maintaining structure. AI accelerates output, but you still have to think about what’s worth building, and how it fits together.</p>
<h2 id="the-publishing-experience">The Publishing Experience</h2>
<p>Getting from working code to published NPM package involved:</p>
<ul>
<li>TypeScript configuration for proper exports</li>
<li>Testing setup with Vitest</li>
<li>Documentation and examples</li>
<li>CI/CD for automated releases</li>
</ul>
<p>Claude Code helped with the technical setup, but the decisions about what to include, how to organize it, and what the user experience should be—that was human judgment.</p>
<h2 id="building-for-others">Building for others</h2>
<p>I didn’t promote the project much, so feedback was limited. But it reminded me that building useful tools isn’t enough—you have to tell people. Shipping is just the first half. Sharing is the second.</p>
<h2 id="results">Results</h2>
<ul>
<li><strong>Published to NPM</strong>: <a href="https://www.npmjs.com/package/photoroom-cli">https://www.npmjs.com/package/photoroom-cli</a></li>
<li><strong>Open source</strong>: <a href="https://github.com/letanure/photoroom-cli">https://github.com/letanure/photoroom-cli</a></li>
<li><strong>Real users</strong>: Solving actual problems for other developers</li>
<li><strong>3 days</strong>: From idea to published package</li>
</ul>
<h2 id="key-takeaways">Key Takeaways</h2>
<ol>
<li><strong>AI coding requires different skills</strong>: More guiding, reviewing, defining rules</li>
<li><strong>Speed vs. quality balance</strong>: Let AI explore, then human reorganization</li>
<li><strong>Pattern enforcement</strong>: Establish consistency early and maintain it</li>
<li><strong>Focus on hard problems</strong>: Let AI handle implementation, you handle design</li>
<li><strong>Build for real users</strong>: Even practice projects should solve real problems</li>
</ol>
<blockquote>
<p>“AI makes 80% of my coding skills almost useless, but makes the other 20% 80× more important.”</p>
</blockquote>
<p>That one line sums up this project better than anything else.</p>
<p>The future of development isn’t human vs. AI—it’s human with AI. The challenge is learning how to be a better conductor of the AI orchestra.</p>
<h2 id="tech-stack">Tech Stack</h2>
<p>Node.js, TypeScript, Yargs, Enquirer, Vitest, GitHub Actions, and of course, Claude Code as my pair programmer.</p>
<p>Sometimes the best “practice” is something small that real people can use. That’s what this was. A fast build, a solid CLI, and one more tool out in the wild.</p>]]></content:encoded>
    </item>
    <item>
      <title>At-Least-Once vs. Exactly-Once - Understanding Message Delivery Guarantees</title>
      <link>https://letanure.dev/writing/at-least-once-vs-exactly-once/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/at-least-once-vs-exactly-once/</guid>
      <pubDate>Thu, 12 Jun 2025 00:00:00 GMT</pubDate>
      <description>Learn about message delivery guarantees in distributed systems. Understand why most production systems implement at-least-once delivery with idempotency rather than attempting exactly-once delivery.</description>
      <content:encoded><![CDATA[<h1 id="at-least-once-vs-exactly-once-understanding-message-delivery-guarantees">At-Least-Once vs. Exactly-Once: Understanding Message Delivery Guarantees</h1>
<p>In distributed systems, when performing critical operations such as webhook delivery, job processing, or payment recording, a fundamental question arises:</p>
<blockquote>
<p><strong>How many times can this operation be executed?</strong></p>
</blockquote>
<p>The answer to this question determines your system’s reliability and consistency guarantees.</p>
<hr/>
<h2 id="at-least-once-delivery">At-Least-Once Delivery</h2>
<p><strong>Definition</strong>: The system guarantees that an operation will be executed at least once, with the possibility of multiple executions.</p>
<h3 id="characteristics">Characteristics</h3>
<ul>
<li>Widely adopted in production systems</li>
<li>Common in message queues: RabbitMQ, Kafka, Supabase Realtime</li>
<li>Requires idempotent operation handlers</li>
<li>Supports automatic retries on failure</li>
<li>Simpler to implement and maintain</li>
</ul>
<h3 id="implementation-example">Implementation Example</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#6A737D">// Webhook handler with idempotency</span></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> async</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> POST</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">req</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Request</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> event</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> req.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#6A737D">  // 1. Check for duplicate processing</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">data</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">existingEvent</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> supabase</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">from</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;webhook_logs&#39;</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">select</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;*&#39;</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">eq</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;event_id&#39;</span><span style="color:#E1E4E8">, event.id)</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">maybeSingle</span><span style="color:#E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (existingEvent) {</span></span>
<span class="line"><span style="color:#6A737D">    // Event already processed, return success</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Response</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;Event already processed&#39;</span><span style="color:#E1E4E8">, { status: </span><span style="color:#79B8FF">200</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">  // 2. Record the event before processing</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">error</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">insertError</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> supabase</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">from</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;webhook_logs&#39;</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">insert</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">      event_id: event.id,</span></span>
<span class="line"><span style="color:#E1E4E8">      payload: event,</span></span>
<span class="line"><span style="color:#E1E4E8">      status: </span><span style="color:#9ECBFF">&#39;processing&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">      created_at: </span><span style="color:#F97583">new</span><span style="color:#B392F0"> Date</span><span style="color:#E1E4E8">().</span><span style="color:#B392F0">toISOString</span><span style="color:#E1E4E8">()</span></span>
<span class="line"><span style="color:#E1E4E8">    });</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (insertError) {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Response</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;Failed to record event&#39;</span><span style="color:#E1E4E8">, { status: </span><span style="color:#79B8FF">500</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  try</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">    // 3. Process the event</span></span>
<span class="line"><span style="color:#F97583">    await</span><span style="color:#B392F0"> processEvent</span><span style="color:#E1E4E8">(event);</span></span>
<span class="line"><span style="color:#E1E4E8">    </span></span>
<span class="line"><span style="color:#6A737D">    // 4. Update event status</span></span>
<span class="line"><span style="color:#F97583">    await</span><span style="color:#E1E4E8"> supabase</span></span>
<span class="line"><span style="color:#E1E4E8">      .</span><span style="color:#B392F0">from</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;webhook_logs&#39;</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8">      .</span><span style="color:#B392F0">update</span><span style="color:#E1E4E8">({ status: </span><span style="color:#9ECBFF">&#39;completed&#39;</span><span style="color:#E1E4E8"> })</span></span>
<span class="line"><span style="color:#E1E4E8">      .</span><span style="color:#B392F0">eq</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;event_id&#39;</span><span style="color:#E1E4E8">, event.id);</span></span>
<span class="line"><span style="color:#E1E4E8">      </span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Response</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;Event processed successfully&#39;</span><span style="color:#E1E4E8">, { status: </span><span style="color:#79B8FF">200</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">  } </span><span style="color:#F97583">catch</span><span style="color:#E1E4E8"> (error) {</span></span>
<span class="line"><span style="color:#6A737D">    // 5. Handle processing errors</span></span>
<span class="line"><span style="color:#F97583">    await</span><span style="color:#E1E4E8"> supabase</span></span>
<span class="line"><span style="color:#E1E4E8">      .</span><span style="color:#B392F0">from</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;webhook_logs&#39;</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8">      .</span><span style="color:#B392F0">update</span><span style="color:#E1E4E8">({ </span></span>
<span class="line"><span style="color:#E1E4E8">        status: </span><span style="color:#9ECBFF">&#39;failed&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">        error: error.message </span></span>
<span class="line"><span style="color:#E1E4E8">      })</span></span>
<span class="line"><span style="color:#E1E4E8">      .</span><span style="color:#B392F0">eq</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;event_id&#39;</span><span style="color:#E1E4E8">, event.id);</span></span>
<span class="line"><span style="color:#E1E4E8">      </span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Response</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;Event processing failed&#39;</span><span style="color:#E1E4E8">, { status: </span><span style="color:#79B8FF">500</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>This implementation ensures that:</p>
<ol>
<li>Duplicate events are detected and handled gracefully</li>
<li>Event processing is tracked and can be monitored</li>
<li>Failures are properly recorded</li>
<li>The system can recover from errors</li>
</ol>
<hr/>
<h2 id="exactly-once-delivery">Exactly-Once Delivery</h2>
<p><strong>Definition</strong>: The system guarantees that an operation will be executed exactly once, no more and no less.</p>
<h3 id="challenges">Challenges</h3>
<ul>
<li>Extremely difficult to implement in distributed systems</li>
<li>Requires complex coordination across:
<ul>
<li>Network layers</li>
<li>State management</li>
<li>Retry mechanisms</li>
<li>Transaction boundaries</li>
</ul>
</li>
<li>Significant performance overhead</li>
<li>Often unnecessary for most use cases</li>
</ul>
<p>Even major platforms like Stripe, Kafka, and AWS don’t implement exactly-once delivery by default. Instead, they rely on at-least-once delivery combined with idempotent operations.</p>
<hr/>
<h2 id="real-world-applications">Real-World Applications</h2>
<p>These delivery guarantees are crucial in several scenarios:</p>
<h3 id="1-webhook-delivery">1. Webhook Delivery</h3>
<ul>
<li>External service notifications</li>
<li>Payment processing callbacks</li>
<li>Integration events</li>
</ul>
<h3 id="2-background-job-processing">2. Background Job Processing</h3>
<ul>
<li>Email sending</li>
<li>Report generation</li>
<li>Data synchronization</li>
</ul>
<h3 id="3-side-effects">3. Side Effects</h3>
<ul>
<li>Inventory updates</li>
<li>Receipt generation</li>
<li>Payout processing</li>
</ul>
<h3 id="4-event-processing">4. Event Processing</h3>
<ul>
<li>User notifications</li>
<li>Audit logging</li>
<li>System state changes</li>
</ul>
<hr/>
<h2 id="best-practices-for-at-least-once-systems">Best Practices for At-Least-Once Systems</h2>
<ol>
<li>
<p><strong>Implement Idempotent Operations</strong></p>
<ul>
<li>Use unique identifiers for operations</li>
<li>Check for existing results before processing</li>
<li>Use atomic operations where possible</li>
</ul>
</li>
<li>
<p><strong>Track Operation State</strong></p>
<ul>
<li>Record operation IDs</li>
<li>Track event processing status</li>
<li>Maintain audit logs</li>
</ul>
</li>
<li>
<p><strong>Handle Duplicates</strong></p>
<ul>
<li>Implement deduplication logic</li>
<li>Use database constraints</li>
<li>Maintain operation logs</li>
</ul>
</li>
<li>
<p><strong>Design for Retries</strong></p>
<ul>
<li>Implement exponential backoff</li>
<li>Set reasonable retry limits</li>
<li>Handle partial failures</li>
</ul>
</li>
</ol>
<hr/>
<h2 id="summary">Summary</h2>























<table><thead><tr><th>Delivery Type</th><th>Guarantees</th><th>Implementation Complexity</th><th>Use Cases</th></tr></thead><tbody><tr><td>At-Least-Once</td><td>Will execute ≥1 times</td><td>Moderate</td><td>Most production systems</td></tr><tr><td>Exactly-Once</td><td>Will execute =1 time</td><td>High</td><td>Rare, specific cases</td></tr></tbody></table>
<p>For most production systems, the recommended approach is:</p>
<ol>
<li>Implement at-least-once delivery</li>
<li>Design idempotent operation handlers</li>
<li>Implement proper retry mechanisms</li>
<li>Maintain comprehensive logging</li>
</ol>
<p>This combination provides the reliability and consistency needed for production systems while maintaining reasonable complexity and performance characteristics.</p>]]></content:encoded>
    </item>
    <item>
      <title>How Idempotency Saves Your API from Chaos</title>
      <link>https://letanure.dev/writing/idempotency-api-chaos/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/idempotency-api-chaos/</guid>
      <pubDate>Wed, 11 Jun 2025 00:00:00 GMT</pubDate>
      <description>Learn how to implement idempotency in your APIs to prevent duplicate actions and ensure data consistency. Includes practical examples with Supabase and Node.js.</description>
      <content:encoded><![CDATA[<h1 id="understanding-api-idempotency-a-practical-guide">Understanding API Idempotency: A Practical Guide</h1>
<p>Idempotency is a crucial concept in API design that ensures:</p>
<blockquote>
<p><strong>Making the same request multiple times produces the same result without side effects.</strong></p>
</blockquote>
<p>This means that if a client sends the same request twice (or more), the system should handle it gracefully without creating duplicate records or causing unintended consequences. Think of it like a light switch: pressing it multiple times doesn’t create multiple lights—it just toggles the same light on or off.</p>
<h2 id="why-idempotency-matters">Why Idempotency Matters</h2>
<h3 id="the-double-charge-problem">The Double-Charge Problem</h3>
<p>Consider this common e-commerce scenario:</p>
<ol>
<li>A user clicks “Pay $100” on a mobile app</li>
<li>The network connection is unstable</li>
<li>The user doesn’t see a response</li>
<li>They click again</li>
<li><strong>Result</strong>: The user gets charged $200 instead of $100</li>
</ol>
<p>This is a real problem that affects user trust and can lead to:</p>
<ul>
<li>Customer support tickets</li>
<li>Refund requests</li>
<li>Loss of customer trust</li>
<li>Potential legal issues</li>
</ul>
<h3 id="the-reload-problem">The Reload Problem</h3>
<p>Another common issue occurs in booking systems:</p>
<ol>
<li>User fills out a hotel booking form</li>
<li>Page generates a new <code>bookingId = &quot;booking_123&quot;</code></li>
<li>User clicks “Confirm Booking” but the request fails</li>
<li>User reloads the page</li>
<li>A new <code>bookingId = &quot;booking_456&quot;</code> is generated</li>
<li>User clicks “Confirm Booking” again</li>
<li><strong>Result</strong>: Two separate bookings are created for the same room and dates</li>
</ol>
<h2 id="implementing-idempotency">Implementing Idempotency</h2>
<h3 id="client-side-implementation">Client-Side Implementation</h3>
<p>The key is to generate and persist a stable ID that represents the user’s intent. Here’s a React hook that handles this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#6A737D">// useIdempotentAction.ts</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { useState, useEffect } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;react&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { v4 </span><span style="color:#F97583">as</span><span style="color:#E1E4E8"> uuidv4 } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;uuid&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> UseIdempotentActionProps</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  actionKey</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;  </span><span style="color:#6A737D">// e.g., &#39;booking&#39;, &#39;payment&#39;, &#39;subscription&#39;</span></span>
<span class="line"><span style="color:#B392F0">  onSuccess</span><span style="color:#F97583">?:</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#79B8FF"> void</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> useIdempotentAction</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">actionKey</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">onSuccess</span><span style="color:#E1E4E8"> }</span><span style="color:#F97583">:</span><span style="color:#B392F0"> UseIdempotentActionProps</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">actionId</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setActionId</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">&lt;</span><span style="color:#79B8FF">string</span><span style="color:#E1E4E8">&gt;(</span><span style="color:#9ECBFF">&#39;&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> storageKey</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> `${</span><span style="color:#E1E4E8">actionKey</span><span style="color:#9ECBFF">}-id`</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">  useEffect</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">    // Try to retrieve existing action ID</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> saved</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> localStorage.</span><span style="color:#B392F0">getItem</span><span style="color:#E1E4E8">(storageKey);</span></span>
<span class="line"><span style="color:#F97583">    if</span><span style="color:#E1E4E8"> (saved) {</span></span>
<span class="line"><span style="color:#B392F0">      setActionId</span><span style="color:#E1E4E8">(saved);</span></span>
<span class="line"><span style="color:#E1E4E8">    } </span><span style="color:#F97583">else</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">      // Generate new ID if none exists</span></span>
<span class="line"><span style="color:#F97583">      const</span><span style="color:#79B8FF"> newId</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> uuidv4</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#E1E4E8">      localStorage.</span><span style="color:#B392F0">setItem</span><span style="color:#E1E4E8">(storageKey, newId);</span></span>
<span class="line"><span style="color:#B392F0">      setActionId</span><span style="color:#E1E4E8">(newId);</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#E1E4E8">  }, [storageKey]);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> clearActionId</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">    localStorage.</span><span style="color:#B392F0">removeItem</span><span style="color:#E1E4E8">(storageKey);</span></span>
<span class="line"><span style="color:#B392F0">    setActionId</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#B392F0">    onSuccess</span><span style="color:#E1E4E8">?.();</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> { actionId, clearActionId };</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Usage in a booking component:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#6A737D">// BookingForm.tsx</span></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> BookingForm</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">actionId</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">clearActionId</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useIdempotentAction</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">    actionKey: </span><span style="color:#9ECBFF">&#39;booking&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#B392F0">    onSuccess</span><span style="color:#E1E4E8">: () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">      // Show success message</span></span>
<span class="line"><span style="color:#6A737D">      // Redirect to confirmation page</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#E1E4E8">  });</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> handleSubmit</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">formData</span><span style="color:#F97583">:</span><span style="color:#B392F0"> BookingFormData</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    try</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">      const</span><span style="color:#79B8FF"> response</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;/api/bookings&#39;</span><span style="color:#E1E4E8">, {</span></span>
<span class="line"><span style="color:#E1E4E8">        method: </span><span style="color:#9ECBFF">&#39;POST&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">        headers: {</span></span>
<span class="line"><span style="color:#9ECBFF">          &#39;Content-Type&#39;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&#39;application/json&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#9ECBFF">          &#39;Idempotency-Key&#39;</span><span style="color:#E1E4E8">: actionId</span></span>
<span class="line"><span style="color:#E1E4E8">        },</span></span>
<span class="line"><span style="color:#E1E4E8">        body: </span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#F97583">          ...</span><span style="color:#E1E4E8">formData,</span></span>
<span class="line"><span style="color:#E1E4E8">          idempotencyKey: actionId</span></span>
<span class="line"><span style="color:#E1E4E8">        })</span></span>
<span class="line"><span style="color:#E1E4E8">      });</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">      if</span><span style="color:#E1E4E8"> (response.ok) {</span></span>
<span class="line"><span style="color:#B392F0">        clearActionId</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#E1E4E8">      }</span></span>
<span class="line"><span style="color:#E1E4E8">    } </span><span style="color:#F97583">catch</span><span style="color:#E1E4E8"> (error) {</span></span>
<span class="line"><span style="color:#6A737D">      // Handle error</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">form</span><span style="color:#B392F0"> onSubmit</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{handleSubmit}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      {</span><span style="color:#6A737D">/* Form fields */</span><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">form</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h3 id="why-client-side-id-generation">Why Client-Side ID Generation?</h3>
<p>The client is the best place to generate the ID because:</p>
<ol>
<li><strong>Intent Tracking</strong>: It knows the exact moment of user intent</li>
<li><strong>State Persistence</strong>: It can persist the ID across page reloads</li>
<li><strong>Retry Management</strong>: It can track retry attempts</li>
<li><strong>Industry Standard</strong>: It follows the pattern used by industry leaders like Stripe and PayPal</li>
</ol>
<h2 id="practical-implementation-with-supabase">Practical Implementation with Supabase</h2>
<h3 id="client-side-code">Client-Side Code</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#6A737D">// api/bookings.ts</span></span>
<span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> BookingRequest</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  roomId</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  checkIn</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  checkOut</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  guestInfo</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">    name</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">    email</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">async</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> createBooking</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">bookingData</span><span style="color:#F97583">:</span><span style="color:#B392F0"> BookingRequest</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">idempotencyKey</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> response</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;/api/bookings&#39;</span><span style="color:#E1E4E8">, {</span></span>
<span class="line"><span style="color:#E1E4E8">    method: </span><span style="color:#9ECBFF">&#39;POST&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    headers: { </span></span>
<span class="line"><span style="color:#9ECBFF">      &#39;Content-Type&#39;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&#39;application/json&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#9ECBFF">      &#39;Idempotency-Key&#39;</span><span style="color:#E1E4E8">: idempotencyKey</span></span>
<span class="line"><span style="color:#E1E4E8">    },</span></span>
<span class="line"><span style="color:#E1E4E8">    body: </span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#F97583">      ...</span><span style="color:#E1E4E8">bookingData,</span></span>
<span class="line"><span style="color:#E1E4E8">      idempotencyKey</span></span>
<span class="line"><span style="color:#E1E4E8">    })</span></span>
<span class="line"><span style="color:#E1E4E8">  });</span></span>
<span class="line"><span style="color:#E1E4E8">  </span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">response.ok) {</span></span>
<span class="line"><span style="color:#F97583">    throw</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Error</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;Booking failed&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> response.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h3 id="server-side-code">Server-Side Code</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#6A737D">// pages/api/bookings.ts</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { createClient } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;@supabase/supabase-js&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> supabase</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> createClient</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#E1E4E8">  process.env.</span><span style="color:#79B8FF">NEXT_PUBLIC_SUPABASE_URL</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  process.env.</span><span style="color:#79B8FF">SUPABASE_SERVICE_KEY</span><span style="color:#F97583">!</span></span>
<span class="line"><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> async</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> handler</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">req</span><span style="color:#F97583">:</span><span style="color:#B392F0"> NextApiRequest</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#F97583">:</span><span style="color:#B392F0"> NextApiResponse</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (req.method </span><span style="color:#F97583">!==</span><span style="color:#9ECBFF"> &#39;POST&#39;</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">status</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">405</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">({ error: </span><span style="color:#9ECBFF">&#39;Method not allowed&#39;</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">idempotencyKey</span><span style="color:#E1E4E8">, </span><span style="color:#F97583">...</span><span style="color:#79B8FF">bookingData</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> req.body;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  try</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D">    // First, check if we&#39;ve already processed this request</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">data</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">existingBooking</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> supabase</span></span>
<span class="line"><span style="color:#E1E4E8">      .</span><span style="color:#B392F0">from</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;bookings&#39;</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8">      .</span><span style="color:#B392F0">select</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;*&#39;</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8">      .</span><span style="color:#B392F0">eq</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;idempotency_key&#39;</span><span style="color:#E1E4E8">, idempotencyKey)</span></span>
<span class="line"><span style="color:#E1E4E8">      .</span><span style="color:#B392F0">single</span><span style="color:#E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">    if</span><span style="color:#E1E4E8"> (existingBooking) {</span></span>
<span class="line"><span style="color:#6A737D">      // Return the existing booking</span></span>
<span class="line"><span style="color:#F97583">      return</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">status</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">200</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">(existingBooking);</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">    // Process new booking</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">data</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">error</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> supabase</span></span>
<span class="line"><span style="color:#E1E4E8">      .</span><span style="color:#B392F0">from</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;bookings&#39;</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8">      .</span><span style="color:#B392F0">insert</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#F97583">        ...</span><span style="color:#E1E4E8">bookingData,</span></span>
<span class="line"><span style="color:#E1E4E8">        idempotency_key: idempotencyKey,</span></span>
<span class="line"><span style="color:#E1E4E8">        status: </span><span style="color:#9ECBFF">&#39;confirmed&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">        created_at: </span><span style="color:#F97583">new</span><span style="color:#B392F0"> Date</span><span style="color:#E1E4E8">().</span><span style="color:#B392F0">toISOString</span><span style="color:#E1E4E8">()</span></span>
<span class="line"><span style="color:#E1E4E8">      })</span></span>
<span class="line"><span style="color:#E1E4E8">      .</span><span style="color:#B392F0">select</span><span style="color:#E1E4E8">()</span></span>
<span class="line"><span style="color:#E1E4E8">      .</span><span style="color:#B392F0">single</span><span style="color:#E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">    if</span><span style="color:#E1E4E8"> (error) {</span></span>
<span class="line"><span style="color:#F97583">      throw</span><span style="color:#E1E4E8"> error;</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">status</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">201</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">(data);</span></span>
<span class="line"><span style="color:#E1E4E8">  } </span><span style="color:#F97583">catch</span><span style="color:#E1E4E8"> (error) {</span></span>
<span class="line"><span style="color:#E1E4E8">    console.</span><span style="color:#B392F0">error</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;Booking error:&#39;</span><span style="color:#E1E4E8">, error);</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">status</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">500</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">({ error: </span><span style="color:#9ECBFF">&#39;Booking failed&#39;</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h2 id="best-practices-for-idempotency">Best Practices for Idempotency</h2>
<ol>
<li>
<p><strong>Generate Stable IDs</strong></p>
<ul>
<li>Use UUIDs (v4) for uniqueness</li>
<li>Include a prefix for different action types (e.g., <code>booking_</code>, <code>payment_</code>)</li>
<li>Store them in localStorage, cookies, or session storage</li>
<li>Clear them after confirmed success</li>
</ul>
</li>
<li>
<p><strong>Handle Edge Cases</strong></p>
<ul>
<li>Network failures and timeouts</li>
<li>Page reloads and browser crashes</li>
<li>Multiple clicks and rapid retries</li>
<li>Concurrent requests</li>
</ul>
</li>
<li>
<p><strong>Server-Side Considerations</strong></p>
<ul>
<li>Use database constraints and unique indexes</li>
<li>Implement proper error handling and logging</li>
<li>Set appropriate timeouts for idempotency keys</li>
<li>Consider using a distributed cache (Redis) for high-traffic systems</li>
</ul>
</li>
<li>
<p><strong>Security Considerations</strong></p>
<ul>
<li>Validate idempotency keys</li>
<li>Set expiration times for keys</li>
<li>Implement rate limiting</li>
<li>Log suspicious patterns</li>
</ul>
</li>
</ol>
<h2 id="summary">Summary</h2>
<p>Idempotency is not about preventing duplicate requests—it’s about handling them gracefully. A well-designed system should:</p>
<ul>
<li>Accept the same request multiple times</li>
<li>Process it only once</li>
<li>Return the same result each time</li>
<li>Maintain data consistency</li>
<li>Handle errors gracefully</li>
</ul>
<p>Remember:</p>
<blockquote>
<p>Your job isn’t to block duplicates.<br/>
Your job is to make sure they don’t hurt anyone.</p>
</blockquote>
<p>By implementing proper idempotency, you create a more resilient system that can handle real-world scenarios like:</p>
<ul>
<li>Poor network conditions</li>
<li>User impatience</li>
<li>Browser refreshes</li>
<li>Mobile app backgrounding</li>
<li>Service interruptions</li>
</ul>
<p>This leads to:</p>
<ul>
<li>Better user experience</li>
<li>Fewer support tickets</li>
<li>More reliable systems</li>
<li>Happier customers</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Vibe Coding ‑ Notes from the First Try</title>
      <link>https://letanure.dev/writing/vibe-coding/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/vibe-coding/</guid>
      <pubDate>Fri, 06 Jun 2025 00:00:00 GMT</pubDate>
      <description>Quick lessons from spinning up a new blog with an AI pair‑programmer and Cursor.</description>
      <content:encoded><![CDATA[<p>You can build a working blog in a weekend.<br/>
I did it using <strong>Cursor</strong> and an AI pair‑programmer.</p>
<h2 id="what-worked">What worked</h2>
<ul>
<li>
<p><strong>Speed</strong><br/>
I had a template running in minutes.<br/>
Live reload kept the loop short.</p>
</li>
<li>
<p><strong>Focused prompts</strong><br/>
Short, clear requests gave better code.<br/>
One task at a time.</p>
</li>
<li>
<p><strong>Hands‑on fixes</strong><br/>
When type errors showed up, I jumped in and patched them fast.<br/>
No waiting for another answer.</p>
</li>
</ul>
<h2 id="what-hurt">What hurt</h2>
<ul>
<li>
<p><strong>Out‑of‑date examples</strong><br/>
The assistant knows only what was public at its last crawl.<br/>
New package versions need manual checks.</p>
</li>
<li>
<p><strong>Over‑eager edits</strong><br/>
I asked for a sidebar tweak; it rewired other files and broke the build.<br/>
I learned to halt the run early.</p>
</li>
<li>
<p><strong>Constraint drift</strong><br/>
“Do not add package X.”<br/>
Ten minutes later, package X popped back.<br/>
Keep an eye on <code>package.json</code>.</p>
</li>
<li>
<p><strong>TypeScript drift</strong><br/>
As the codebase grew, generated types lagged.<br/>
I had to prune old code.</p>
</li>
</ul>
<h2 id="pro-tips">Pro tips</h2>
<ul>
<li>Write a <code>.nvmrc</code> early.</li>
<li>Add a smoke test that runs <code>next build</code> before each commit or push.</li>
<li>Keep <code>prompt.md</code>,  rules file or notepad with all active constraints.</li>
<li>Stop the assistant if it touches files outside the task.</li>
<li>Commit small and often.</li>
</ul>
<h2 id="final-thoughts">Final thoughts</h2>
<p>AI pair‑programming is an interesting shortcut, but it won’t replace real craft For now.<br/>
You still need multiple projects to master the flow, bigger teams get messy, and the output quality matches the developer’s own skills—otherwise you may end up with a basic scaffold that you could have built faster with a simple <strong>git clone</strong>.</p>]]></content:encoded>
    </item>
    <item>
      <title>20 Years in Front-End – Lessons on Simplicity and Accessibility</title>
      <link>https://letanure.dev/writing/20-years-front-end-lessons/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/20-years-front-end-lessons/</guid>
      <pubDate>Sun, 01 Jun 2025 00:00:00 GMT</pubDate>
      <description>Timeless lessons from two decades building for the web – why simplicity, accessibility, and good UX still matter most.</description>
      <content:encoded><![CDATA[<p>Twenty years. That’s a long time in front-end.</p>
<p>In that time, we’ve gone from jQuery plugins and table layouts to React Server Components and Edge Functions. But some lessons don’t change. Here are the ones that stuck with me.</p>
<h2 id="1-keep-it-simple">1. Keep it simple</h2>
<p>Complexity breaks things. Users don’t care if you used the latest framework. They care that the site loads fast and works. Simple stacks are easier to debug, easier to maintain, and easier to hand off.</p>
<p>I’ve seen projects collapse under the weight of over-architecture. A hand-rolled toolchain, six layers of abstraction, and no one left to maintain it. Meanwhile, a plain HTML/CSS/JS version would have done the job.</p>
<h2 id="2-design-for-users-not-devs">2. Design for users, not devs</h2>
<p>Sometimes we get caught up solving our own problems. But front-end is about <em>users</em>. Every decision – from layout to color contrast – affects real people.</p>
<p>Example: a project I worked on had amazing animations and transitions. But users on low-end phones couldn’t use it. We stripped things down. The result was faster, more inclusive, and users actually stayed.</p>
<h2 id="3-accessibility-isnt-optional">3. Accessibility isn’t optional</h2>
<p>Making your app accessible helps everyone. Keyboard users. Screen readers. People on mobile in the sun. Accessibility isn’t a feature – it’s baseline.</p>
<p>Use semantic HTML. Add ALT text. Ensure keyboard navigation. Follow WCAG basics. These are not hard, and they go a long way.</p>
<p>One small win: we added proper labels and focus states to a booking form. Suddenly, conversion went up. Why? Because more people could actually complete it.</p>
<h2 id="4-learn-new-tools-but-trust-your-principles">4. Learn new tools, but trust your principles</h2>
<p>New frameworks will keep coming. Some good. Some overhyped. Learn them, but stay grounded. Your job isn’t to use the newest thing. Your job is to build things people can use.</p>
<p>Performance, clarity, and usefulness win every time.</p>
<h2 id="5-you-wont-remember-every-syntax-but-youll-remember-what-works">5. You won’t remember every syntax, but you’ll remember what works</h2>
<p>After two decades, I don’t remember every version of every tool I used. But I remember the bugs that cost me hours. The fixes that made a real difference. The tools that respected my time.</p>
<p>The tech changes. The value stays the same.</p>
<hr/>
<p>Thanks for reading. Whether you’re starting out or deep in your career, remember: people &gt; tools, clarity &gt; cleverness, and function &gt; flair.</p>]]></content:encoded>
    </item>
    <item>
      <title>The Meta-Framework Showdown – Angular, React, Vue in the New Era</title>
      <link>https://letanure.dev/writing/meta-framework-showdown/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/meta-framework-showdown/</guid>
      <pubDate>Sat, 01 Mar 2025 00:00:00 GMT</pubDate>
      <description>A comparison of Angular, React, and Vue in 2025, exploring how each evolved and what they offer today.</description>
      <content:encoded><![CDATA[<p>The front-end world has changed a lot in the past decade, but the “big three” frameworks—Angular, React, and Vue—are still going strong. In this post, I’ll go over what each looks like today and how they’ve adapted to new trends.</p>
<h2 id="angular-signals-and-standalone-components">Angular: Signals and Standalone Components</h2>
<p>Angular has seen major changes since v16+. It introduced:</p>
<ul>
<li><strong>Signals</strong>: for fine-grained reactivity, inspired by Solid and others.</li>
<li><strong>Standalone components</strong>: now you don’t need NgModules.</li>
<li>Better DX with faster builds and improved CLI.</li>
</ul>
<p>Angular is still popular in enterprise projects. It feels more modern now, but the learning curve is still there.</p>
<h2 id="react-server-components-and-the-app-router">React: Server Components and the App Router</h2>
<p>React kept evolving without changing its core too much. In the latest versions (React 18/19):</p>
<ul>
<li><strong>Server Components</strong> are now usable with frameworks like Next.js.</li>
<li><strong>Next.js App Router</strong> supports layouts, loading UI, and nested routing.</li>
<li><strong>startTransition</strong> and automatic batching help improve performance.</li>
</ul>
<p>React is still the default for many devs, especially when combined with Next.js or Remix.</p>
<h2 id="vue-composition-api-and-nuxt-3">Vue: Composition API and Nuxt 3</h2>
<p>Vue 3 is the default now, and the Composition API is standard:</p>
<ul>
<li>Easier logic reuse and better TypeScript support.</li>
<li>Nuxt 3 gives Vue apps a strong meta-framework.</li>
<li>Ecosystem is smaller than React’s, but focused.</li>
</ul>
<p>Vue remains the easiest to get started with, and is used a lot in Asia and by smaller teams.</p>
<h2 id="framework-stats">Framework Stats</h2>
<p>According to the latest State of JS results:</p>
<ul>
<li><strong>React</strong> is still most used.</li>
<li><strong>Vue</strong> has high satisfaction.</li>
<li><strong>Angular</strong> is stable in large teams, but not trending up.</li>
</ul>
<h2 id="which-one">Which One?</h2>
<p>If you want full control: go with React + Next.js.<br/>
If you want productivity and simplicity: try Vue + Nuxt.<br/>
If you’re in enterprise or need structure: Angular still delivers.</p>
<p>They’ve all improved a lot. Choose the one that fits your project and team.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Next-Gen Build Tools – Turbopacks and Beyond</title>
      <link>https://letanure.dev/writing/next-gen-build-tools-turbopack/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/next-gen-build-tools-turbopack/</guid>
      <pubDate>Wed, 01 Jan 2025 00:00:00 GMT</pubDate>
      <description>A look at Turbopack and the future of JavaScript build tooling in 2025.</description>
      <content:encoded><![CDATA[<p>Build tools are evolving again.</p>
<p>Webpack ruled the bundling world for years. Then came faster alternatives like Parcel, Rollup, and later, <strong>esbuild</strong> and <strong>Vite</strong> – built for speed and modern workflows.</p>
<p>Now, it’s <strong>Turbopack</strong>’s turn to shake things up.</p>
<h2 id="what-is-turbopack">What is Turbopack?</h2>
<p>Turbopack is a next-gen bundler created by the team at Vercel. It’s written in <strong>Rust</strong>, just like swc (which Vercel also maintains), and aims to be a <strong>Webpack replacement</strong> — but much faster.</p>
<p>Key features:</p>
<ul>
<li>Built with performance in mind</li>
<li>Native support for modern JS and TypeScript</li>
<li>Incremental compilation and caching</li>
<li>Great integration with <strong>Next.js</strong></li>
</ul>
<p>Turbopack is still early, but already being used in some production apps. It’s expected to become the default bundler for Next.js in the near future.</p>
<h2 id="how-does-it-compare">How does it compare?</h2>
<p>Here’s how some modern build tools stack up:</p>
<ul>
<li><strong>Webpack</strong>: powerful but slower, very flexible</li>
<li><strong>esbuild</strong>: ultra-fast but not as extensible</li>
<li><strong>swc</strong>: great for transforming code, used in many tools</li>
<li><strong>Vite</strong>: fast dev server using esbuild, with Rollup for production</li>
<li><strong>Turbopack</strong>: promises best of both worlds with Rust performance and deep framework integration</li>
</ul>
<h2 id="a-glimpse-at-the-future">A glimpse at the future</h2>
<p>We’re heading toward:</p>
<ul>
<li>Instant dev servers (cold start &lt; 100ms)</li>
<li>Smart dependency graphs and caching</li>
<li>Compile-less environments (e.g. native ESM in browsers)</li>
<li>Toolchains that work out of the box (zero-config)</li>
</ul>
<p>As we enter 2025, it’s clear developers care less about bundling theory and more about <strong>instant feedback</strong>, <strong>short feedback loops</strong>, and <strong>fewer moving parts</strong>.</p>
<p>Whether Turbopack becomes the new standard or not, it’s part of a wider move toward faster, leaner, more modern tooling.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Reflecting on Front-End Trends – What a Decade!</title>
      <link>https://letanure.dev/writing/reflecting-on-frontend-decade/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/reflecting-on-frontend-decade/</guid>
      <pubDate>Fri, 01 Nov 2024 00:00:00 GMT</pubDate>
      <description>A retrospective on 10 years of front-end evolution, from jQuery dominance to AI-assisted coding.</description>
      <content:encoded><![CDATA[<p>Ten years go by fast.</p>
<p>In 2014–2015, most of us were still using jQuery. SPAs were becoming more common, but not yet the norm. Frameworks like AngularJS and Backbone were popular. React was still new. TypeScript was just starting to get noticed.</p>
<p>A lot changed.</p>
<h2 id="what-changed">What changed</h2>
<ul>
<li><strong>2015–2016</strong>: ES6 became the standard. Arrow functions, <code>let</code>, <code>const</code>, and modules became everyday tools. Babel helped bridge the gap.</li>
<li><strong>2017–2019</strong>: Framework wars peaked. React matured fast, Vue gained fans, Angular (rewritten) lost some ground. GraphQL started gaining adoption.</li>
<li><strong>2020–2022</strong>: JAMstack got popular. Static generation with Next.js, Nuxt, Hugo, and newer tools like Astro redefined how we build sites. SSR/SSG hybrids became the default.</li>
<li><strong>2023–2024</strong>: Signals, edge rendering, and new runtimes like Bun started shifting how we think about performance. Deno, Vite, Qwik, Solid all challenged older models. AI started helping us code.</li>
</ul>
<h2 id="what-stayed">What stayed</h2>
<ul>
<li><strong>Good UX still matters.</strong> No matter the tool, fast, usable, accessible sites win.</li>
<li><strong>Simple code wins.</strong> Fewer abstractions, smaller bundles, faster sites.</li>
<li><strong>CSS got better.</strong> Container queries and <code>:has()</code> unlocked new layout power without hacks.</li>
</ul>
<h2 id="what-we-learned">What we learned</h2>
<ul>
<li>Don’t get too attached to one tool. The landscape keeps shifting.</li>
<li>Focus on fundamentals: HTML, CSS, JS, accessibility, and clean code.</li>
<li>Invest in learning patterns, not libraries.</li>
</ul>
<h2 id="whats-next">What’s next?</h2>
<p>Maybe frameworks will disappear. Maybe more things will run at the edge. Maybe AI writes 90% of our boilerplate.</p>
<p>But someone still has to make it usable.</p>
<p>So here’s to the next 10 years. And to whatever comes after React.</p>
]]></content:encoded>
    </item>
    <item>
      <title>WebGPU – Graphics Programming in the Browser</title>
      <link>https://letanure.dev/writing/webgpu-in-the-browser/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/webgpu-in-the-browser/</guid>
      <pubDate>Sun, 01 Sep 2024 00:00:00 GMT</pubDate>
      <description>A first look at WebGPU and how it opens new doors for high-performance graphics and computation in web applications.</description>
      <content:encoded><![CDATA[<p>WebGPU is a new web standard that brings modern GPU programming to the browser. It’s a successor to WebGL and is designed to be closer in capabilities to native graphics APIs like Vulkan, Metal, or DirectX 12.</p>
<p>Unlike WebGL, which is mainly for rendering graphics, WebGPU is also great for general-purpose GPU computing (GPGPU). That means you can use it not only for 3D scenes but also for high-performance tasks like physics simulations, image processing, and machine learning.</p>
<h2 id="why-webgpu-matters">Why WebGPU matters</h2>
<ul>
<li>More control over GPU pipelines</li>
<li>Better performance with lower-level access</li>
<li>Modern shader language (WGSL)</li>
<li>Access to compute shaders in the browser</li>
</ul>
<p>By 2023, WebGPU had started shipping in Chrome stable, and in 2024, more browsers are rolling it out or supporting it behind flags.</p>
<h2 id="simple-example--a-colored-triangle">Simple example – a colored triangle</h2>
<p>Here’s a minimal setup using WebGPU to render a triangle. This assumes WebGPU is supported and enabled in your browser.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> canvas</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> document.</span><span style="color:#B392F0">querySelector</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;canvas&#39;</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> adapter</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> navigator.gpu.</span><span style="color:#B392F0">requestAdapter</span><span style="color:#E1E4E8">()</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> device</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> adapter.</span><span style="color:#B392F0">requestDevice</span><span style="color:#E1E4E8">()</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> context</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> canvas.</span><span style="color:#B392F0">getContext</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;webgpu&#39;</span><span style="color:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> format</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> navigator.gpu.</span><span style="color:#B392F0">getPreferredCanvasFormat</span><span style="color:#E1E4E8">()</span></span>
<span class="line"><span style="color:#E1E4E8">context.</span><span style="color:#B392F0">configure</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">  device,</span></span>
<span class="line"><span style="color:#E1E4E8">  format</span></span>
<span class="line"><span style="color:#E1E4E8">})</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// Create a basic shader</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> shaderCode</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> `</span></span>
<span class="line"><span style="color:#9ECBFF">  @vertex</span></span>
<span class="line"><span style="color:#9ECBFF">  fn vs_main(@builtin(vertex_index) VertexIndex : u32)</span></span>
<span class="line"><span style="color:#9ECBFF">       -&gt; @builtin(position) vec4&lt;f32&gt; {</span></span>
<span class="line"><span style="color:#9ECBFF">    var pos = array&lt;vec2&lt;f32&gt;, 3&gt;(</span></span>
<span class="line"><span style="color:#9ECBFF">      vec2&lt;f32&gt;(0.0, 0.5),</span></span>
<span class="line"><span style="color:#9ECBFF">      vec2&lt;f32&gt;(-0.5, -0.5),</span></span>
<span class="line"><span style="color:#9ECBFF">      vec2&lt;f32&gt;(0.5, -0.5)</span></span>
<span class="line"><span style="color:#9ECBFF">    )</span></span>
<span class="line"><span style="color:#9ECBFF">    return vec4&lt;f32&gt;(pos[VertexIndex], 0.0, 1.0)</span></span>
<span class="line"><span style="color:#9ECBFF">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#9ECBFF">  @fragment</span></span>
<span class="line"><span style="color:#9ECBFF">  fn fs_main() -&gt; @location(0) vec4&lt;f32&gt; {</span></span>
<span class="line"><span style="color:#9ECBFF">    return vec4&lt;f32&gt;(1.0, 0.0, 0.0, 1.0)</span></span>
<span class="line"><span style="color:#9ECBFF">  }</span></span>
<span class="line"><span style="color:#9ECBFF">`</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> module</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> device.</span><span style="color:#B392F0">createShaderModule</span><span style="color:#E1E4E8">({ code: shaderCode })</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> pipeline</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> device.</span><span style="color:#B392F0">createRenderPipeline</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">  layout: </span><span style="color:#9ECBFF">&#39;auto&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  vertex: { module, entryPoint: </span><span style="color:#9ECBFF">&#39;vs_main&#39;</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#E1E4E8">  fragment: {</span></span>
<span class="line"><span style="color:#E1E4E8">    module,</span></span>
<span class="line"><span style="color:#E1E4E8">    entryPoint: </span><span style="color:#9ECBFF">&#39;fs_main&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    targets: [{ format }]</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#E1E4E8">  primitive: { topology: </span><span style="color:#9ECBFF">&#39;triangle-list&#39;</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">})</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> commandEncoder</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> device.</span><span style="color:#B392F0">createCommandEncoder</span><span style="color:#E1E4E8">()</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> textureView</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> context.</span><span style="color:#B392F0">getCurrentTexture</span><span style="color:#E1E4E8">().</span><span style="color:#B392F0">createView</span><span style="color:#E1E4E8">()</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> pass</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> commandEncoder.</span><span style="color:#B392F0">beginRenderPass</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">  colorAttachments: [{</span></span>
<span class="line"><span style="color:#E1E4E8">    view: textureView,</span></span>
<span class="line"><span style="color:#E1E4E8">    clearValue: { r: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">, g: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">, b: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">, a: </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#E1E4E8">    loadOp: </span><span style="color:#9ECBFF">&#39;clear&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    storeOp: </span><span style="color:#9ECBFF">&#39;store&#39;</span></span>
<span class="line"><span style="color:#E1E4E8">  }]</span></span>
<span class="line"><span style="color:#E1E4E8">})</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">pass.</span><span style="color:#B392F0">setPipeline</span><span style="color:#E1E4E8">(pipeline)</span></span>
<span class="line"><span style="color:#E1E4E8">pass.</span><span style="color:#B392F0">draw</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">3</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8">pass.</span><span style="color:#B392F0">end</span><span style="color:#E1E4E8">()</span></span>
<span class="line"><span style="color:#E1E4E8">device.queue.</span><span style="color:#B392F0">submit</span><span style="color:#E1E4E8">([commandEncoder.</span><span style="color:#B392F0">finish</span><span style="color:#E1E4E8">()])</span></span></code></pre>
<h2 id="learning-curve">Learning curve</h2>
<p>Working with WebGPU means writing shaders in WGSL and managing your rendering pipeline manually. It’s more verbose than WebGL, but it’s also much more powerful and flexible.</p>
<p>If you’re familiar with lower-level graphics APIs or GPU compute frameworks, you’ll find WebGPU familiar. If not, start small, like with the triangle example above.</p>
<h2 id="what-to-explore-next">What to explore next</h2>
<ul>
<li>Compute shaders for non-graphics tasks</li>
<li>Integrating with React or other frameworks</li>
<li>Animations and post-processing</li>
<li>Using WebGPU in frameworks like Babylon.js or Three.js (early support)</li>
</ul>
<p>WebGPU is still new, but it’s stable enough to experiment with today.</p>
]]></content:encoded>
    </item>
    <item>
      <title>AI-Assisted Development – One Year with GitHub Copilot</title>
      <link>https://letanure.dev/writing/ai-assisted-development/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/ai-assisted-development/</guid>
      <pubDate>Sat, 01 Jun 2024 00:00:00 GMT</pubDate>
      <description>Reflections on one year of using GitHub Copilot, its benefits, limitations, and practical tips for front-end developers.</description>
      <content:encoded><![CDATA[<p>AI pair-programming tools are no longer hype. After using GitHub Copilot daily for over a year, I can say it’s changed how I code – and not just in small ways.</p>
<h2 id="what-copilot-helps-with">What Copilot Helps With</h2>
<p>Here’s where Copilot saves me time every day:</p>
<ul>
<li><strong>Boilerplate</strong> – It writes out <code>useEffect</code>, <code>useState</code>, API call scaffolding, even basic CSS and Tailwind classes.</li>
<li><strong>Unknown syntax</strong> – If I vaguely remember how to write a Prisma query or a new regex pattern, it fills the gap.</li>
<li><strong>Test cases</strong> – I write a function, and it often autocompletes good test scenarios using Vitest or Jest.</li>
<li><strong>String manipulation or parsing</strong> – These are boring. Copilot makes them fast.</li>
<li><strong>Markdown, README, docs</strong> – I don’t love writing these, but Copilot makes suggestions to speed it up.</li>
</ul>
<h2 id="what-copilot-gets-wrong">What Copilot Gets Wrong</h2>
<p>Copilot isn’t magic. It guesses.</p>
<ul>
<li>It sometimes makes things up.</li>
<li>You still need to verify logic and types.</li>
<li>It might pull in patterns that are outdated or not idiomatic.</li>
<li>It doesn’t understand the big picture of your code – only what’s around your cursor.</li>
</ul>
<h2 id="how-to-use-it-well">How to Use It Well</h2>
<ul>
<li><strong>Be active</strong> – Treat Copilot like a junior pair. Let it start, but you edit.</li>
<li><strong>Edit heavily</strong> – Use suggestions as a base. Don’t trust without reading.</li>
<li><strong>Avoid for sensitive or license-restricted code</strong> – Generated output might not be safe to copy blindly.</li>
</ul>
<h2 id="overall-impact">Overall Impact</h2>
<p>After a year, I’m more productive. I write more. I finish side projects faster. I explore unfamiliar libraries without getting blocked.</p>
<p>The key? I use it as a boost, not a crutch.</p>
<p>Copilot won’t replace you. But it can help you code more, try more, and learn faster – if you drive the process.</p>
]]></content:encoded>
    </item>
    <item>
      <title>The Rise of Signals – Solid, Qwik, and React’s New RFC</title>
      <link>https://letanure.dev/writing/rise-of-signals/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/rise-of-signals/</guid>
      <pubDate>Mon, 01 Apr 2024 00:00:00 GMT</pubDate>
      <description>A look into how signals are changing state management in modern frameworks like Solid, Qwik, and even React.</description>
      <content:encoded><![CDATA[<p>Signals are becoming one of the most discussed ideas in front-end frameworks lately.</p>
<p>They offer a lightweight, fine-grained reactivity model. Unlike traditional state systems like <code>useState</code> in React, signals let you track and react to changes at a lower cost.</p>
<h2 id="what-are-signals">What Are Signals?</h2>
<p>A signal is a reactive value. You create it once, and when it changes, everything that uses it updates automatically.</p>
<p>In SolidJS:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { createSignal } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &quot;solid-js&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">count</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setCount</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> createSignal</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// Reactive usage</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;Count: {</span><span style="color:#B392F0">count</span><span style="color:#E1E4E8">()}&lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> onClick</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{() </span><span style="color:#F97583">=&gt;</span><span style="color:#B392F0"> setCount</span><span style="color:#E1E4E8">(</span><span style="color:#B392F0">count</span><span style="color:#E1E4E8">() </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">)}&gt;Increment&lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>This is different from React’s model, which needs rerendering the whole component to update the UI.</p>
<h2 id="why-use-signals">Why Use Signals?</h2>
<ul>
<li>Fine-grained updates (only parts that need to change will change)</li>
<li>Better performance for large or reactive UIs</li>
<li>More declarative and less boilerplate</li>
</ul>
<h2 id="qwik-and-resumability">Qwik and Resumability</h2>
<p>Qwik also uses signals at its core, but it adds resumability on top. That means it doesn’t hydrate the whole app—only the parts the user interacts with.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { component$, useSignal } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &quot;@builder.io/qwik&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> const</span><span style="color:#79B8FF"> Counter</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> component$</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> count</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> useSignal</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#F97583">    &lt;</span><span style="color:#E1E4E8">button onClick$</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{() =&gt; count.value++}</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#FFAB70">      Count</span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> {</span><span style="color:#B392F0">count</span><span style="color:#E1E4E8">.</span><span style="color:#FFAB70">value</span><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#F97583">    &lt;/</span><span style="color:#E1E4E8">button</span><span style="color:#F97583">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  )</span></span>
<span class="line"><span style="color:#E1E4E8">})</span></span></code></pre>
<p>This makes Qwik fast even on large apps, as only interactive components are hydrated.</p>
<h2 id="reacts-signals-rfc">React’s Signals RFC?</h2>
<p>React’s core team is also considering a signals-like pattern. While it’s still early, the discussion shows interest in moving toward more efficient reactivity in the long run.</p>
<h2 id="developer-satisfaction">Developer Satisfaction</h2>
<p>Frameworks like Solid and Qwik consistently report very high satisfaction in developer surveys. Once developers try signals, they often don’t want to go back.</p>
<h2 id="final-thoughts">Final Thoughts</h2>
<p>Signals aren’t just a trend. They represent a shift toward more efficient, scalable UI logic. Whether you’re using Solid, Qwik, or waiting for React’s version, it’s worth learning this pattern now.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Is React Still King? – State of JS/React 2023 Insights</title>
      <link>https://letanure.dev/writing/is-react-still-king/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/is-react-still-king/</guid>
      <pubDate>Thu, 01 Feb 2024 00:00:00 GMT</pubDate>
      <description>React remains dominant, but new frameworks and patterns are gaining attention. What should you focus on next?</description>
      <content:encoded><![CDATA[<p>Every year, the State of JS and State of React surveys provide a snapshot of how developers feel about front-end tools.</p>
<p>React continues to be the most used front-end library.</p>
<p>But the surveys also reveal growing curiosity about alternatives like:</p>
<ul>
<li><strong>SolidJS</strong> – praised for speed and fine-grained reactivity</li>
<li><strong>Qwik</strong> – focused on resumability and instant loading</li>
<li><strong>Alpine.js</strong> – popular in smaller, simpler projects</li>
<li><strong>Web Components</strong> – used in larger orgs through tools like Lit or Stencil</li>
</ul>
<p>React isn’t losing popularity, but the ecosystem is more diverse.</p>
<p>Many teams now evaluate whether React is the right choice based on:</p>
<ul>
<li>Bundle size</li>
<li>Build complexity</li>
<li>Interactivity needs</li>
<li>Team familiarity</li>
</ul>
<p>React has evolved with:</p>
<ul>
<li>Server Components (RSC)</li>
<li>Streaming support</li>
<li>App Router in Next.js</li>
<li>More async-aware APIs</li>
</ul>
<p>If you’re starting a new project, this is a good time to:</p>
<ul>
<li>Reassess your framework needs</li>
<li>Try out a small experiment with Solid or Qwik</li>
<li>Explore RSC to simplify server+client logic</li>
</ul>
<p>The front-end landscape is more open than ever.</p>
<p>React remains strong—but it’s no longer the only path worth exploring.</p>]]></content:encoded>
    </item>
    <item>
      <title>Low-Code and No-Code – Threat or Boon for Developers?</title>
      <link>https://letanure.dev/writing/low-code-no-code/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/low-code-no-code/</guid>
      <pubDate>Wed, 01 Nov 2023 00:00:00 GMT</pubDate>
      <description>A balanced take on the rise of no-code/low-code tools and what they mean for front-end developers.</description>
      <content:encoded><![CDATA[<p>Low-code and no-code platforms are everywhere now.</p>
<p>You’ve probably seen tools like:</p>
<ul>
<li>Webflow for websites</li>
<li>Bubble for apps</li>
<li>Airtable, Notion, Zapier as automation backbones</li>
</ul>
<p>They promise to make it easy for anyone to build apps or automate workflows, without needing to write code. And many of them deliver—especially for internal tools, landing pages, or quick prototypes.</p>
<p>So… are they a threat to developers?</p>
<h3 id="the-shift">The shift</h3>
<p>Over the past few years, low-code/no-code platforms have grown fast.</p>
<p>Some reasons why:</p>
<ul>
<li>Businesses want to move faster</li>
<li>Developers are expensive</li>
<li>Many internal apps don’t need custom UIs</li>
</ul>
<p>At the same time, these tools have become more powerful. You can now connect databases, write conditional logic, embed APIs, and even design full UIs visually.</p>
<p>Some developers use them too—especially for:</p>
<ul>
<li>Admin dashboards</li>
<li>MVPs</li>
<li>Workflow automations</li>
</ul>
<h3 id="what-theyre-good-at">What they’re good at</h3>
<ul>
<li>Building fast</li>
<li>Empowering non-technical users</li>
<li>Reducing time-to-launch</li>
<li>Standardized tasks (forms, CRUD, integrations)</li>
</ul>
<p>They shine when you need to build something simple and repeatable.</p>
<h3 id="where-they-fall-short">Where they fall short</h3>
<ul>
<li>Custom design and complex UI logic</li>
<li>Performance tuning</li>
<li>Maintainability at scale</li>
<li>Clean code, versioning, collaboration</li>
</ul>
<p>Even with extensions or code injection, you’ll eventually hit a ceiling. That’s when developers step in.</p>
<h3 id="should-you-worry">Should you worry?</h3>
<p>No.</p>
<p>Developers still build the tools that power low-code platforms. We still:</p>
<ul>
<li>Design systems</li>
<li>Write custom components</li>
<li>Build APIs</li>
<li>Solve edge cases</li>
</ul>
<p>Low-code shifts who can build <em>some</em> things. It doesn’t remove the need for custom solutions.</p>
<p>If anything, it makes developer skills even more valuable. You can work faster, build better abstractions, and help teams scale.</p>
<h3 id="what-to-do">What to do</h3>
<p>Instead of ignoring it:</p>
<ul>
<li>Learn how these tools work</li>
<li>Use them for non-critical workflows</li>
<li>Know when to recommend them</li>
<li>Keep building custom stuff where needed</li>
</ul>
<p>Low-code is just another tool. Know its limits. Know your strengths.</p>
<p>They don’t replace you. But they do change the landscape.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Modern CSS – Container Queries and :has() in Action</title>
      <link>https://letanure.dev/writing/modern-css-container-has/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/modern-css-container-has/</guid>
      <pubDate>Sun, 01 Oct 2023 00:00:00 GMT</pubDate>
      <description>A look at how container queries and the :has() selector open new doors for responsive and contextual styling in CSS.</description>
      <content:encoded><![CDATA[<p>Two major features have made their way into modern CSS: <strong>container queries</strong> and the <code>:has()</code> selector. Together, they unlock new ways to write styles that are more flexible, modular, and context-aware.</p>
<h2 id="what-are-container-queries">What are Container Queries?</h2>
<p>Container queries allow components to adapt based on the <strong>size of their container</strong>, not the entire viewport. This is a game-changer for building reusable, responsive components.</p>
<p>Here’s a basic example:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#B392F0">.card</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  container-type</span><span style="color:#E1E4E8">: inline-size;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">@container</span><span style="color:#E1E4E8"> (min-width: 400px) {</span></span>
<span class="line"><span style="color:#B392F0">  .card</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">    flex-direction</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">row</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>With this, <code>.card</code> changes its layout only when its <strong>container</strong> is wider than 400px, not the whole screen. You can use it in grids, toolbars, cards, and nested components.</p>
<h2 id="what-is-has">What is <code>:has()</code>?</h2>
<p>The <code>:has()</code> selector is like a parent selector – it applies styles to elements <strong>based on their children</strong>.</p>
<p>Example:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#85E89D">form</span><span style="color:#B392F0">:has</span><span style="color:#E1E4E8">(</span><span style="color:#85E89D">input</span><span style="color:#B392F0">:invalid</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#79B8FF">  border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#79B8FF"> red</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>This applies a red border to the whole <code>form</code> if any of its inputs are invalid. Another use:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#85E89D">label</span><span style="color:#B392F0">:has</span><span style="color:#E1E4E8">(</span><span style="color:#F97583">+</span><span style="color:#85E89D"> input</span><span style="color:#B392F0">:focus</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#79B8FF">  font-weight</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">bold</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>This bolds a label when its associated input is focused.</p>
<h2 id="why-this-matters">Why This Matters</h2>
<ul>
<li>Container queries help components behave <strong>independently</strong>, especially useful in design systems.</li>
<li><code>:has()</code> gives us a clean way to react to user interaction <strong>without JS</strong>.</li>
<li>Support for both features is now solid in evergreen browsers.</li>
</ul>
<h2 id="tools-and-usage-tips">Tools and Usage Tips</h2>
<ul>
<li>
<p>Use <code>@supports</code> to check for availability:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#F97583">@supports</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">container-type</span><span style="color:#E1E4E8">: inline-size) {</span></span>
<span class="line"><span style="color:#6A737D">  /* safe to use container queries */</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
</li>
<li>
<p>Consider pairing with utility-first CSS like Tailwind (which now supports container queries in some setups).</p>
</li>
</ul>
<p>Modern CSS keeps evolving fast. These features reduce the need for JavaScript or complex class toggles and make styling cleaner and more powerful.</p>
]]></content:encoded>
    </item>
    <item>
      <title>SolidJS and Signals – A Different Reactivity</title>
      <link>https://letanure.dev/writing/solidjs-signals-reactivity/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/solidjs-signals-reactivity/</guid>
      <pubDate>Thu, 01 Jun 2023 00:00:00 GMT</pubDate>
      <description>Exploring SolidJS&apos;s fine-grained reactivity model and how it differs from virtual DOM frameworks.</description>
      <content:encoded><![CDATA[<p>SolidJS is a front-end framework that takes a different path than React or Vue. It doesn’t use a virtual DOM. Instead, it relies on fine-grained reactivity powered by signals.</p>
<h3 id="why-signals">Why Signals?</h3>
<p>In Solid, signals are reactive values that automatically update your UI when they change.</p>
<p>Here’s a simple example:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { createSignal } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &quot;solid-js&quot;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> Counter</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">count</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setCount</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> createSignal</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;Count: {</span><span style="color:#B392F0">count</span><span style="color:#E1E4E8">()}&lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> onClick</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{() </span><span style="color:#F97583">=&gt;</span><span style="color:#B392F0"> setCount</span><span style="color:#E1E4E8">(</span><span style="color:#B392F0">count</span><span style="color:#E1E4E8">() </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">)}&gt;Increment&lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Unlike React, you don’t write <code>useState</code> and <code>useEffect</code>. The component is reactive by default. <code>count()</code> triggers re-renders only where it’s used, not the entire component.</p>
<h3 id="how-solid-differs">How Solid Differs</h3>
<ul>
<li>No virtual DOM</li>
<li>Compile-time optimizations</li>
<li>Fine-grained reactive updates</li>
<li>Small bundle sizes</li>
</ul>
<h3 id="solid-vs-react">Solid vs React</h3>
<p>React updates components as a whole. Solid updates DOM nodes directly. This results in better performance for many use cases, especially smaller projects or embedded widgets.</p>
<h3 id="signals-everywhere">Signals Everywhere</h3>
<p>Solid’s model is gaining attention. Other frameworks are also exploring signal-based reactivity:</p>
<ul>
<li><strong>Preact</strong> introduced <code>signals</code> as an experiment</li>
<li><strong>Vue</strong> has its <code>ref()</code> API</li>
<li><strong>Qwik</strong> uses resumable reactivity</li>
</ul>
<p>Developers are now exploring frameworks that prioritize performance with minimal abstraction.</p>
<h3 id="when-to-use-solid">When to Use Solid</h3>
<p>Use Solid if you:</p>
<ul>
<li>Care a lot about runtime performance</li>
<li>Are building small or medium apps</li>
<li>Want simpler mental models for reactivity</li>
<li>Like JSX but want more control</li>
</ul>
<p>Solid is not trying to replace React but offers a clean and fast alternative where simplicity and speed matter most.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Bun 1.0 – Testing a Turbo-Fast JS Runtime</title>
      <link>https://letanure.dev/writing/bun-1.0-runtime-review/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/bun-1.0-runtime-review/</guid>
      <pubDate>Sat, 01 Apr 2023 00:00:00 GMT</pubDate>
      <description>Exploring Bun 1.0 – a fast JavaScript runtime, bundler, and test runner built in Zig.</description>
      <content:encoded><![CDATA[<p>Bun 1.0 is out. It’s a new JavaScript runtime built in Zig, and it aims to be fast—very fast.</p>
<p>It’s not just a runtime. It also includes:</p>
<ul>
<li>A bundler</li>
<li>A test runner</li>
<li>A package manager</li>
<li>A development server</li>
</ul>
<p>All built in.</p>
<p>Bun tries to replace several tools at once: Node, Webpack, Jest, even npm.</p>
<h2 id="installing-bun">Installing Bun</h2>
<p>To install Bun:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">curl</span><span style="color:#9ECBFF"> https://bun.sh/install</span><span style="color:#F97583"> |</span><span style="color:#B392F0"> bash</span></span></code></pre>
<p>You get access to the <code>bun</code> command, which works like <code>node</code>, <code>npm</code>, and <code>vite</code>—all at once.</p>
<h2 id="creating-a-bun-project">Creating a Bun project</h2>
<p>You can start a new project like this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">bun</span><span style="color:#9ECBFF"> init</span></span></code></pre>
<p>Then run your server:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">bun</span><span style="color:#9ECBFF"> run</span><span style="color:#9ECBFF"> index.ts</span></span></code></pre>
<p>Bun supports TypeScript out of the box—no config, no transpile step.</p>
<h2 id="why-its-interesting">Why it’s interesting</h2>
<ul>
<li>Bun uses JavaScriptCore (from Safari), not V8</li>
<li>Written in Zig, so it compiles to a single binary</li>
<li>It’s fast—cold starts and installs are much quicker than Node</li>
</ul>
<h2 id="what-i-tried">What I tried</h2>
<p>I migrated a simple server from Node to Bun:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#6A737D">// index.ts</span></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  port: </span><span style="color:#79B8FF">3000</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#B392F0">  fetch</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">request</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Request</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Response</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;Hello from Bun!&quot;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p>Then ran:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">bun</span><span style="color:#9ECBFF"> run</span><span style="color:#9ECBFF"> index.ts</span></span></code></pre>
<p>Worked instantly.</p>
<p>Install times for dependencies were about 10x faster than npm.</p>
<h2 id="gotchas">Gotchas</h2>
<ul>
<li>Not all Node APIs are supported</li>
<li>Still new—some ecosystem gaps</li>
<li>No Windows support at the time of writing</li>
</ul>
<h2 id="should-you-use-it">Should you use it?</h2>
<p>Bun is promising. It’s great for:</p>
<ul>
<li>Simple scripts</li>
<li>Side projects</li>
<li>Trying something fast and new</li>
</ul>
<p>For large teams, the Node ecosystem is still more mature. But Bun is improving fast.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Bringing AI to the Front-End – Integrating GPT APIs</title>
      <link>https://letanure.dev/writing/bringing-ai-to-frontend-chatgpt-integration/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/bringing-ai-to-frontend-chatgpt-integration/</guid>
      <pubDate>Wed, 01 Mar 2023 00:00:00 GMT</pubDate>
      <description>A tutorial on integrating GPT APIs into front-end applications with a simple chatbot example.</description>
      <content:encoded><![CDATA[<p>AI is no longer a back-end-only topic. It’s showing up in UIs—from autocomplete to smart assistants. This post shows how to build a simple chatbot UI that talks to a GPT model through an API.</p>
<h2 id="what-well-build">What we’ll build</h2>
<ul>
<li>A front-end chat interface</li>
<li>A simple call to a GPT API using <code>fetch</code></li>
<li>Handling loading states and errors</li>
</ul>
<h2 id="1-setting-up-the-ui">1. Setting up the UI</h2>
<p>We’ll start with a basic input and message history.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> Chat</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">messages</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setMessages</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> React.</span><span style="color:#B392F0">useState</span><span style="color:#E1E4E8">([]);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">input</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setInput</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> React.</span><span style="color:#B392F0">useState</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;&quot;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">loading</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setLoading</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> React.</span><span style="color:#B392F0">useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">false</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#B392F0"> sendMessage</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    if</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">input) </span><span style="color:#F97583">return</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#B392F0">    setLoading</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> userMessage</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> { role: </span><span style="color:#9ECBFF">&quot;user&quot;</span><span style="color:#E1E4E8">, content: input };</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> newMessages</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> [</span><span style="color:#F97583">...</span><span style="color:#E1E4E8">messages, userMessage];</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">    try</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">      const</span><span style="color:#79B8FF"> res</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;/api/chat&quot;</span><span style="color:#E1E4E8">, {</span></span>
<span class="line"><span style="color:#E1E4E8">        method: </span><span style="color:#9ECBFF">&quot;POST&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">        headers: { </span><span style="color:#9ECBFF">&quot;Content-Type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;application/json&quot;</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#E1E4E8">        body: </span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">({ messages: newMessages }),</span></span>
<span class="line"><span style="color:#E1E4E8">      });</span></span>
<span class="line"><span style="color:#F97583">      const</span><span style="color:#79B8FF"> data</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#F97583">      const</span><span style="color:#79B8FF"> botMessage</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> { role: </span><span style="color:#9ECBFF">&quot;assistant&quot;</span><span style="color:#E1E4E8">, content: data.reply };</span></span>
<span class="line"><span style="color:#B392F0">      setMessages</span><span style="color:#E1E4E8">([</span><span style="color:#F97583">...</span><span style="color:#E1E4E8">newMessages, botMessage]);</span></span>
<span class="line"><span style="color:#E1E4E8">    } </span><span style="color:#F97583">catch</span><span style="color:#E1E4E8"> (err) {</span></span>
<span class="line"><span style="color:#E1E4E8">      console.</span><span style="color:#B392F0">error</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;Error:&quot;</span><span style="color:#E1E4E8">, err);</span></span>
<span class="line"><span style="color:#E1E4E8">    } </span><span style="color:#F97583">finally</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">      setLoading</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">false</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#B392F0">      setInput</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;&quot;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">        {messages.</span><span style="color:#B392F0">map</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">m</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">i</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">          &lt;</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> key</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{i}&gt;&lt;</span><span style="color:#85E89D">strong</span><span style="color:#E1E4E8">&gt;{m.role}:&lt;/</span><span style="color:#85E89D">strong</span><span style="color:#E1E4E8">&gt; {m.content}&lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">        ))}</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> value</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{input} </span><span style="color:#B392F0">onChange</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#FFAB70">e</span><span style="color:#F97583"> =&gt;</span><span style="color:#B392F0"> setInput</span><span style="color:#E1E4E8">(e.target.value)} /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> onClick</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{sendMessage} </span><span style="color:#B392F0">disabled</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{loading}&gt;Send&lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h2 id="2-backend-handler-nextjs-example">2. Backend handler (Next.js example)</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#6A737D">// pages/api/chat.js</span></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> async</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> handler</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> messages</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> req.body.messages;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> response</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;https://api.openai.com/v1/chat/completions&quot;</span><span style="color:#E1E4E8">, {</span></span>
<span class="line"><span style="color:#E1E4E8">    method: </span><span style="color:#9ECBFF">&quot;POST&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    headers: {</span></span>
<span class="line"><span style="color:#9ECBFF">      &quot;Authorization&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">`Bearer YOUR_API_KEY`</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#9ECBFF">      &quot;Content-Type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;application/json&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">    },</span></span>
<span class="line"><span style="color:#E1E4E8">    body: </span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">      model: </span><span style="color:#9ECBFF">&quot;gpt-3.5-turbo&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">      messages</span></span>
<span class="line"><span style="color:#E1E4E8">    })</span></span>
<span class="line"><span style="color:#E1E4E8">  });</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> data</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> response.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#E1E4E8">  res.</span><span style="color:#B392F0">status</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">200</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">({ reply: data.choices[</span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">].message.content });</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h2 id="3-final-thoughts">3. Final thoughts</h2>
<p>This is just the start. You could:</p>
<ul>
<li>Add streaming responses</li>
<li>Save chat history</li>
<li>Support tools or actions with function calling</li>
</ul>
<p>Using AI in the front-end opens a lot of creative space. From simple assistants to personalized content, the line between static UI and smart UI keeps blurring.</p>]]></content:encoded>
    </item>
    <item>
      <title>React Server Components and the New Next.js App Router</title>
      <link>https://letanure.dev/writing/react-server-components-nextjs-app-router/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/react-server-components-nextjs-app-router/</guid>
      <pubDate>Sun, 01 Jan 2023 00:00:00 GMT</pubDate>
      <description>A deep dive into React Server Components and the App Router introduced in Next.js 13, showing how to structure and optimize React apps for performance and scalability.</description>
      <content:encoded><![CDATA[<p>React Server Components (RSC) and the new App Router in Next.js 13 introduced a new way of thinking about React apps.</p>
<p>This post explains what changed, why it matters, and how to start using it today.</p>
<h2 id="what-are-react-server-components">What Are React Server Components?</h2>
<p>React Server Components run on the server and send a serialized component tree to the browser.</p>
<p>This has a few benefits:</p>
<ul>
<li>Smaller JavaScript bundles (because server-only code doesn’t go to the browser)</li>
<li>Faster initial load (streaming HTML from server)</li>
<li>More flexibility in separating concerns between client and server</li>
</ul>
<p>RSC lets you write components like this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#6A737D">// app/posts/page.tsx</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { fetchPosts } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;./data&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> async</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> PostsPage</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> posts</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetchPosts</span><span style="color:#E1E4E8">()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      {posts.</span><span style="color:#B392F0">map</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">post</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">        &lt;</span><span style="color:#85E89D">li</span><span style="color:#B392F0"> key</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{post.id}&gt;{post.title}&lt;/</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      ))}</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  )</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>This component is server-rendered by default. You can fetch data directly and render output without sending any of that logic to the client.</p>
<h2 id="the-app-router">The App Router</h2>
<p>Next.js 13 introduces a new <code>app/</code> directory.</p>
<p>Main differences:</p>
<ul>
<li>Routing is now based on folders inside <code>app/</code></li>
<li>Server and client components are mixed by default</li>
<li>Data fetching is built-in to components using async/await</li>
<li>Layouts and templates offer new control over structure and caching</li>
</ul>
<p>Basic file structure:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>app/</span></span>
<span class="line"><span>  layout.tsx</span></span>
<span class="line"><span>  page.tsx</span></span>
<span class="line"><span>  dashboard/</span></span>
<span class="line"><span>    layout.tsx</span></span>
<span class="line"><span>    page.tsx</span></span></code></pre>
<p>Each <code>page.tsx</code> exports a route. Each <code>layout.tsx</code> wraps the routes below it.</p>
<h2 id="mixing-server-and-client-components">Mixing Server and Client Components</h2>
<p>By default, components are rendered on the server. To opt into client-side rendering, add a directive:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#9ECBFF">&#39;use client&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { useState } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;react&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> Counter</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">count</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setCount</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> onClick</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{() </span><span style="color:#F97583">=&gt;</span><span style="color:#B392F0"> setCount</span><span style="color:#E1E4E8">(count </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">)}&gt;{count}&lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Use this when:</p>
<ul>
<li>You need interactivity (hooks, event listeners)</li>
<li>You use browser-only APIs</li>
</ul>
<h2 id="when-to-use-rsc">When to Use RSC</h2>
<p>Use RSC for:</p>
<ul>
<li>Static or dynamic data fetching</li>
<li>Markup generation</li>
<li>Parts of the UI that don’t need interactivity</li>
</ul>
<p>Use client components for:</p>
<ul>
<li>Forms</li>
<li>Buttons</li>
<li>Real-time updates</li>
</ul>
<h2 id="why-it-matters">Why It Matters</h2>
<p>React Server Components and the App Router reduce boilerplate, make routing clearer, and shift more logic to the server. This leads to faster, leaner apps.</p>
<p>Give it a try if:</p>
<ul>
<li>You’re starting a new Next.js project</li>
<li>You want better performance with less client JavaScript</li>
<li>You’re ready to adopt a new rendering model with server as a first-class citizen</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Monorepos and PNPM – Managing Multiple Apps Efficiently</title>
      <link>https://letanure.dev/writing/monorepos-pnpm-setup/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/monorepos-pnpm-setup/</guid>
      <pubDate>Tue, 01 Nov 2022 00:00:00 GMT</pubDate>
      <description>Learn how to set up a front-end monorepo using PNPM workspaces to manage multiple apps and shared packages efficiently.</description>
      <content:encoded><![CDATA[<p>Managing multiple front-end projects or packages in a single codebase can be a pain. That’s where <strong>monorepos</strong> come in.</p>
<p>Monorepos allow you to keep multiple apps and shared packages (like a design system) in the same repository, with a unified workflow. In 2022, PNPM and its <strong>workspace</strong> feature became one of the most popular ways to manage monorepos in JavaScript/TypeScript projects.</p>
<h2 id="why-use-a-monorepo">Why use a monorepo?</h2>
<ul>
<li>Easier dependency management (one lockfile)</li>
<li>Easier to share and reuse components or utilities</li>
<li>Better consistency across packages</li>
<li>Simplified CI/CD pipelines</li>
</ul>
<h2 id="why-pnpm">Why PNPM?</h2>
<p>PNPM uses a content-addressable store and symlinks instead of copying node_modules. That means:</p>
<ul>
<li>Much faster install times</li>
<li>Less disk space usage</li>
<li>Better hoisting behavior</li>
</ul>
<p>Compared to Yarn and npm, PNPM’s performance and workspace isolation made it a strong candidate for monorepo setups.</p>
<h2 id="setting-up-a-monorepo-with-pnpm">Setting up a monorepo with PNPM</h2>
<p>Let’s create a basic structure:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">mkdir</span><span style="color:#9ECBFF"> my-monorepo</span></span>
<span class="line"><span style="color:#79B8FF">cd</span><span style="color:#9ECBFF"> my-monorepo</span></span>
<span class="line"><span style="color:#B392F0">pnpm</span><span style="color:#9ECBFF"> init</span></span></code></pre>
<p>Now set up <code>pnpm-workspace.yaml</code>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="yaml"><code><span class="line"><span style="color:#85E89D">packages</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#E1E4E8">  - </span><span style="color:#9ECBFF">&quot;apps/*&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">  - </span><span style="color:#9ECBFF">&quot;packages/*&quot;</span></span></code></pre>
<p>Then create folders:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">mkdir</span><span style="color:#79B8FF"> -p</span><span style="color:#9ECBFF"> apps/web</span></span>
<span class="line"><span style="color:#B392F0">mkdir</span><span style="color:#79B8FF"> -p</span><span style="color:#9ECBFF"> packages/ui</span></span></code></pre>
<p>Inside each, add a <code>package.json</code>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;name&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;web&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;version&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;1.0.0&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;private&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">true</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;name&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;ui&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;version&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;1.0.0&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;main&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;index.js&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Now you can install and link packages:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">pnpm</span><span style="color:#9ECBFF"> install</span></span>
<span class="line"><span style="color:#B392F0">pnpm</span><span style="color:#9ECBFF"> add</span><span style="color:#9ECBFF"> ui</span><span style="color:#79B8FF"> --filter</span><span style="color:#9ECBFF"> web</span></span></code></pre>
<p>This links the <code>ui</code> package into <code>web</code>, all locally.</p>
<h2 id="tips">Tips</h2>
<ul>
<li>Use <code>pnpm dev</code> or scripts in the root to run across packages</li>
<li>Combine with tools like TurboRepo or Nx for more control</li>
<li>Keep each package isolated and documented</li>
</ul>
<p>Monorepos with PNPM are a great way to keep large projects organized and fast. Whether you’re building multiple apps or just sharing a design system, it’s worth trying.</p>]]></content:encoded>
    </item>
    <item>
      <title>Qwik – The Quest for Instant-Load Web Apps</title>
      <link>https://letanure.dev/writing/qwik-instant-load-framework/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/qwik-instant-load-framework/</guid>
      <pubDate>Thu, 01 Sep 2022 00:00:00 GMT</pubDate>
      <description>Exploring Qwik&apos;s resumability model and how it challenges traditional hydration to deliver near-instant web app interactions.</description>
      <content:encoded><![CDATA[<p>Qwik is a new front-end framework introduced in 2022 with a bold goal: make websites load instantly, no matter how complex they are.</p>
<p>Instead of using client-side hydration like React or Vue, Qwik introduces a new concept: <strong>resumability</strong>. The app doesn’t rehydrate — it continues execution exactly where the server left off.</p>
<h2 id="how-it-works">How It Works</h2>
<p>When a Qwik app is rendered on the server:</p>
<ul>
<li>It serializes the entire application state and event listeners into the HTML.</li>
<li>When the browser loads the page, no JavaScript runs immediately.</li>
<li>Only when a user interacts (e.g., clicks a button), Qwik lazily loads the needed code for that interaction.</li>
</ul>
<p>This results in:</p>
<ul>
<li>Very fast first paint (HTML is ready to go).</li>
<li>Very small JavaScript payload on initial load.</li>
<li>Fine-grained lazy-loading.</li>
</ul>
<h2 id="example-simple-counter">Example: Simple Counter</h2>
<p>Here’s what a basic counter component looks like in Qwik:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="tsx"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> {{ component$, useStore }} </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;@builder.io/qwik&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> const</span><span style="color:#79B8FF"> Counter</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> component$</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> state</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> useStore</span><span style="color:#E1E4E8">({ count: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> onClick$</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{() </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> state.count</span><span style="color:#F97583">++</span><span style="color:#E1E4E8">}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      Count: {{ state.count }}</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<p>This button won’t hydrate until it’s clicked. Before that, it’s just static HTML.</p>
<h2 id="key-concepts">Key Concepts</h2>
<ul>
<li><strong>component$</strong>: Qwik components use the <code>$</code> suffix to denote lazy-load boundaries.</li>
<li><strong>useStore</strong>: A reactive state hook.</li>
<li><strong>onClick$</strong>: Event handlers are lazy-loaded too.</li>
</ul>
<h2 id="why-it-matters">Why It Matters</h2>
<p>Qwik addresses problems many SPAs face:</p>
<ul>
<li>Large JavaScript bundles</li>
<li>Long Time-to-Interactive</li>
<li>Poor performance on low-end devices</li>
</ul>
<p>By shifting the responsibility of interaction setup to the moment it’s needed, Qwik minimizes unnecessary code execution.</p>
<h2 id="should-you-use-it">Should You Use It?</h2>
<p>Qwik is still young and evolving. It’s ideal for:</p>
<ul>
<li>Content-heavy websites (blogs, docs, landing pages)</li>
<li>Apps where SEO and performance are key</li>
<li>Projects that need fast cold-start time</li>
</ul>
<p>It might not be ready for every use case, especially complex web apps that rely on deep client-side state. But it’s worth watching — resumability could be the next big paradigm shift in front-end development.</p>]]></content:encoded>
    </item>
    <item>
      <title>What&apos;s New in React 18 – Concurrent Features</title>
      <link>https://letanure.dev/writing/react-18-concurrent-features/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/react-18-concurrent-features/</guid>
      <pubDate>Fri, 01 Jul 2022 00:00:00 GMT</pubDate>
      <description>A practical guide to React 18’s new concurrent features like automatic batching, startTransition, and Suspense improvements.</description>
      <content:encoded><![CDATA[<p>React 18 brought major changes to how React works under the hood, focusing on better user experience and performance with <strong>concurrent rendering</strong>.</p>
<h3 id="key-features-in-react-18">Key Features in React 18</h3>
<ul>
<li><strong>Automatic Batching</strong><br/>
Multiple state updates inside events, timeouts, or native handlers are now batched by default. This reduces unnecessary re-renders.</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#B392F0">setCount</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">c</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> c </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#B392F0">setFlag</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">f</span><span style="color:#F97583"> =&gt;</span><span style="color:#F97583"> !</span><span style="color:#E1E4E8">f)</span></span>
<span class="line"><span style="color:#6A737D">// These are now batched automatically</span></span></code></pre>
<ul>
<li><strong>startTransition</strong><br/>
Marks updates as non-urgent, so React can keep the UI responsive.</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { startTransition } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;react&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">startTransition</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">  setSearchQuery</span><span style="color:#E1E4E8">(input)</span></span>
<span class="line"><span style="color:#E1E4E8">})</span></span></code></pre>
<p>Use this for things like filtering lists, background tab updates, or lazy-loaded components.</p>
<ul>
<li><strong>Improved Suspense</strong><br/>
Suspense works more broadly now. It’s especially useful with streaming server rendering in frameworks like Next.js.</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#79B8FF">Suspense</span><span style="color:#B392F0"> fallback</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{&lt;</span><span style="color:#79B8FF">Loading</span><span style="color:#E1E4E8"> /&gt;}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#79B8FF">Comments</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#79B8FF">Suspense</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<ul>
<li><strong>New Root API</strong><br/>
You must now use <code>createRoot</code> from <code>react-dom/client</code>.</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { createRoot } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;react-dom/client&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> root</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> createRoot</span><span style="color:#E1E4E8">(document.</span><span style="color:#B392F0">getElementById</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;root&#39;</span><span style="color:#E1E4E8">))</span></span>
<span class="line"><span style="color:#E1E4E8">root.</span><span style="color:#B392F0">render</span><span style="color:#E1E4E8">(&lt;</span><span style="color:#79B8FF">App</span><span style="color:#E1E4E8"> /&gt;)</span></span></code></pre>
<ul>
<li><strong>Concurrent Rendering</strong><br/>
Under the hood, React 18 introduces a concurrent renderer. It enables React to interrupt rendering to prioritize urgent tasks and continue where it left off.</li>
</ul>
<p>This means:</p>
<ul>
<li>React can render updates in the background.</li>
<li>Low-priority updates won’t block more important ones.</li>
<li>UIs feel faster and more responsive.</li>
</ul>
<h3 id="breaking-changes-to-know">Breaking Changes to Know</h3>
<ul>
<li>
<p><strong>useEffect Timing</strong><br/>
Effects now run after the layout and paint phase, closer to how the browser handles rendering. This change avoids blocking the browser’s ability to paint updated content.</p>
</li>
<li>
<p><strong>Third-Party Library Compatibility</strong><br/>
Some older React libraries may need updates to fully support concurrent features.</p>
</li>
</ul>
<h3 id="final-thoughts">Final Thoughts</h3>
<p>React 18 doesn’t force you to change your code, but to take full advantage of the new features, you’ll need to gradually adopt the new APIs. If you’re using a framework like Next.js or Remix, many of these features are already baked in.</p>]]></content:encoded>
    </item>
    <item>
      <title>Astro and Island Architecture – Faster Websites by Doing Less</title>
      <link>https://letanure.dev/writing/astro-island-architecture/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/astro-island-architecture/</guid>
      <pubDate>Thu, 05 May 2022 00:00:00 GMT</pubDate>
      <description>Learn how Astro and island architecture help build faster websites by reducing JavaScript.</description>
      <content:encoded><![CDATA[<p>Astro is a modern static site builder that introduced a refreshing idea: <strong>do less in the browser</strong>. While other frameworks focus on how to make client-side rendering faster, Astro focuses on <em>not sending JavaScript unless necessary</em>.</p>
<p>This idea is called <strong>island architecture</strong>.</p>
<h2 id="what-is-island-architecture">What is island architecture?</h2>
<p>It means you can mix multiple frameworks (React, Svelte, Vue, etc.) in your page, but only hydrate specific parts – the “islands” of interactivity. The rest of the page stays static, like pure HTML and CSS.</p>
<p>Benefits:</p>
<ul>
<li>Less JavaScript in the browser</li>
<li>Faster load times and better Lighthouse scores</li>
<li>Easy integration of different components</li>
<li>Good for content-focused sites like blogs, docs, marketing</li>
</ul>
<h2 id="getting-started-with-astro">Getting started with Astro</h2>
<p>Install Astro:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> create</span><span style="color:#9ECBFF"> astro@latest</span></span></code></pre>
<p>Select the minimal template or one with a framework like React or Svelte.</p>
<p>Run dev server:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#79B8FF">cd</span><span style="color:#9ECBFF"> your-project</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> run</span><span style="color:#9ECBFF"> dev</span></span></code></pre>
<h2 id="using-components">Using components</h2>
<p>You can import components from different frameworks inside <code>.astro</code> files:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="javascript"><code><span class="line"><span style="color:#F97583">---</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> MyReactComponent </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;../components/MyReactComponent.jsx&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> Counter </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;../components/Counter.svelte&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">---</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">html</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">body</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;Static content is fast&lt;/</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#79B8FF">MyReactComponent</span><span style="color:#B392F0"> client</span><span style="color:#E1E4E8">:</span><span style="color:#B392F0">load</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#79B8FF">Counter</span><span style="color:#B392F0"> client</span><span style="color:#E1E4E8">:</span><span style="color:#B392F0">idle</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;/</span><span style="color:#85E89D">body</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">html</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>Each interactive block is hydrated only when needed:</p>
<ul>
<li><code>client:load</code> runs after page loads</li>
<li><code>client:idle</code> waits for browser idle time</li>
<li><code>client:visible</code> waits until the component is in view</li>
</ul>
<h2 id="output">Output</h2>
<p>Astro renders static HTML for everything else. You don’t send React or Svelte runtime if you don’t need it. That’s a big performance win.</p>
<h2 id="when-to-use-astro">When to use Astro?</h2>
<p>Astro is great for:</p>
<ul>
<li>Blogs</li>
<li>Documentation</li>
<li>Marketing sites</li>
<li>Sites with mostly static content and a few dynamic parts</li>
</ul>
<p>If your app is very dynamic or needs lots of client-side interactivity, use something like Next.js or SvelteKit.</p>
<h2 id="final-thoughts">Final thoughts</h2>
<p>Astro follows a smart idea: send less to the browser. Use components when needed. Keep the rest static. In a time where performance matters, this shift makes a lot of sense.</p>
<p>Astro gives you control over interactivity, framework flexibility, and great performance by default.</p>]]></content:encoded>
    </item>
    <item>
      <title>Goodbye, Webpack? Hello, Vite!</title>
      <link>https://letanure.dev/writing/vite-vs-webpack/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/vite-vs-webpack/</guid>
      <pubDate>Thu, 10 Mar 2022 00:00:00 GMT</pubDate>
      <description>A deep dive into Vite, the fast and modern alternative to Webpack for frontend development.</description>
      <content:encoded><![CDATA[<p>Vite is a modern build tool that has quickly become a go-to choice for frontend developers seeking speed and simplicity. Originally created by Evan You (the creator of Vue.js), Vite was designed to address long-standing pain points with traditional bundlers like Webpack.</p>
<h2 id="why-vite">Why Vite?</h2>
<p>Vite delivers near-instant startup and updates in development mode by taking a different approach:</p>
<ul>
<li>It uses native ES Modules in the browser.</li>
<li>No bundling is required for dev mode.</li>
<li>Dependencies are pre-bundled using esbuild, which is extremely fast (written in Go).</li>
<li>It supports hot module replacement (HMR) out of the box, and it’s incredibly fast and reliable.</li>
</ul>
<p>This is a major shift from tools like Webpack or Parcel, which traditionally bundle everything upfront for both dev and production.</p>
<h2 id="vite-vs-webpack">Vite vs. Webpack</h2>
<p>While Webpack became the industry standard through its flexibility and massive plugin ecosystem, it has also become notorious for complex configs, slow cold starts, and long rebuild times.</p>



































<table><thead><tr><th>Feature</th><th>Webpack</th><th>Vite</th></tr></thead><tbody><tr><td>Dev Startup Time</td><td>Often slow (seconds+)</td><td>Instant (milliseconds)</td></tr><tr><td>Hot Module Reloading</td><td>Sometimes delayed</td><td>Near-instant</td></tr><tr><td>Config Complexity</td><td>Often high</td><td>Minimal, zero-config possible</td></tr><tr><td>Ecosystem</td><td>Mature, plugin-rich</td><td>Growing rapidly, focused</td></tr><tr><td>Default Language</td><td>JavaScript + loaders</td><td>Native ES Modules + modern JS</td></tr></tbody></table>
<h2 id="setup-example">Setup Example</h2>
<p>Install Vite and scaffold a new project:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> create</span><span style="color:#9ECBFF"> vite@latest</span><span style="color:#9ECBFF"> my-vite-app</span></span>
<span class="line"><span style="color:#79B8FF">cd</span><span style="color:#9ECBFF"> my-vite-app</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> run</span><span style="color:#9ECBFF"> dev</span></span></code></pre>
<p>You’ll immediately notice the dev server starts almost instantly.</p>
<h2 id="using-vite-with-react">Using Vite with React</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> create</span><span style="color:#9ECBFF"> vite@latest</span><span style="color:#9ECBFF"> my-react-app</span><span style="color:#79B8FF"> --template</span><span style="color:#9ECBFF"> react</span></span>
<span class="line"><span style="color:#79B8FF">cd</span><span style="color:#9ECBFF"> my-react-app</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> run</span><span style="color:#9ECBFF"> dev</span></span></code></pre>
<p>Vite works seamlessly with JSX, TypeScript, and CSS modules. The development experience is fluid and minimal.</p>
<h2 id="production-builds">Production Builds</h2>
<p>For production, Vite uses Rollup under the hood to bundle your code efficiently.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> run</span><span style="color:#9ECBFF"> build</span></span></code></pre>
<p>The output is clean and optimized, ready for deployment.</p>
<h2 id="plugins-and-ecosystem">Plugins and Ecosystem</h2>
<p>Vite supports a plugin system similar to Rollup. Some popular plugins include:</p>
<ul>
<li><code>@vitejs/plugin-react</code> for React fast refresh</li>
<li><code>vite-plugin-pwa</code> for Progressive Web App support</li>
<li><code>vite-plugin-mdx</code> for MDX support</li>
</ul>
<h2 id="when-to-use-vite">When to Use Vite?</h2>
<ul>
<li>When starting a new project with modern tools</li>
<li>When you want fast dev feedback cycles</li>
<li>When you’re building with frameworks like Vue, React, or Svelte</li>
<li>When you want less bundler config and better DX</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>Vite brings a breath of fresh air to frontend development. While Webpack is still powerful and used widely, Vite offers an appealing alternative for projects that need speed, simplicity, and modern standards. If you’re tired of waiting on builds and configs, it’s time to give Vite a try.</p>]]></content:encoded>
    </item>
    <item>
      <title>End of an Era – Internet Explorer Bows Out</title>
      <link>https://letanure.dev/writing/internet-explorer-end/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/internet-explorer-end/</guid>
      <pubDate>Thu, 10 Feb 2022 00:00:00 GMT</pubDate>
      <description>Marking the official retirement of Internet Explorer and what it means for developers.</description>
      <content:encoded><![CDATA[<p>After more than two decades, Internet Explorer has reached the end of its life.</p>
<p>Microsoft officially announced the retirement of Internet Explorer 11. This means the IE 11 desktop app will no longer be supported, and most users will be transitioned to Microsoft Edge.</p>
<h2 id="what-does-this-mean">What does this mean?</h2>
<ul>
<li>No more security updates or technical support for IE.</li>
<li>Organizations still relying on IE will be urged to switch to Edge’s IE mode.</li>
<li>Developers can officially drop support for IE in most modern web apps.</li>
</ul>
<h2 id="a-look-back">A look back</h2>
<p>Internet Explorer played a major role in the early web. It helped bring browsing to the masses, dominated the market for years, and introduced proprietary features that shaped how we built websites. But it also held the web back for a long time due to slow updates and non-standard behavior.</p>
<h2 id="why-this-matters-for-developers">Why this matters for developers</h2>
<p>With IE retired, front-end developers can:</p>
<ul>
<li>Use modern JavaScript and CSS without as many polyfills or workarounds.</li>
<li>Rely on evergreen browsers with consistent support for new standards.</li>
<li>Reduce testing complexity by not targeting a browser stuck in the past.</li>
</ul>
<h2 id="what-you-should-do">What you should do</h2>
<p>If you still have:</p>
<ul>
<li>Legacy code supporting IE, start auditing and updating it.</li>
<li>Compatibility scripts or fallbacks, it might be time to remove them.</li>
<li>Concerns about old clients, encourage migration to Edge (or any modern browser).</li>
</ul>
<p>This is a major milestone. We’re finally moving on from the browser that defined – and often constrained – the web for years.</p>
<p>Modern web development just got simpler.</p>]]></content:encoded>
    </item>
    <item>
      <title>Headless CMS – Building a Blog with Contentful</title>
      <link>https://letanure.dev/writing/headless-cms-with-contentful/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/headless-cms-with-contentful/</guid>
      <pubDate>Fri, 15 Oct 2021 00:00:00 GMT</pubDate>
      <description>Learn how to use a headless CMS to build a blog by integrating Contentful with a modern front-end.</description>
      <content:encoded><![CDATA[<p>Headless CMSs separate content from presentation, giving front-end developers more flexibility. Instead of managing both content and layout in a traditional CMS like WordPress, a headless CMS stores content and exposes it via an API.</p>
<p>Popular options include:</p>
<ul>
<li>Contentful</li>
<li>Sanity</li>
<li>Strapi</li>
</ul>
<p>These tools let non-developers manage content in a UI, while developers use the API to pull data into their apps.</p>
<h2 id="why-use-a-headless-cms">Why use a headless CMS?</h2>
<ul>
<li>Keep content editing and layout development independent</li>
<li>Serve content via API to multiple channels (web, mobile, apps)</li>
<li>Use your preferred frontend (React, Vue, Svelte, etc.)</li>
<li>Better performance and scalability with static site generators</li>
</ul>
<h2 id="example-blog-with-contentful--nextjs">Example: Blog with Contentful + Next.js</h2>
<p>We’ll use Contentful as our CMS and Next.js as the front-end.</p>
<h3 id="step-1-set-up-contentful-space">Step 1: Set up Contentful space</h3>
<ol>
<li>Create an account at Contentful</li>
<li>Create a new space</li>
<li>Add a content type “Post” with fields like:
<ul>
<li><code>title</code> (Text)</li>
<li><code>slug</code> (Text)</li>
<li><code>body</code> (Rich Text)</li>
</ul>
</li>
</ol>
<h3 id="step-2-add-some-content">Step 2: Add some content</h3>
<p>Fill in a few blog posts using the Contentful UI.</p>
<h3 id="step-3-connect-nextjs-to-contentful">Step 3: Connect Next.js to Contentful</h3>
<p>Install the required packages:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#9ECBFF"> contentful</span></span></code></pre>
<p>Create a helper to fetch data:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#6A737D">// lib/contentful.js</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { createClient } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;contentful&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> client</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> createClient</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">  space: process.env.</span><span style="color:#79B8FF">CONTENTFUL_SPACE_ID</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  accessToken: process.env.</span><span style="color:#79B8FF">CONTENTFUL_ACCESS_TOKEN</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">})</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> async</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> getPosts</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> entries</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> client.</span><span style="color:#B392F0">getEntries</span><span style="color:#E1E4E8">({ content_type: </span><span style="color:#9ECBFF">&#39;post&#39;</span><span style="color:#E1E4E8"> })</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> entries.items</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Load data in your page:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#6A737D">// pages/index.js</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { getPosts } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;../lib/contentful&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> async</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> getStaticProps</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> posts</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> getPosts</span><span style="color:#E1E4E8">()</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> { props: { posts } }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h3 id="step-4-display-the-posts">Step 4: Display the posts</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> Home</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">posts</span><span style="color:#E1E4E8"> }) {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      {posts.</span><span style="color:#B392F0">map</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">post</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">        &lt;</span><span style="color:#85E89D">article</span><span style="color:#B392F0"> key</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{post.sys.id}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">          &lt;</span><span style="color:#85E89D">h2</span><span style="color:#E1E4E8">&gt;{post.fields.title}&lt;/</span><span style="color:#85E89D">h2</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">        &lt;/</span><span style="color:#85E89D">article</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      ))}</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  )</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h2 id="recap">Recap</h2>
<p>Headless CMSs like Contentful let you:</p>
<ul>
<li>Store and manage structured content</li>
<li>Serve that content via API</li>
<li>Use it in any front-end framework</li>
</ul>
<p>They’re a great fit for JAMstack apps and give you full control over your UI while editors manage the content easily.</p>]]></content:encoded>
    </item>
    <item>
      <title>Mastering CSS Grid + Flexbox Combo</title>
      <link>https://letanure.dev/writing/css-grid-flexbox-combo/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/css-grid-flexbox-combo/</guid>
      <pubDate>Mon, 20 Sep 2021 00:00:00 GMT</pubDate>
      <description>Learn how to combine CSS Grid and Flexbox for powerful, responsive layouts with practical patterns.</description>
      <content:encoded><![CDATA[<p>Using CSS Grid and Flexbox together can solve many layout challenges in modern web design. Both are powerful on their own, but combining them gives you full control over both macro and micro layout structures.</p>
<h2 id="why-combine-grid-and-flexbox">Why combine Grid and Flexbox?</h2>
<ul>
<li><strong>Grid</strong> is best for overall page structure.</li>
<li><strong>Flexbox</strong> is ideal for layout within a component or single row/column.</li>
<li>Together, they replace many old hacks (like nested floats or complex margins).</li>
</ul>
<h2 id="example-holy-grail-layout">Example: Holy Grail Layout</h2>
<p>Use Grid for the main layout, Flexbox inside the header and sidebar.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#85E89D">body</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">grid</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  grid-template-columns</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">200</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> 1</span><span style="color:#F97583">fr</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  grid-template-rows</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">auto</span><span style="color:#79B8FF"> 1</span><span style="color:#F97583">fr</span><span style="color:#79B8FF"> auto</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  grid-template-areas</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#9ECBFF">    &quot;header header&quot;</span></span>
<span class="line"><span style="color:#9ECBFF">    &quot;sidebar main&quot;</span></span>
<span class="line"><span style="color:#9ECBFF">    &quot;footer footer&quot;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  min-height</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">100</span><span style="color:#F97583">vh</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">header</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  grid-area</span><span style="color:#E1E4E8">: header;</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  justify-content</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">space-between</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  align-items</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">center</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">#eee</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">aside</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  grid-area</span><span style="color:#E1E4E8">: sidebar;</span></span>
<span class="line"><span style="color:#79B8FF">  background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">#f4f4f4</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">main</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  grid-area</span><span style="color:#E1E4E8">: main;</span></span>
<span class="line"><span style="color:#79B8FF">  padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">footer</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  grid-area</span><span style="color:#E1E4E8">: footer;</span></span>
<span class="line"><span style="color:#79B8FF">  text-align</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">center</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">#ddd</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h2 id="design-patterns">Design Patterns</h2>
<ul>
<li><strong>Dashboard layouts</strong>: Use Grid for structure, Flexbox inside widgets/cards</li>
<li><strong>Navigation bars</strong>: Flexbox helps align logo, links, and user menu</li>
<li><strong>Marketing pages</strong>: Grid defines rows and sections, Flexbox inside each block</li>
</ul>
<h2 id="tips">Tips</h2>
<ul>
<li>Don’t overuse nesting. Use Grid at top-level layout, Flexbox where you need fine control</li>
<li>Use <code>minmax()</code> and <code>auto-fit</code> in Grid for fluid layouts</li>
<li>Test on different screen sizes early</li>
</ul>
<p>This combo is now a go-to for clean, responsive design.</p>]]></content:encoded>
    </item>
    <item>
      <title>Core Web Vitals – Optimizing for Google’s UX Metrics</title>
      <link>https://letanure.dev/writing/core-web-vitals-ux-metrics/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/core-web-vitals-ux-metrics/</guid>
      <pubDate>Sat, 10 Jul 2021 00:00:00 GMT</pubDate>
      <description>Learn how to improve user experience and SEO by focusing on Google&apos;s Core Web Vitals LCP, FID, and CLS.</description>
      <content:encoded><![CDATA[<p>Core Web Vitals are a set of metrics defined by Google to evaluate the user experience of a web page. They focus on loading speed, interactivity, and visual stability.</p>
<p>These three metrics became especially important for front-end developers when they started to influence search ranking.</p>
<h2 id="what-are-core-web-vitals">What are Core Web Vitals?</h2>
<ul>
<li><strong>Largest Contentful Paint (LCP)</strong>: Measures loading performance. A good score is under 2.5 seconds.</li>
<li><strong>First Input Delay (FID)</strong>: Measures interactivity. A good score is under 100ms.</li>
<li><strong>Cumulative Layout Shift (CLS)</strong>: Measures visual stability. A good score is below 0.1.</li>
</ul>
<h2 id="tips-to-improve-core-web-vitals">Tips to Improve Core Web Vitals</h2>
<h3 id="improving-lcp">Improving LCP</h3>
<ul>
<li>Use lazy loading for images and videos</li>
<li>Optimize critical rendering path</li>
<li>Serve images in modern formats like WebP</li>
<li>Reduce server response times</li>
</ul>
<h3 id="improving-fid">Improving FID</h3>
<ul>
<li>Minimize main-thread blocking time</li>
<li>Reduce JavaScript bundle size</li>
<li>Use web workers for heavy computation</li>
<li>Split code using dynamic <code>import()</code></li>
</ul>
<h3 id="improving-cls">Improving CLS</h3>
<ul>
<li>Always include width and height on images and videos</li>
<li>Reserve space for ads and embeds</li>
<li>Avoid injecting content above existing content</li>
<li>Use CSS <code>aspect-ratio</code> to maintain size stability</li>
</ul>
<h2 id="how-to-measure-core-web-vitals">How to Measure Core Web Vitals</h2>
<p>You can test your site using:</p>
<ul>
<li>Lighthouse (in Chrome DevTools)</li>
<li>PageSpeed Insights</li>
<li>Web Vitals Chrome Extension</li>
<li>Real-user monitoring tools</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Run Lighthouse in CLI</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> -g</span><span style="color:#9ECBFF"> lighthouse</span></span>
<span class="line"><span style="color:#B392F0">lighthouse</span><span style="color:#9ECBFF"> https://your-site.com</span></span></code></pre>
<p>Improving these metrics not only helps SEO but also provides a better experience for users across devices and connection speeds.</p>]]></content:encoded>
    </item>
    <item>
      <title>Svelte &amp; SvelteKit – Exploring a Different UI Paradigm</title>
      <link>https://letanure.dev/writing/svelte-and-sveltekit-ui-paradigm/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/svelte-and-sveltekit-ui-paradigm/</guid>
      <pubDate>Thu, 10 Jun 2021 00:00:00 GMT</pubDate>
      <description>A walkthrough of building a project with SvelteKit, highlighting its simplicity and performance through compile-time optimizations.</description>
      <content:encoded><![CDATA[<p>SvelteKit is the official application framework for Svelte. It builds on the ideas of Sapper but brings a more modern setup with better performance and flexibility.</p>
<p>Unlike frameworks like React or Vue, Svelte compiles your code at build time. That means less JavaScript in the browser and faster runtime performance.</p>
<h2 id="getting-started">Getting Started</h2>
<p>To scaffold a new SvelteKit project:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> create</span><span style="color:#9ECBFF"> svelte@latest</span><span style="color:#9ECBFF"> my-app</span></span>
<span class="line"><span style="color:#79B8FF">cd</span><span style="color:#9ECBFF"> my-app</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> run</span><span style="color:#9ECBFF"> dev</span></span></code></pre>
<p>This sets up:</p>
<ul>
<li>File-based routing (routes are defined by the filesystem)</li>
<li>Server-side rendering by default</li>
<li>Svelte components with zero runtime overhead</li>
</ul>
<h2 id="example-component">Example Component</h2>
<p>A simple counter component in Svelte:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="javascript"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  let count = 0;</span></span>
<span class="line"><span style="color:#E1E4E8">  function increment() {</span></span>
<span class="line"><span style="color:#E1E4E8">    count </span><span style="color:#F97583">+=</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> on</span><span style="color:#E1E4E8">:</span><span style="color:#B392F0">click</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{increment}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  Clicks: {count}</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>This syntax is minimal and reactive out of the box.</p>
<h2 id="file-based-routing">File-Based Routing</h2>
<p>To add a new page, just create a <code>.svelte</code> file under <code>src/routes</code>.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">touch</span><span style="color:#9ECBFF"> src/routes/about.svelte</span></span></code></pre>
<p>The file <code>about.svelte</code> becomes accessible at <code>/about</code>.</p>
<h2 id="why-sveltekit">Why SvelteKit?</h2>
<ul>
<li>Less client-side JavaScript</li>
<li>Built-in SSR and static site generation</li>
<li>Simpler mental model</li>
<li>Flexible deployment (static or dynamic)</li>
</ul>
<p>SvelteKit projects can also integrate with TypeScript, environment variables, and endpoints easily.</p>
<h2 id="conclusion">Conclusion</h2>
<p>SvelteKit brings a refreshing developer experience with good defaults, fast builds, and clear separation of concerns. It’s worth exploring if you’re looking for something faster and simpler than traditional UI frameworks.</p>]]></content:encoded>
    </item>
    <item>
      <title>Deno vs Node – A Secure Runtime Showdown</title>
      <link>https://letanure.dev/writing/deno-vs-node-runtime-showdown/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/deno-vs-node-runtime-showdown/</guid>
      <pubDate>Thu, 15 Apr 2021 00:00:00 GMT</pubDate>
      <description>A hands-on comparison between Deno and Node.js showing how common tasks differ, their tooling, and the trade-offs.</description>
      <content:encoded><![CDATA[<p>Deno was introduced as a fresh alternative to Node.js, aiming to fix some of Node’s design flaws. One year after its 1.0 release, it’s time to compare how the two runtimes stack up for common development tasks.</p>
<h2 id="why-compare">Why Compare?</h2>
<ul>
<li>Both are JavaScript/TypeScript runtimes</li>
<li>Built by the same creator (Ryan Dahl)</li>
<li>Focus on developer tooling and modern JavaScript support</li>
<li>Competing philosophies: Node is stable and mature; Deno is secure and modern</li>
</ul>
<hr/>
<h2 id="1-hello-world-http-server">1. Hello World HTTP Server</h2>
<p><strong>Node.js</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> http</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> require</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;http&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">http.</span><span style="color:#B392F0">createServer</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">req</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">res</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  res.</span><span style="color:#B392F0">end</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;Hello from Node&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}).</span><span style="color:#B392F0">listen</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">3000</span><span style="color:#E1E4E8">);</span></span></code></pre>
<p><strong>Deno</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { serve } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &quot;https://deno.land/std/http/server.ts&quot;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">serve</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">_req</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Response</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;Hello from Deno&quot;</span><span style="color:#E1E4E8">), { port: </span><span style="color:#79B8FF">3000</span><span style="color:#E1E4E8"> });</span></span></code></pre>
<hr/>
<h2 id="2-reading-a-file">2. Reading a File</h2>
<p><strong>Node.js</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> fs</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> require</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;fs&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">fs.</span><span style="color:#B392F0">readFile</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;example.txt&#39;</span><span style="color:#E1E4E8">, </span><span style="color:#9ECBFF">&#39;utf8&#39;</span><span style="color:#E1E4E8">, (</span><span style="color:#FFAB70">err</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">data</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(data);</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<p><strong>Deno</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> text</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> Deno.</span><span style="color:#B392F0">readTextFile</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;example.txt&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(text);</span></span></code></pre>
<p>Note: Deno requires permission to read files. You must run it with:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">deno</span><span style="color:#9ECBFF"> run</span><span style="color:#79B8FF"> --allow-read</span><span style="color:#9ECBFF"> read.ts</span></span></code></pre>
<hr/>
<h2 id="3-fetching-remote-data">3. Fetching Remote Data</h2>
<p><strong>Node.js (with fetch in newer versions)</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#B392F0">fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;https://api.example.com/data&#39;</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8">  .</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">res</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">())</span></span>
<span class="line"><span style="color:#E1E4E8">  .</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">data</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(data));</span></span></code></pre>
<p><strong>Deno</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> res</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;https://api.example.com/data&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> data</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#E1E4E8">console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(data);</span></span></code></pre>
<p>No extra install needed. Deno supports fetch natively.</p>
<hr/>
<h2 id="key-differences">Key Differences</h2>
<ul>
<li><strong>Security</strong>: Deno is secure by default. No file/network access unless explicitly granted.</li>
<li><strong>Modules</strong>: Deno uses ES Modules and imports directly via URL. Node relies on npm and CommonJS.</li>
<li><strong>Tooling</strong>: Deno includes formatter, linter, bundler, test runner—built-in.</li>
<li><strong>TypeScript</strong>: First-class TypeScript support out of the box in Deno.</li>
</ul>
<hr/>
<h2 id="ecosystem-maturity">Ecosystem Maturity</h2>
<ul>
<li><strong>Node</strong>: Thousands of npm packages, mature tooling, wide adoption.</li>
<li><strong>Deno</strong>: Smaller ecosystem, but growing steadily.</li>
</ul>
<hr/>
<h2 id="final-thoughts">Final Thoughts</h2>
<p>Deno simplifies some workflows and introduces modern practices. Node, with its maturity and vast ecosystem, still dominates production use. For new tools, quick scripts, or learning modern APIs, Deno is worth exploring. But for large-scale apps, Node might still be the safer choice—for now.</p>]]></content:encoded>
    </item>
    <item>
      <title>Next.js for Production – Hybrid Rendering and Incremental Static Regeneration</title>
      <link>https://letanure.dev/writing/nextjs-hybrid-rendering-isr/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/nextjs-hybrid-rendering-isr/</guid>
      <pubDate>Mon, 15 Mar 2021 00:00:00 GMT</pubDate>
      <description>Exploring how Next.js combines SSR, SSG, and ISR for high-performance production apps.</description>
      <content:encoded><![CDATA[<p>Next.js keeps evolving as the go-to framework for building fast React apps. One of its biggest advantages is supporting multiple rendering strategies in the same app:</p>
<ul>
<li>Static Site Generation (SSG)</li>
<li>Server-Side Rendering (SSR)</li>
<li>Client-Side Rendering (CSR)</li>
<li>Incremental Static Regeneration (ISR)</li>
</ul>
<p>This flexibility lets you serve content based on your use case—fast static content, dynamic content when needed, and everything in between.</p>
<h2 id="hybrid-rendering-in-practice">Hybrid Rendering in Practice</h2>
<p>You can mix SSR and SSG in the same project. For example:</p>
<ul>
<li>A homepage rendered statically at build time</li>
<li>A product page rendered with SSR for real-time pricing</li>
<li>A blog post page updated every 10 minutes with ISR</li>
</ul>
<p>This gives you speed <strong>and</strong> freshness.</p>
<h2 id="incremental-static-regeneration-isr">Incremental Static Regeneration (ISR)</h2>
<p>ISR allows you to update static pages <strong>after</strong> deployment without rebuilding the whole site. You set a <code>revalidate</code> time per page, and Next.js handles the regeneration in the background.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> async</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> getStaticProps</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> data</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetchData</span><span style="color:#E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">    props: { data },</span></span>
<span class="line"><span style="color:#E1E4E8">    revalidate: </span><span style="color:#79B8FF">600</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// Regenerate the page every 10 minutes</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>The first request after the revalidate time triggers the update. Users never see a loading state.</p>
<h2 id="example-use-case">Example Use Case</h2>
<p>Let’s say you’re building an e-commerce site:</p>
<ul>
<li><code>/products</code> can use SSG for performance.</li>
<li><code>/products/[id]</code> can use SSR or ISR to show real-time stock or price.</li>
<li><code>/checkout</code> uses CSR for dynamic interaction.</li>
</ul>
<p>This setup improves speed, SEO, and developer experience without sacrificing flexibility.</p>
<h2 id="final-thoughts">Final Thoughts</h2>
<p>Next.js makes high-performance React apps easier to build. With features like ISR, you can have the best of both worlds—fast, static-like performance with dynamic data updates when needed.</p>]]></content:encoded>
    </item>
    <item>
      <title>Tailwind CSS – Utility-First CSS in Action</title>
      <link>https://letanure.dev/writing/tailwind-css-utility-first/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/tailwind-css-utility-first/</guid>
      <pubDate>Sun, 10 Jan 2021 00:00:00 GMT</pubDate>
      <description>How Tailwind CSS changed the way we style components with utility-first classes.</description>
      <content:encoded><![CDATA[<p>Tailwind CSS is a utility-first CSS framework that encourages building UIs directly in your HTML using small, reusable utility classes.</p>
<p>Unlike traditional frameworks like Bootstrap that give you components, Tailwind gives you the building blocks. You style elements by composing utility classes right in your markup.</p>
<h2 id="why-tailwind">Why Tailwind?</h2>
<ul>
<li>Encourages consistency without writing custom CSS</li>
<li>Lets you prototype fast</li>
<li>Avoids naming confusion with class names</li>
<li>Supports dark mode, responsive design, and variants out of the box</li>
</ul>
<h2 id="getting-started">Getting Started</h2>
<p>Install Tailwind using npm:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#9ECBFF"> tailwindcss</span></span>
<span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> tailwindcss</span><span style="color:#9ECBFF"> init</span></span></code></pre>
<p>Configure the generated <code>tailwind.config.js</code> file if needed.</p>
<p>Set up Tailwind to process your CSS:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#6A737D">/* ./src/styles.css */</span></span>
<span class="line"><span style="color:#F97583">@tailwind</span><span style="color:#E1E4E8"> base;</span></span>
<span class="line"><span style="color:#F97583">@tailwind</span><span style="color:#E1E4E8"> components;</span></span>
<span class="line"><span style="color:#F97583">@tailwind</span><span style="color:#E1E4E8"> utilities;</span></span></code></pre>
<p>And in your build tool (like PostCSS):</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> tailwindcss</span><span style="color:#79B8FF"> -i</span><span style="color:#9ECBFF"> ./src/styles.css</span><span style="color:#79B8FF"> -o</span><span style="color:#9ECBFF"> ./dist/styles.css</span><span style="color:#79B8FF"> --watch</span></span></code></pre>
<h2 id="example-card-component">Example: Card Component</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;max-w-sm rounded overflow-hidden shadow-lg&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">img</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;w-full&quot;</span><span style="color:#B392F0"> src</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;/img/card-top.jpg&quot;</span><span style="color:#B392F0"> alt</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;Card image&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;px-6 py-4&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;font-bold text-xl mb-2&quot;</span><span style="color:#E1E4E8">&gt;Tailwind Card&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;text-gray-700 text-base&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      This is a simple card built with Tailwind utility classes.</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<h2 id="design-without-leaving-html">Design Without Leaving HTML</h2>
<p>One of Tailwind’s main ideas is: design and implementation should happen in the same place. You don’t write new class names in CSS files. You compose them using existing utilities:</p>
<ul>
<li><code>text-center</code>, <code>text-lg</code>, <code>font-semibold</code></li>
<li><code>bg-blue-500</code>, <code>hover:bg-blue-700</code>, <code>text-white</code></li>
</ul>
<h2 id="responsive-design">Responsive Design</h2>
<p>Tailwind uses a mobile-first approach with simple prefixes:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;text-base md:text-lg lg:text-xl&quot;</span><span style="color:#E1E4E8">&gt;Responsive text&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<h2 id="final-thoughts">Final Thoughts</h2>
<p>Tailwind CSS promotes a shift from traditional CSS thinking. Instead of writing custom styles and managing class names, you rely on predefined building blocks.</p>
<p>It feels strange at first but once you get used to it, the speed and consistency are hard to beat.</p>]]></content:encoded>
    </item>
    <item>
      <title>Web Accessibility Checklist – Building Inclusive Web Apps</title>
      <link>https://letanure.dev/writing/web-accessibility-checklist/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/web-accessibility-checklist/</guid>
      <pubDate>Sat, 12 Dec 2020 00:00:00 GMT</pubDate>
      <description>A practical accessibility guide covering key areas like semantic HTML, ARIA roles, keyboard navigation, and testing tools.</description>
      <content:encoded><![CDATA[<p>Web accessibility is about making websites usable for everyone, including people with disabilities. This checklist focuses on practical areas where developers can ensure accessibility in their apps.</p>
<h2 id="use-semantic-html">Use Semantic HTML</h2>
<p>Semantic elements help screen readers and other assistive technologies understand your content:</p>
<ul>
<li>Use <code>&lt;header&gt;</code>, <code>&lt;nav&gt;</code>, <code>&lt;main&gt;</code>, <code>&lt;article&gt;</code>, <code>&lt;section&gt;</code>, and <code>&lt;footer&gt;</code></li>
<li>Use <code>&lt;button&gt;</code> instead of clickable <code>&lt;div&gt;</code> or <code>&lt;span&gt;</code></li>
<li>Use <code>&lt;label&gt;</code> elements properly linked to <code>&lt;input&gt;</code> via <code>for</code> and <code>id</code></li>
</ul>
<h2 id="add-alt-text-to-images">Add ALT Text to Images</h2>
<p>Every <code>&lt;img&gt;</code> must have a meaningful <code>alt</code> attribute, or <code>alt=&quot;&quot;</code> if the image is decorative.</p>
<h2 id="ensure-keyboard-navigation">Ensure Keyboard Navigation</h2>
<p>Users should be able to:</p>
<ul>
<li>Navigate with the <code>Tab</code> key</li>
<li>Activate links and buttons with <code>Enter</code> or <code>Space</code></li>
<li>Avoid getting stuck in keyboard traps</li>
</ul>
<p>Test this manually or using browser DevTools.</p>
<h2 id="use-aria-roles-when-needed">Use ARIA Roles When Needed</h2>
<p>Only when semantic HTML isn’t enough:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> role</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;dialog&quot;</span><span style="color:#B392F0"> aria-labelledby</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;dialogTitle&quot;</span><span style="color:#B392F0"> aria-describedby</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;dialogDesc&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  ...</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>Common roles:</p>
<ul>
<li><code>role=&quot;button&quot;</code></li>
<li><code>role=&quot;dialog&quot;</code></li>
<li><code>role=&quot;alert&quot;</code></li>
<li><code>aria-expanded</code>, <code>aria-hidden</code>, etc.</li>
</ul>
<h2 id="ensure-sufficient-color-contrast">Ensure Sufficient Color Contrast</h2>
<p>Check foreground and background color contrast ratios. Aim for:</p>
<ul>
<li>4.5:1 for normal text</li>
<li>3:1 for large text (18px+ or 14px bold)</li>
</ul>
<p>Use tools like <code>color-contrast-checker</code> or in-browser extensions.</p>
<h2 id="provide-focus-styles">Provide Focus Styles</h2>
<p>Don’t remove focus outlines. If you restyle them, make sure they are clearly visible:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#85E89D">button</span><span style="color:#B392F0">:focus</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  outline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#79B8FF"> #005fcc</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  outline-offset</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h2 id="label-form-fields-clearly">Label Form Fields Clearly</h2>
<ul>
<li>Always associate <code>&lt;label&gt;</code>s with form fields</li>
<li>Use placeholder text only for hints, not as a label substitute</li>
<li>Group related fields using <code>&lt;fieldset&gt;</code> and <code>&lt;legend&gt;</code></li>
</ul>
<h2 id="add-skip-links">Add Skip Links</h2>
<p>Provide a way to skip repetitive content:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;#main-content&quot;</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;skip-link&quot;</span><span style="color:#E1E4E8">&gt;Skip to content&lt;/</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>Make the link visible when focused.</p>
<h2 id="test-with-accessibility-tools">Test with Accessibility Tools</h2>
<ul>
<li>[axe DevTools] browser extension</li>
<li>Lighthouse in Chrome DevTools</li>
<li>Screen readers like NVDA (Windows) or VoiceOver (macOS)</li>
<li>Keyboard-only navigation</li>
</ul>
<h2 id="think-about-motion">Think About Motion</h2>
<p>Reduce unnecessary animations. Respect user preferences:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#F97583">@media</span><span style="color:#E1E4E8"> (prefers-reduced-motion: reduce) {</span></span>
<span class="line"><span style="color:#85E89D">  *</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">    animation</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">none</span><span style="color:#F97583"> !important</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">    transition</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">none</span><span style="color:#F97583"> !important</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<hr/>
<p>Accessibility is not a feature. It’s part of good web design. Use this checklist to catch problems early and build more inclusive experiences.</p>]]></content:encoded>
    </item>
    <item>
      <title>Working from Home as a Developer – Tips and Tools</title>
      <link>https://letanure.dev/writing/remote-work-dev-tips/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/remote-work-dev-tips/</guid>
      <pubDate>Mon, 05 Oct 2020 00:00:00 GMT</pubDate>
      <description>Practical advice for developers adjusting to remote work – setup, tools, and staying productive.</description>
      <content:encoded><![CDATA[<p>Working from home became the new normal for many developers in 2020. For some, it was a smooth transition. For others, it brought new challenges: distractions, isolation, and the need for better time management.</p>
<p>This post shares some practical tips, tools, and habits that help developers stay productive and sane when working remotely.</p>
<h2 id="workspace-setup">Workspace Setup</h2>
<p>A good setup makes a huge difference. It doesn’t need to be expensive or fancy.</p>
<ul>
<li>Use a dedicated space if possible – avoid working from the couch or bed.</li>
<li>Invest in a decent chair and desk.</li>
<li>Use an external monitor and keyboard if you’re on a laptop.</li>
<li>Good lighting helps with video calls and eye strain.</li>
<li>Use noise-canceling headphones or earplugs for focus.</li>
</ul>
<h2 id="tools-for-communication">Tools for Communication</h2>
<p>Keeping in sync with your team is essential. Use tools that help communicate clearly and often.</p>
<ul>
<li><strong>Slack</strong> or <strong>Microsoft Teams</strong> – for real-time messaging and quick updates.</li>
<li><strong>Zoom</strong> or <strong>Google Meet</strong> – for stand-ups, pair programming, and one-on-ones.</li>
<li><strong>Notion</strong>, <strong>Confluence</strong>, or <strong>Docs</strong> – to write and share long-form updates or decisions.</li>
<li><strong>Trello</strong>, <strong>Jira</strong>, or <strong>Linear</strong> – for task tracking and project visibility.</li>
</ul>
<h2 id="time-and-task-management">Time and Task Management</h2>
<p>Without the office routine, structure matters even more.</p>
<ul>
<li>Block your day with clear work hours and breaks.</li>
<li>Use a simple task list – pen and paper, Todoist, or your favorite app.</li>
<li>Turn off non-essential notifications during deep work.</li>
<li>Use the Pomodoro technique or timeboxing to stay focused.</li>
</ul>
<h2 id="healthy-habits">Healthy Habits</h2>
<p>Remote work can blur the line between personal and work time.</p>
<ul>
<li>Set a start and end time to your day.</li>
<li>Get dressed like you’re going to the office – it signals your brain to switch to work mode.</li>
<li>Move regularly – stretch, walk, or do a short workout.</li>
<li>Eat away from your desk.</li>
<li>Talk to people – isolation is real. Schedule casual calls if needed.</li>
</ul>
<h2 id="mental-health-matters">Mental Health Matters</h2>
<p>Remote work can get lonely. Stay connected.</p>
<ul>
<li>Join online communities or developer meetups.</li>
<li>Have non-work chats with teammates.</li>
<li>Take mental health breaks. It’s fine to pause when needed.</li>
</ul>
<p>Remote work is here to stay in some form. Learning how to thrive in it is worth the effort.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Deno 1.0 – First Impressions of Node’s New Rival</title>
      <link>https://letanure.dev/writing/deno-first-impressions/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/deno-first-impressions/</guid>
      <pubDate>Mon, 10 Aug 2020 00:00:00 GMT</pubDate>
      <description>Exploring Deno 1.0, a new JavaScript and TypeScript runtime with modern features and strong security.</description>
      <content:encoded><![CDATA[<p>Deno is a secure runtime for JavaScript and TypeScript created by Ryan Dahl, the original creator of Node.js. Deno 1.0 was released with some strong opinions and a clear goal: improve on Node by learning from its limitations.</p>
<h2 id="key-features">Key Features</h2>
<ul>
<li>Built-in TypeScript support</li>
<li>Uses ES module imports (URLs or local paths)</li>
<li>No <code>node_modules</code> folder or <code>package.json</code></li>
<li>Secure by default (no file, network, or environment access unless allowed)</li>
<li>Ships as a single binary</li>
<li>Comes with built-in utilities like a formatter, bundler, and test runner</li>
</ul>
<h2 id="basic-script-example">Basic Script Example</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#6A737D">// hello.ts</span></span>
<span class="line"><span style="color:#E1E4E8">console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;Hello from Deno&quot;</span><span style="color:#E1E4E8">);</span></span></code></pre>
<p>Run it with:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">deno</span><span style="color:#9ECBFF"> run</span><span style="color:#9ECBFF"> hello.ts</span></span></code></pre>
<p>Deno checks permissions by default. For example, to allow reading files:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">deno</span><span style="color:#9ECBFF"> run</span><span style="color:#79B8FF"> --allow-read</span><span style="color:#9ECBFF"> hello.ts</span></span></code></pre>
<h2 id="importing-modules">Importing Modules</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { serve } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &quot;https://deno.land/std@0.61.0/http/server.ts&quot;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> s</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> serve</span><span style="color:#E1E4E8">({ port: </span><span style="color:#79B8FF">8000</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;Listening on http://localhost:8000&quot;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">for</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">const</span><span style="color:#79B8FF"> req</span><span style="color:#F97583"> of</span><span style="color:#E1E4E8"> s) {</span></span>
<span class="line"><span style="color:#E1E4E8">  req.</span><span style="color:#B392F0">respond</span><span style="color:#E1E4E8">({ body: </span><span style="color:#9ECBFF">&quot;Hello Deno</span><span style="color:#79B8FF">\n</span><span style="color:#9ECBFF">&quot;</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<ul>
<li>No <code>npm install</code></li>
<li>No <code>package.json</code></li>
<li>Modules are cached and compiled once</li>
</ul>
<h2 id="pros">Pros</h2>
<ul>
<li>Simpler setup</li>
<li>Secure by default</li>
<li>Strong focus on modern JavaScript</li>
<li>First-class TypeScript support</li>
</ul>
<h2 id="cons">Cons</h2>
<ul>
<li>Smaller ecosystem compared to Node</li>
<li>Some missing mature libraries</li>
<li>Different standard modules from Node.js</li>
</ul>
<h2 id="use-cases">Use Cases</h2>
<p>Deno is well-suited for:</p>
<ul>
<li>Scripts</li>
<li>Small web services</li>
<li>Secure server-side scripting</li>
<li>Learning modern JavaScript runtime internals</li>
</ul>
<p>It’s still early, but Deno is promising. Whether it replaces Node or carves out a niche remains to be seen. For now, it’s a clean and interesting option, especially for new projects that value security and simplicity.</p>]]></content:encoded>
    </item>
    <item>
      <title>Next.js for Beginners – Static and Server Rendering</title>
      <link>https://letanure.dev/writing/nextjs-static-server-rendering/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/nextjs-static-server-rendering/</guid>
      <pubDate>Fri, 05 Jun 2020 00:00:00 GMT</pubDate>
      <description>A beginner guide to Next.js with examples of static generation and server-side rendering using getStaticProps.</description>
      <content:encoded><![CDATA[<p>Next.js makes it easy to build fast and SEO-friendly React apps. It combines the best parts of static sites and server-rendered apps.</p>
<p>You don’t need extra setup to support static generation (SSG) or server-side rendering (SSR). Next.js handles both out of the box.</p>
<h2 id="basic-concepts">Basic Concepts</h2>
<ul>
<li><strong>Pages</strong>: Every file in the <code>pages</code> folder becomes a route.</li>
<li><strong>SSG</strong>: Pre-renders pages at build time using <code>getStaticProps</code>.</li>
<li><strong>SSR</strong>: Pre-renders pages on each request using <code>getServerSideProps</code>.</li>
</ul>
<h2 id="example-static-blog-with-getstaticprops">Example: Static Blog with getStaticProps</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#6A737D">// pages/posts.js</span></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> async</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> getStaticProps</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> posts</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetchPostsFromCMS</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">    props: { posts },</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> Posts</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">posts</span><span style="color:#E1E4E8"> }) {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      {posts.</span><span style="color:#B392F0">map</span><span style="color:#E1E4E8">((</span><span style="color:#FFAB70">p</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">        &lt;</span><span style="color:#85E89D">li</span><span style="color:#B392F0"> key</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{p.id}&gt;{p.title}&lt;/</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      ))}</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<ul>
<li>This will generate the page at build time.</li>
<li>Fast load, good SEO.</li>
</ul>
<h2 id="server-side-example">Server-Side Example</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#6A737D">// pages/dashboard.js</span></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> async</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> getServerSideProps</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> data</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetchSecureDashboardData</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">    props: { data },</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> Dashboard</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">data</span><span style="color:#E1E4E8"> }) {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">pre</span><span style="color:#E1E4E8">&gt;{</span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">(data)}&lt;/</span><span style="color:#85E89D">pre</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<ul>
<li>This page is generated on every request.</li>
<li>Use it when data changes often or depends on auth/session.</li>
</ul>
<h2 id="routing-and-navigation">Routing and Navigation</h2>
<p>Next.js uses file-based routing. For links:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> Link </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;next/link&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#79B8FF">Link</span><span style="color:#B392F0"> href</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">&quot;/about&quot;</span><span style="color:#E1E4E8">&gt;About&lt;/</span><span style="color:#79B8FF">Link</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<h2 id="setup">Setup</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> create-next-app</span><span style="color:#9ECBFF"> my-app</span></span>
<span class="line"><span style="color:#79B8FF">cd</span><span style="color:#9ECBFF"> my-app</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> run</span><span style="color:#9ECBFF"> dev</span></span></code></pre>
<p>This gives you:</p>
<ul>
<li>React 16+</li>
<li>File-based routing</li>
<li>Fast builds and hot reload</li>
</ul>
<h2 id="when-to-use-what">When to Use What</h2>
<ul>
<li>Use <code>getStaticProps</code> when content doesn’t change often.</li>
<li>Use <code>getServerSideProps</code> when content is dynamic.</li>
<li>Use <code>getStaticPaths</code> for dynamic routes.</li>
</ul>
<p>Next.js became a go-to tool for React devs who want performance, simplicity, and a good developer experience—all without losing flexibility.</p>]]></content:encoded>
    </item>
    <item>
      <title>Svelte 3 – A Radical New Approach to UI</title>
      <link>https://letanure.dev/writing/svelte-3-introduction/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/svelte-3-introduction/</guid>
      <pubDate>Fri, 10 Apr 2020 00:00:00 GMT</pubDate>
      <description>An introduction to Svelte 3 and how it compiles UI components at build time for performance and simplicity.</description>
      <content:encoded><![CDATA[<p>Svelte 3 introduced a new approach to building web UIs. Instead of using a virtual DOM like React or Vue, Svelte compiles your components at build time into efficient, minimal JavaScript. This means less runtime overhead and better performance.</p>
<h2 id="why-svelte-is-different">Why Svelte Is Different</h2>
<ul>
<li>No virtual DOM</li>
<li>Compiles to native JavaScript</li>
<li>Built-in reactivity without external state management</li>
<li>Smaller bundle sizes</li>
</ul>
<h2 id="basic-svelte-component">Basic Svelte Component</h2>
<p>Here’s a simple <code>Counter</code> component:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="javascript"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  let count = 0;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">  function increment() {</span></span>
<span class="line"><span style="color:#E1E4E8">    count </span><span style="color:#F97583">+=</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> on</span><span style="color:#E1E4E8">:</span><span style="color:#B392F0">click</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{increment}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  Clicked {count} times</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>Any assignment to <code>count</code> automatically updates the DOM. You don’t need to use <code>setState</code> or call any render functions.</p>
<h2 id="setting-up-svelte">Setting Up Svelte</h2>
<p>You can use the official template to start quickly.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> degit</span><span style="color:#9ECBFF"> sveltejs/template</span><span style="color:#9ECBFF"> svelte-app</span></span>
<span class="line"><span style="color:#79B8FF">cd</span><span style="color:#9ECBFF"> svelte-app</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> run</span><span style="color:#9ECBFF"> dev</span></span></code></pre>
<p>This sets up a project with rollup and hot reload.</p>
<h2 id="reactive-statements">Reactive Statements</h2>
<p>Svelte also lets you define reactive values based on other variables:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="javascript"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  let a = 1;</span></span>
<span class="line"><span style="color:#E1E4E8">  let b = 2;</span></span>
<span class="line"><span style="color:#E1E4E8">  $: sum = a + b;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;{a} + {b} = {sum}&lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>The <code>$:</code> syntax makes <code>sum</code> update automatically whenever <code>a</code> or <code>b</code> changes.</p>
<h2 id="styling">Styling</h2>
<p>Svelte scopes styles to each component:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="javascript"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">style</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  button {</span></span>
<span class="line"><span style="color:#E1E4E8">    background</span><span style="color:#F97583">-</span><span style="color:#E1E4E8">color: coral;</span></span>
<span class="line"><span style="color:#E1E4E8">    color: white;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">style</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>No CSS-in-JS or BEM necessary.</p>
<h2 id="when-to-use-svelte">When to Use Svelte</h2>
<p>Svelte is a good choice when you want:</p>
<ul>
<li>Simple state and logic</li>
<li>Fast initial load and performance</li>
<li>Less boilerplate and tooling</li>
</ul>
<p>It’s especially great for personal projects, static sites, or widgets where bundle size matters.</p>
<p>Svelte 3 challenged many assumptions about how frontend frameworks should work. It focused on simplicity and efficiency—values that many developers were looking for in 2020.</p>]]></content:encoded>
    </item>
    <item>
      <title>Design Systems 2.0 – Atomic Design in Practice</title>
      <link>https://letanure.dev/writing/atomic-design-systems/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/atomic-design-systems/</guid>
      <pubDate>Thu, 12 Mar 2020 00:00:00 GMT</pubDate>
      <description>Applying Atomic Design principles to build scalable and consistent design systems using reusable components.</description>
      <content:encoded><![CDATA[<p>Atomic Design is a method for creating design systems based on the idea of breaking down UIs into fundamental building blocks. Introduced by Brad Frost, this approach helps teams create scalable, reusable components with a clear hierarchy.</p>
<h2 id="what-is-atomic-design">What is Atomic Design?</h2>
<p>Atomic Design structures UI components into five levels:</p>
<ul>
<li><strong>Atoms</strong>: The basic building blocks like buttons, inputs, labels.</li>
<li><strong>Molecules</strong>: Simple combinations of atoms. For example, a form label + input + button.</li>
<li><strong>Organisms</strong>: Complex UI sections composed of molecules and atoms. Example: a navbar or a card.</li>
<li><strong>Templates</strong>: Page-level layouts using organisms and components.</li>
<li><strong>Pages</strong>: Final views with real content.</li>
</ul>
<p>This structure improves consistency and encourages reuse.</p>
<h2 id="setting-up-a-design-system-with-atomic-design">Setting Up a Design System with Atomic Design</h2>
<ol>
<li>
<p><strong>Audit your UI</strong></p>
<ul>
<li>List recurring UI elements (buttons, headings, forms).</li>
<li>Identify inconsistencies in spacing, colors, font sizes.</li>
</ul>
</li>
<li>
<p><strong>Create your atoms</strong></p>
<ul>
<li>Use consistent naming.</li>
<li>Example: <code>Button</code>, <code>InputField</code>, <code>TextLabel</code>.</li>
</ul>
</li>
</ol>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#6A737D">// Button.js</span></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> Button</span><span style="color:#E1E4E8">({ </span><span style="color:#FFAB70">children</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">onClick</span><span style="color:#E1E4E8"> }) {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> className</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">&quot;btn&quot;</span><span style="color:#B392F0"> onClick</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{onClick}&gt;{children}&lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<ol start="3">
<li><strong>Combine into molecules</strong>
<ul>
<li>Pair buttons with inputs or labels.</li>
</ul>
</li>
</ol>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#6A737D">// SearchBox.js</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> Button </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;./Button&#39;</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> Input </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;./InputField&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> SearchBox</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> className</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">&quot;search&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#79B8FF">Input</span><span style="color:#B392F0"> placeholder</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">&quot;Search...&quot;</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#79B8FF">Button</span><span style="color:#E1E4E8">&gt;Go&lt;/</span><span style="color:#79B8FF">Button</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  )</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<ol start="4">
<li><strong>Assemble organisms</strong>
<ul>
<li>Sections like headers, footers, or cards.</li>
</ul>
</li>
</ol>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#6A737D">// Header.js</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> Logo </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;./Logo&#39;</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> NavLinks </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;./NavLinks&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> Header</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">header</span><span style="color:#B392F0"> className</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">&quot;site-header&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#79B8FF">Logo</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#79B8FF">NavLinks</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">header</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  )</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<ol start="5">
<li><strong>Build templates and pages</strong>
<ul>
<li>Wireframe complete layouts using your component library.</li>
</ul>
</li>
</ol>
<h2 id="document-your-components">Document Your Components</h2>
<p>Use a tool like Storybook to:</p>
<ul>
<li>Preview components in isolation</li>
<li>Display usage guidelines</li>
<li>Help designers and developers stay aligned</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Install Storybook</span></span>
<span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> sb</span><span style="color:#9ECBFF"> init</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> run</span><span style="color:#9ECBFF"> storybook</span></span></code></pre>
<h2 id="why-atomic-design-helps">Why Atomic Design Helps</h2>
<ul>
<li>Clear structure and naming</li>
<li>Faster prototyping with reusable components</li>
<li>Better communication between design and dev</li>
<li>Easier to onboard new team members</li>
</ul>
<p>Atomic Design gives you a mental model to create UIs that scale well across teams and projects.</p>]]></content:encoded>
    </item>
    <item>
      <title>Micro-Frontends – Scaling Your Front-End Architecture</title>
      <link>https://letanure.dev/writing/micro-frontends-intro/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/micro-frontends-intro/</guid>
      <pubDate>Fri, 10 Jan 2020 00:00:00 GMT</pubDate>
      <description>Learn what micro-frontends are, why they matter, and how to apply them to large-scale applications.</description>
      <content:encoded><![CDATA[<p>Micro-frontends are a way to split a large front-end application into smaller, more manageable pieces. Each piece (or “micro-frontend”) is owned by a different team and can be developed, deployed, and updated independently.</p>
<p>This idea comes from microservices, but applied to the front-end.</p>
<h2 id="what-are-micro-frontends">What Are Micro-Frontends?</h2>
<ul>
<li><strong>Independent front-end apps</strong> that can be developed and deployed separately.</li>
<li>Often loaded at runtime into a main “shell” or container application.</li>
<li>Useful in large teams or enterprise apps where different parts of the UI evolve separately.</li>
</ul>
<h2 id="benefits">Benefits</h2>
<ul>
<li><strong>Independent deployments</strong>: Teams can release their features without coordinating with others.</li>
<li><strong>Technology flexibility</strong>: Teams can use different stacks (React, Vue, etc.) if needed.</li>
<li><strong>Team autonomy</strong>: Smaller teams can take full ownership of their parts of the UI.</li>
<li><strong>Code isolation</strong>: Reduced risk of regressions across unrelated parts of the app.</li>
</ul>
<h2 id="challenges">Challenges</h2>
<ul>
<li><strong>Initial setup complexity</strong></li>
<li><strong>Cross-team coordination</strong></li>
<li><strong>Shared dependencies</strong> (e.g., design systems, global state)</li>
<li><strong>Performance and loading times</strong> (more assets to download)</li>
</ul>
<h2 id="example-use-case">Example Use Case</h2>
<p>Imagine an e-commerce site:</p>
<ul>
<li><strong>Homepage</strong>: Core team</li>
<li><strong>Product Search</strong>: Search team</li>
<li><strong>Product Details</strong>: Catalog team</li>
<li><strong>Shopping Cart</strong>: Checkout team</li>
<li><strong>User Profile</strong>: Account team</li>
</ul>
<p>Each of these could be a micro-frontend, deployed on its own and integrated into a shared layout.</p>
<h2 id="approaches">Approaches</h2>
<h3 id="server-side-composition">Server-Side Composition</h3>
<ul>
<li>Each micro-frontend is rendered on the server and merged before being sent to the browser.</li>
<li>Works well with traditional server-rendered apps.</li>
</ul>
<h3 id="client-side-composition">Client-Side Composition</h3>
<ul>
<li>The shell app loads each micro-frontend at runtime via JavaScript.</li>
<li>Allows more flexibility but needs careful handling of dependencies.</li>
</ul>
<h3 id="webpack-module-federation-introduced-in-webpack-5">Webpack Module Federation (introduced in Webpack 5)</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#6A737D">// Example config snippet</span></span>
<span class="line"><span style="color:#F97583">new</span><span style="color:#B392F0"> ModuleFederationPlugin</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">  name: </span><span style="color:#9ECBFF">&#39;checkout&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  filename: </span><span style="color:#9ECBFF">&#39;remoteEntry.js&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  exposes: {</span></span>
<span class="line"><span style="color:#9ECBFF">    &#39;./Cart&#39;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&#39;./src/components/Cart&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#E1E4E8">  shared: [</span><span style="color:#9ECBFF">&#39;react&#39;</span><span style="color:#E1E4E8">, </span><span style="color:#9ECBFF">&#39;react-dom&#39;</span><span style="color:#E1E4E8">],</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<h2 id="when-to-use-micro-frontends">When to Use Micro-Frontends</h2>
<ul>
<li>You have <strong>many teams</strong> working on the same front-end codebase.</li>
<li>You want <strong>independent deployments</strong>.</li>
<li>You maintain <strong>separate domains</strong> of business logic.</li>
<li>Your app is <strong>too large</strong> for a single team to own or understand.</li>
</ul>
<p>If you’re in a small team or project, micro-frontends may add more complexity than value.</p>
<h2 id="final-thoughts">Final Thoughts</h2>
<p>Micro-frontends aren’t for every project. But for large apps with many teams, they can help scale your architecture in a clean and maintainable way.</p>]]></content:encoded>
    </item>
    <item>
      <title>Going Serverless Part 2 – Building a REST API with No Servers</title>
      <link>https://letanure.dev/writing/serverless-api-no-servers/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/serverless-api-no-servers/</guid>
      <pubDate>Sun, 10 Nov 2019 00:00:00 GMT</pubDate>
      <description>A tutorial on using serverless functions to build a simple REST API without managing backend infrastructure.</description>
      <content:encoded><![CDATA[<p>This post continues the exploration of serverless by showing how to create a REST API using serverless functions.</p>
<h2 id="what-is-serverless">What Is Serverless?</h2>
<p>Serverless doesn’t mean there’s no server. It means:</p>
<ul>
<li>You don’t manage the server.</li>
<li>You write functions that respond to HTTP events.</li>
<li>They scale automatically and only run when called.</li>
</ul>
<h2 id="example-project-guestbook-api">Example Project: Guestbook API</h2>
<p>Create an API to:</p>
<ul>
<li><code>GET /entries</code> – fetch all guestbook entries</li>
<li><code>POST /entries</code> – add a new entry</li>
</ul>
<h2 id="option-1-netlify-functions">Option 1: Netlify Functions</h2>
<h3 id="1-setup">1. Setup</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#9ECBFF"> netlify-cli</span><span style="color:#79B8FF"> -g</span></span>
<span class="line"><span style="color:#B392F0">netlify</span><span style="color:#9ECBFF"> init</span></span>
<span class="line"><span style="color:#B392F0">netlify</span><span style="color:#9ECBFF"> functions:create</span></span></code></pre>
<p>Create a file at <code>netlify/functions/entries.js</code>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#79B8FF">exports</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">handler</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">event</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (event.httpMethod </span><span style="color:#F97583">===</span><span style="color:#9ECBFF"> &quot;GET&quot;</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">      statusCode: </span><span style="color:#79B8FF">200</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">      body: </span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">([{ name: </span><span style="color:#9ECBFF">&quot;Luiz&quot;</span><span style="color:#E1E4E8">, message: </span><span style="color:#9ECBFF">&quot;Great blog!&quot;</span><span style="color:#E1E4E8"> }]),</span></span>
<span class="line"><span style="color:#E1E4E8">    };</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  if</span><span style="color:#E1E4E8"> (event.httpMethod </span><span style="color:#F97583">===</span><span style="color:#9ECBFF"> &quot;POST&quot;</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> data</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">parse</span><span style="color:#E1E4E8">(event.body);</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">      statusCode: </span><span style="color:#79B8FF">201</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">      body: </span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">({ saved: </span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8">, data }),</span></span>
<span class="line"><span style="color:#E1E4E8">    };</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> { statusCode: </span><span style="color:#79B8FF">405</span><span style="color:#E1E4E8"> };</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p>Run locally:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">netlify</span><span style="color:#9ECBFF"> dev</span></span></code></pre>
<p>Call from front-end with fetch:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#B392F0">fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;/.netlify/functions/entries&quot;</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8">  .</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">res</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">())</span></span>
<span class="line"><span style="color:#E1E4E8">  .</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">data</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(data));</span></span></code></pre>
<h2 id="option-2-aws-lambda--api-gateway">Option 2: AWS Lambda + API Gateway</h2>
<p>This requires more setup, but is useful for production:</p>
<ul>
<li>Use AWS SAM or Serverless Framework</li>
<li>Define function handler and route via API Gateway</li>
<li>Deploy with AWS CLI</li>
</ul>
<h2 id="benefits">Benefits</h2>
<ul>
<li>No server provisioning or maintenance</li>
<li>Scales automatically</li>
<li>Pay per request</li>
<li>Works well with static frontends (like JAMstack sites)</li>
</ul>
<hr/>
<p>Serverless is more than just a trend. It’s a solid way to build real APIs without the weight of traditional backend stacks.</p>]]></content:encoded>
    </item>
    <item>
      <title>Building a Component Library – Our Design System Journey</title>
      <link>https://letanure.dev/writing/component-library-design-system/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/component-library-design-system/</guid>
      <pubDate>Sun, 15 Sep 2019 00:00:00 GMT</pubDate>
      <description>How we created a shared UI library to improve consistency, speed up development, and collaborate better with design.</description>
      <content:encoded><![CDATA[<p>Creating a component library helped us unify the look and feel of an application while speeding up development and improving collaboration with designers.</p>
<h2 id="why-build-a-component-library">Why Build a Component Library?</h2>
<ul>
<li>Keep styles and behaviors consistent across the app</li>
<li>Reuse logic and reduce code duplication</li>
<li>Improve onboarding for new team members</li>
<li>Share visual language with design team</li>
</ul>
<h2 id="step-1-identify-reusable-components">Step 1: Identify Reusable Components</h2>
<p>Start with the basics:</p>
<ul>
<li>Buttons</li>
<li>Form inputs (text fields, checkboxes, radios)</li>
<li>Modals and popups</li>
<li>Notifications and alerts</li>
<li>Layout containers (grids, wrappers)</li>
</ul>
<p>List what you use often and generalize patterns that repeat.</p>
<h2 id="step-2-set-up-the-component-folder">Step 2: Set Up the Component Folder</h2>
<p>We created a <code>/components</code> folder and grouped things by type.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">src/</span></span>
<span class="line"><span style="color:#B392F0">├──</span><span style="color:#9ECBFF"> components/</span></span>
<span class="line"><span style="color:#B392F0">│</span><span style="color:#9ECBFF">   ├──</span><span style="color:#9ECBFF"> Button/</span></span>
<span class="line"><span style="color:#B392F0">│</span><span style="color:#9ECBFF">   │</span><span style="color:#9ECBFF">   ├──</span><span style="color:#9ECBFF"> Button.tsx</span></span>
<span class="line"><span style="color:#B392F0">│</span><span style="color:#9ECBFF">   │</span><span style="color:#9ECBFF">   ├──</span><span style="color:#9ECBFF"> Button.stories.tsx</span></span>
<span class="line"><span style="color:#B392F0">│</span><span style="color:#9ECBFF">   │</span><span style="color:#9ECBFF">   └──</span><span style="color:#9ECBFF"> index.ts</span></span>
<span class="line"><span style="color:#B392F0">│</span><span style="color:#9ECBFF">   ├──</span><span style="color:#9ECBFF"> Modal/</span></span>
<span class="line"><span style="color:#B392F0">│</span><span style="color:#9ECBFF">   └──</span><span style="color:#9ECBFF"> ...</span></span></code></pre>
<p>Each component has:</p>
<ul>
<li>The code</li>
<li>A test (optional)</li>
<li>A Storybook story (for visual testing)</li>
</ul>
<h2 id="step-3-use-storybook">Step 3: Use Storybook</h2>
<p>Storybook helped us:</p>
<ul>
<li>Document how each component works</li>
<li>Preview variants (sizes, colors, states)</li>
<li>Share with designers and QA</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> sb</span><span style="color:#9ECBFF"> init</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> run</span><span style="color:#9ECBFF"> storybook</span></span></code></pre>
<p>This setup made it easier to demo and test components in isolation.</p>
<h2 id="step-4-add-tokens-and-themes">Step 4: Add Tokens and Themes</h2>
<p>We also added a <code>theme.ts</code> file to centralize colors, spacing, font sizes, and other values.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> const</span><span style="color:#79B8FF"> theme</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  colors: {</span></span>
<span class="line"><span style="color:#E1E4E8">    primary: </span><span style="color:#9ECBFF">&quot;#0070f3&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    danger: </span><span style="color:#9ECBFF">&quot;#e00&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    gray: </span><span style="color:#9ECBFF">&quot;#666&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#E1E4E8">  spacing: [</span><span style="color:#79B8FF">4</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">8</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">16</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">32</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">64</span><span style="color:#E1E4E8">]</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p>Then passed the theme into styled components or context providers.</p>
<h2 id="what-we-gained">What We Gained</h2>
<ul>
<li>Faster development with ready-to-use blocks</li>
<li>Consistency across screens and developers</li>
<li>Better handoff from Figma to code</li>
<li>Easier testing and documentation</li>
</ul>
<hr/>
<p>A component library is not just for large teams. Even solo projects benefit from consistent UI and code reuse. Once you start building with shared pieces, it’s hard to go back.</p>]]></content:encoded>
    </item>
    <item>
      <title>Adopting TypeScript – Tips from Our Transition</title>
      <link>https://letanure.dev/writing/adopting-typescript/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/adopting-typescript/</guid>
      <pubDate>Thu, 22 Aug 2019 00:00:00 GMT</pubDate>
      <description>Lessons learned while migrating a JavaScript project to TypeScript, with practical tips for a smoother transition.</description>
      <content:encoded><![CDATA[<p>Switching from JavaScript to TypeScript doesn’t have to be all at once. We migrated a mid-size project over several weeks and learned a lot along the way.</p>
<h2 id="why-move-to-typescript">Why Move to TypeScript?</h2>
<ul>
<li>Catches common bugs at compile time</li>
<li>Improves code editor support (autocomplete, refactoring)</li>
<li>Makes collaboration easier with better-defined types</li>
</ul>
<h2 id="step-1-enable-gradual-typing">Step 1: Enable Gradual Typing</h2>
<p>Use <code>allowJs</code> to let JavaScript and TypeScript files coexist:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#6A737D">// tsconfig.json</span></span>
<span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;compilerOptions&quot;</span><span style="color:#E1E4E8">: {</span></span>
<span class="line"><span style="color:#79B8FF">    &quot;allowJs&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">    &quot;checkJs&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">false</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">    &quot;outDir&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;./dist&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">    &quot;target&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;es6&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">    &quot;module&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;commonjs&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;include&quot;</span><span style="color:#E1E4E8">: [</span><span style="color:#9ECBFF">&quot;src/**/*&quot;</span><span style="color:#E1E4E8">]</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>This way, we converted files incrementally.</p>
<h2 id="step-2-add-jsdoc-for-existing-js">Step 2: Add JSDoc for Existing JS</h2>
<p>For files not yet converted, add basic JSDoc types:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#6A737D">/**</span></span>
<span class="line"><span style="color:#6A737D"> * </span><span style="color:#F97583">@param</span><span style="color:#B392F0"> {string}</span><span style="color:#E1E4E8"> name</span></span>
<span class="line"><span style="color:#6A737D"> * </span><span style="color:#F97583">@returns</span><span style="color:#B392F0"> {string}</span></span>
<span class="line"><span style="color:#6A737D"> */</span></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> greet</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">name</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#9ECBFF"> `Hello, ${</span><span style="color:#E1E4E8">name</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>This gave us editor type checking without converting everything to <code>.ts</code>.</p>
<h2 id="step-3-convert-files-slowly">Step 3: Convert Files Slowly</h2>
<p>We started by converting utility functions and new files to <code>.ts</code>.</p>
<ul>
<li>Kept <code>.js</code> files untouched where stable</li>
<li>Converted shared types to <code>.d.ts</code> or <code>.ts</code> files</li>
<li>Used type aliases and <code>any</code> when stuck, then refined</li>
</ul>
<h2 id="step-4-deal-with-third-party-types">Step 4: Deal with Third-Party Types</h2>
<p>Many packages don’t ship types. Use DefinitelyTyped:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> --save-dev</span><span style="color:#9ECBFF"> @types/lodash</span></span></code></pre>
<p>Or add your own quick fix in <code>types.d.ts</code>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">declare</span><span style="color:#F97583"> module</span><span style="color:#9ECBFF"> &#39;my-untagged-lib&#39;</span><span style="color:#E1E4E8">;</span></span></code></pre>
<h2 id="wins-we-saw-early">Wins We Saw Early</h2>
<ul>
<li>Found bugs like undefined props</li>
<li>Simplified debugging with better autocomplete</li>
<li>Cleaner function contracts and return types</li>
</ul>
<h2 id="common-tips">Common Tips</h2>
<ul>
<li>Don’t rewrite the app all at once</li>
<li>Use <code>any</code> and <code>@ts-ignore</code> only temporarily</li>
<li>Start with the files that get touched the most</li>
<li>Define shared interfaces and types early</li>
</ul>
<hr/>
<p>The migration wasn’t free, but TypeScript brought real, daily benefits. If your team is on the fence, try a partial rollout and see how it improves the workflow.</p>]]></content:encoded>
    </item>
    <item>
      <title>WebAssembly in Practice – Speeding Up Image Processing</title>
      <link>https://letanure.dev/writing/wasm-image-processing/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/wasm-image-processing/</guid>
      <pubDate>Thu, 20 Jun 2019 00:00:00 GMT</pubDate>
      <description>A practical demo using WebAssembly to handle CPU-heavy image tasks faster than JavaScript.</description>
      <content:encoded><![CDATA[<p>WebAssembly lets us run compiled code from C, C++, or Rust in the browser. It opens up a new world for front-end developers needing performance for heavy tasks.</p>
<p>In this post, we’ll use WebAssembly to process an image—resizing or applying a grayscale filter—and compare it to a JavaScript version.</p>
<h2 id="why-use-webassembly-for-this">Why Use WebAssembly for This?</h2>
<ul>
<li>JavaScript is single-threaded and not optimized for CPU-heavy operations.</li>
<li>WebAssembly is compiled and runs closer to native speed.</li>
<li>You can reuse existing C/C++ libraries with little overhead.</li>
</ul>
<h2 id="step-1-compile-the-c-code-to-webassembly">Step 1: Compile the C Code to WebAssembly</h2>
<p>This is a simple image grayscale function written in C.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="c"><code><span class="line"><span style="color:#6A737D">// grayscale.c</span></span>
<span class="line"><span style="color:#F97583">#include</span><span style="color:#9ECBFF"> &lt;stdint.h&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">void</span><span style="color:#B392F0"> grayscale</span><span style="color:#E1E4E8">(</span><span style="color:#F97583">uint8_t*</span><span style="color:#FFAB70"> data</span><span style="color:#E1E4E8">, </span><span style="color:#F97583">int</span><span style="color:#FFAB70"> size</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  for</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">int</span><span style="color:#E1E4E8"> i </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">; i </span><span style="color:#F97583">&lt;</span><span style="color:#E1E4E8"> size; i </span><span style="color:#F97583">+=</span><span style="color:#79B8FF"> 4</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">    uint8_t</span><span style="color:#E1E4E8"> avg </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">data</span><span style="color:#E1E4E8">[i] </span><span style="color:#F97583">+</span><span style="color:#FFAB70"> data</span><span style="color:#E1E4E8">[i </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">+</span><span style="color:#FFAB70"> data</span><span style="color:#E1E4E8">[i </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> 2</span><span style="color:#E1E4E8">]) </span><span style="color:#F97583">/</span><span style="color:#79B8FF"> 3</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">    data</span><span style="color:#E1E4E8">[i] </span><span style="color:#F97583">=</span><span style="color:#FFAB70"> data</span><span style="color:#E1E4E8">[i </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#FFAB70"> data</span><span style="color:#E1E4E8">[i </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> 2</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> avg;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Compile it using Emscripten:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">emcc</span><span style="color:#9ECBFF"> grayscale.c</span><span style="color:#79B8FF"> -O3</span><span style="color:#79B8FF"> -s</span><span style="color:#9ECBFF"> WASM=</span><span style="color:#79B8FF">1</span><span style="color:#79B8FF"> -s</span><span style="color:#9ECBFF"> EXPORTED_FUNCTIONS=&#39;[&quot;_grayscale&quot;]&#39;</span><span style="color:#79B8FF"> -o</span><span style="color:#9ECBFF"> grayscale.js</span></span></code></pre>
<p>This gives you:</p>
<ul>
<li><code>grayscale.js</code> – glue code to run the module</li>
<li><code>grayscale.wasm</code> – compiled binary</li>
</ul>
<h2 id="step-2-load-the-wasm-module-in-javascript">Step 2: Load the WASM Module in JavaScript</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> wasm</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;grayscale.wasm&#39;</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">res</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">arrayBuffer</span><span style="color:#E1E4E8">());</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> module</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> WebAssembly.</span><span style="color:#B392F0">instantiate</span><span style="color:#E1E4E8">(wasm);</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> grayscale</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> module</span><span style="color:#E1E4E8">.instance.exports.grayscale;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// Now grayscale() can be called with an image buffer</span></span></code></pre>
<h2 id="step-3-compare-with-javascript">Step 3: Compare with JavaScript</h2>
<p>Here’s a JS version:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> grayscaleJS</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">data</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  for</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">let</span><span style="color:#E1E4E8"> i </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">; i </span><span style="color:#F97583">&lt;</span><span style="color:#E1E4E8"> data.</span><span style="color:#79B8FF">length</span><span style="color:#E1E4E8">; i </span><span style="color:#F97583">+=</span><span style="color:#79B8FF"> 4</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> avg</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (data[i] </span><span style="color:#F97583">+</span><span style="color:#E1E4E8"> data[i</span><span style="color:#F97583">+</span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">+</span><span style="color:#E1E4E8"> data[i</span><span style="color:#F97583">+</span><span style="color:#79B8FF">2</span><span style="color:#E1E4E8">]) </span><span style="color:#F97583">/</span><span style="color:#79B8FF"> 3</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">    data[i] </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> data[i</span><span style="color:#F97583">+</span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> data[i</span><span style="color:#F97583">+</span><span style="color:#79B8FF">2</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> avg;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>And the WASM call is:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> buffer</span><span style="color:#F97583"> =</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Uint8Array</span><span style="color:#E1E4E8">(imageData.data.buffer);</span></span>
<span class="line"><span style="color:#B392F0">grayscale</span><span style="color:#E1E4E8">(buffer, buffer.</span><span style="color:#79B8FF">length</span><span style="color:#E1E4E8">);</span></span></code></pre>
<h2 id="performance-results">Performance Results</h2>
<p>Tests show:</p>
<ul>
<li>WASM is 2–5x faster on large images</li>
<li>Less impact on main thread</li>
<li>Easier to scale for more filters or real-time edits</li>
</ul>
<hr/>
<p>This example shows how WebAssembly brings native performance to the web, unlocking use cases that were once too slow in JavaScript.</p>]]></content:encoded>
    </item>
    <item>
      <title>The JAMstack Revolution – Building with Hugo and Headless CMS</title>
      <link>https://letanure.dev/writing/jamstack-hugo-headless/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/jamstack-hugo-headless/</guid>
      <pubDate>Mon, 15 Apr 2019 00:00:00 GMT</pubDate>
      <description>A walkthrough of building a fast static site using Hugo and content pulled from a headless CMS via API, using the JAMstack model.</description>
      <content:encoded><![CDATA[<p>JAMstack stands for JavaScript, APIs, and Markup. It’s an approach to building websites that are static, fast, and secure—but powered by dynamic content from APIs.</p>
<p>We’ll walk through creating a site using Hugo, a static site generator written in Go, and pulling data from a headless CMS.</p>
<h2 id="why-jamstack">Why JAMstack?</h2>
<p>JAMstack separates:</p>
<ul>
<li>The frontend (markup, HTML, JS)</li>
<li>The content (delivered by APIs or CMS)</li>
<li>The build process (pre-rendered at deploy time)</li>
</ul>
<p>Benefits:</p>
<ul>
<li>Fast loading from static hosting (CDN)</li>
<li>Improved security (no backend server to hack)</li>
<li>Easier scaling</li>
<li>Better DX with modern tools</li>
</ul>
<h2 id="step-1-install-hugo">Step 1: Install Hugo</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">brew</span><span style="color:#9ECBFF"> install</span><span style="color:#9ECBFF"> hugo</span></span>
<span class="line"><span style="color:#B392F0">hugo</span><span style="color:#9ECBFF"> new</span><span style="color:#9ECBFF"> site</span><span style="color:#9ECBFF"> jamstack-demo</span></span>
<span class="line"><span style="color:#79B8FF">cd</span><span style="color:#9ECBFF"> jamstack-demo</span></span></code></pre>
<p>Pick a theme:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">git</span><span style="color:#9ECBFF"> init</span></span>
<span class="line"><span style="color:#B392F0">git</span><span style="color:#9ECBFF"> submodule</span><span style="color:#9ECBFF"> add</span><span style="color:#9ECBFF"> https://github.com/budparr/gohugo-theme-ananke</span><span style="color:#9ECBFF"> themes/ananke</span></span>
<span class="line"><span style="color:#79B8FF">echo</span><span style="color:#9ECBFF"> &#39;theme = &quot;ananke&quot;&#39;</span><span style="color:#F97583"> &gt;&gt;</span><span style="color:#9ECBFF"> config.toml</span></span></code></pre>
<h2 id="step-2-create-pages">Step 2: Create Pages</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">hugo</span><span style="color:#9ECBFF"> new</span><span style="color:#9ECBFF"> posts/my-first-post.md</span></span></code></pre>
<p>Edit the post in <code>content/posts/my-first-post.md</code>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="markdown"><code><span class="line"><span style="color:#79B8FF;font-weight:bold">---</span></span>
<span class="line"><span style="color:#E1E4E8">title: &quot;My First Post&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">date: 2019-04-15</span></span>
<span class="line"><span style="color:#79B8FF;font-weight:bold">---</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">This is my first JAMstack post powered by Hugo.</span></span></code></pre>
<h2 id="step-3-pull-content-from-a-headless-cms">Step 3: Pull Content from a Headless CMS</h2>
<p>Use a script (Node or Go) to fetch content via API from a CMS like:</p>
<ul>
<li>Contentful</li>
<li>Sanity</li>
<li>Strapi</li>
</ul>
<p>Save it as Markdown files into <code>content/posts/</code>.</p>
<p>Example fetch and write:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#6A737D">// fetch-posts.js</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> fs</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> require</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;fs&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> fetch</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> require</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;node-fetch&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">async</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> getPosts</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> res</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;https://api.mycms.com/posts&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> posts</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">  posts.</span><span style="color:#B392F0">forEach</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">post</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> content</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> `---</span></span>
<span class="line"><span style="color:#9ECBFF">title: &quot;${</span><span style="color:#E1E4E8">post</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">title</span><span style="color:#9ECBFF">}&quot;</span></span>
<span class="line"><span style="color:#9ECBFF">date: &quot;${</span><span style="color:#E1E4E8">post</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">date</span><span style="color:#9ECBFF">}&quot;</span></span>
<span class="line"><span style="color:#9ECBFF">---</span></span>
<span class="line"></span>
<span class="line"><span style="color:#9ECBFF">${</span><span style="color:#E1E4E8">post</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">body</span><span style="color:#9ECBFF">}</span></span>
<span class="line"><span style="color:#9ECBFF">`</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">    fs.</span><span style="color:#B392F0">writeFileSync</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`content/posts/${</span><span style="color:#E1E4E8">post</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">slug</span><span style="color:#9ECBFF">}.md`</span><span style="color:#E1E4E8">, content);</span></span>
<span class="line"><span style="color:#E1E4E8">  });</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">getPosts</span><span style="color:#E1E4E8">();</span></span></code></pre>
<p>Run this script before building the site:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">node</span><span style="color:#9ECBFF"> fetch-posts.js</span></span>
<span class="line"><span style="color:#B392F0">hugo</span></span></code></pre>
<h2 id="step-4-deploy-to-netlify">Step 4: Deploy to Netlify</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> -g</span><span style="color:#9ECBFF"> netlify-cli</span></span>
<span class="line"><span style="color:#B392F0">netlify</span><span style="color:#9ECBFF"> init</span></span>
<span class="line"><span style="color:#B392F0">netlify</span><span style="color:#9ECBFF"> deploy</span></span></code></pre>
<hr/>
<p>Using Hugo and a headless CMS shows how JAMstack can be flexible, fast, and suitable for both small sites and large content-driven platforms.</p>]]></content:encoded>
    </item>
    <item>
      <title>Using React Hooks – A New Way to Write Components</title>
      <link>https://letanure.dev/writing/using-react-hooks/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/using-react-hooks/</guid>
      <pubDate>Tue, 12 Feb 2019 00:00:00 GMT</pubDate>
      <description>How to use React Hooks like useState and useEffect to write simpler functional components instead of class-based ones.</description>
      <content:encoded><![CDATA[<p>React Hooks were introduced in version 16.8. They let you use state and lifecycle features in functional components. This changed how many people write React apps.</p>
<h2 id="why-hooks">Why Hooks?</h2>
<p>Before Hooks, you had to use class components to:</p>
<ul>
<li>Manage state</li>
<li>Use lifecycle methods</li>
<li>Share logic between components</li>
</ul>
<p>Hooks made this easier by adding functions like <code>useState</code> and <code>useEffect</code>.</p>
<h2 id="usestate-example">useState Example</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> React, { useState } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;react&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> Counter</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">count</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setCount</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;You clicked {count} times&lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> onClick</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{() </span><span style="color:#F97583">=&gt;</span><span style="color:#B392F0"> setCount</span><span style="color:#E1E4E8">(count </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">)}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">        Click me</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>No constructor, no <code>this</code>, just clean and readable.</p>
<h2 id="useeffect-example">useEffect Example</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> React, { useState, useEffect } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;react&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> Timer</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">seconds</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setSeconds</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">  useEffect</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> interval</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> setInterval</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0">      setSeconds</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">prev</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> prev </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">    }, </span><span style="color:#79B8FF">1000</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#B392F0"> clearInterval</span><span style="color:#E1E4E8">(interval);</span></span>
<span class="line"><span style="color:#E1E4E8">  }, []);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;{seconds} seconds have passed.&lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p><code>useEffect</code> replaces <code>componentDidMount</code>, <code>componentDidUpdate</code>, and <code>componentWillUnmount</code>.</p>
<h2 id="replacing-a-class-component">Replacing a Class Component</h2>
<p>Old class component:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">class</span><span style="color:#B392F0"> Counter</span><span style="color:#F97583"> extends</span><span style="color:#B392F0"> React</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">Component</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  state</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> { count: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8"> };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">  render</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> onClick</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{() </span><span style="color:#F97583">=&gt;</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">setState</span><span style="color:#E1E4E8">({ count: </span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">.state.count </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8"> })}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">        {</span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">.state.count}</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    );</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Now with Hooks:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> Counter</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">count</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">setCount</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useState</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> onClick</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{() </span><span style="color:#F97583">=&gt;</span><span style="color:#B392F0"> setCount</span><span style="color:#E1E4E8">(count </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">)}&gt;{count}&lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h2 id="why-this-matters">Why This Matters</h2>
<p>Hooks:</p>
<ul>
<li>Simplify code</li>
<li>Avoid class boilerplate</li>
<li>Make it easier to reuse logic with custom hooks</li>
</ul>
<hr/>
<p>Hooks changed the way we write React apps. They’re simple, flexible, and work well with today’s component-based design.</p>]]></content:encoded>
    </item>
    <item>
      <title>Going Serverless – Front-End Meets AWS Lambda</title>
      <link>https://letanure.dev/writing/going-serverless-lambda/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/going-serverless-lambda/</guid>
      <pubDate>Mon, 12 Nov 2018 00:00:00 GMT</pubDate>
      <description>Learn how to use AWS Lambda to handle backend logic without setting up a full server, perfect for simple tasks from your frontend app.</description>
      <content:encoded><![CDATA[<p>Serverless is a way to run backend code without managing servers. Instead of maintaining a backend service, you write small functions that are deployed to the cloud and run on demand.</p>
<p>This approach works great for front-end developers who need to:</p>
<ul>
<li>Send form data</li>
<li>Store emails</li>
<li>Call third-party APIs</li>
<li>Run small tasks</li>
</ul>
<h2 id="what-is-serverless">What Is Serverless?</h2>
<p>You write a function and deploy it to a provider like:</p>
<ul>
<li>AWS Lambda</li>
<li>Netlify Functions</li>
<li>Vercel Functions</li>
</ul>
<p>The function runs only when it’s called. You pay only for usage. There’s no always-on server.</p>
<h2 id="example-form-submission-with-aws-lambda">Example: Form Submission with AWS Lambda</h2>
<p>Let’s say we want to send a contact form.</p>
<h3 id="1-the-lambda-function">1. The Lambda Function</h3>
<p>Save this in <code>submitForm.js</code>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#79B8FF">exports</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">handler</span><span style="color:#F97583"> =</span><span style="color:#F97583"> async</span><span style="color:#E1E4E8"> (</span><span style="color:#FFAB70">event</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">name</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">email</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">message</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">parse</span><span style="color:#E1E4E8">(event.body);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">  // Do something with the data (e.g., send email, store in DB)</span></span>
<span class="line"><span style="color:#E1E4E8">  console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(name, email, message);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">    statusCode: </span><span style="color:#79B8FF">200</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    body: </span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">({ success: </span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8"> }),</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<h3 id="2-deploy-with-aws-cli">2. Deploy with AWS CLI</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">zip</span><span style="color:#9ECBFF"> function.zip</span><span style="color:#9ECBFF"> submitForm.js</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">aws</span><span style="color:#9ECBFF"> lambda</span><span style="color:#9ECBFF"> create-function</span><span style="color:#79B8FF"> --function-name</span><span style="color:#9ECBFF"> submitForm</span><span style="color:#79B8FF">   --zip-file</span><span style="color:#9ECBFF"> fileb://function.zip</span><span style="color:#79B8FF"> --handler</span><span style="color:#9ECBFF"> submitForm.handler</span><span style="color:#79B8FF">   --runtime</span><span style="color:#9ECBFF"> nodejs12.x</span><span style="color:#79B8FF"> --role</span><span style="color:#9ECBFF"> YOUR_IAM_ROLE_ARN</span></span></code></pre>
<h3 id="3-call-from-front-end">3. Call from Front-End</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#B392F0">fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;https://your-api-endpoint/submitForm&#39;</span><span style="color:#E1E4E8">, {</span></span>
<span class="line"><span style="color:#E1E4E8">  method: </span><span style="color:#9ECBFF">&#39;POST&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  body: </span><span style="color:#79B8FF">JSON</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">stringify</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">    name: </span><span style="color:#9ECBFF">&#39;Luiz&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    email: </span><span style="color:#9ECBFF">&#39;luiz@example.com&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    message: </span><span style="color:#9ECBFF">&#39;Hello!&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  }),</span></span>
<span class="line"><span style="color:#E1E4E8">})</span></span>
<span class="line"><span style="color:#E1E4E8">  .</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">res</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">())</span></span>
<span class="line"><span style="color:#E1E4E8">  .</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">data</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(data));</span></span></code></pre>
<h2 id="benefits-of-serverless-for-front-end-devs">Benefits of Serverless for Front-End Devs</h2>
<ul>
<li>Easy to add backend logic without full server setup</li>
<li>Scales automatically</li>
<li>Cheap for low-traffic or personal projects</li>
<li>Works well with static sites and JAMstack</li>
</ul>
<hr/>
<p>Serverless lets you stay in the frontend but still build powerful full-stack features. It’s a practical way to extend what your app can do with minimal setup.</p>]]></content:encoded>
    </item>
    <item>
      <title>Building a Design System – How We Standardized Our UI</title>
      <link>https://letanure.dev/writing/building-a-design-system/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/building-a-design-system/</guid>
      <pubDate>Tue, 18 Sep 2018 00:00:00 GMT</pubDate>
      <description>A guide on how we created a shared component library to improve consistency, reuse, and communication across our frontend team.</description>
      <content:encoded><![CDATA[<p>Many teams were turning to design systems to bring consistency and scalability to their interfaces. We decided to create our own simple system to unify the UI across our frontend projects.</p>
<h2 id="why-we-started-a-design-system">Why We Started a Design System</h2>
<p>We noticed:</p>
<ul>
<li>Repeated UI patterns across different features</li>
<li>Small visual inconsistencies between pages</li>
<li>Slower onboarding of new developers and designers</li>
</ul>
<p>A shared design system helped us:</p>
<ul>
<li>Reduce duplication</li>
<li>Keep design consistent</li>
<li>Document rules and patterns</li>
<li>Improve collaboration between devs and designers</li>
</ul>
<h2 id="first-steps">First Steps</h2>
<p>We started by identifying repeatable components:</p>
<ul>
<li>Buttons</li>
<li>Form inputs</li>
<li>Modals</li>
<li>Cards</li>
<li>Alerts</li>
</ul>
<p>Each one had:</p>
<ul>
<li>A consistent naming structure</li>
<li>Props for variations (size, type, icon, etc.)</li>
<li>Styles built using our color and spacing tokens</li>
</ul>
<h2 id="using-storybook">Using Storybook</h2>
<p>To document and test components in isolation, we used Storybook:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> sb</span><span style="color:#9ECBFF"> init</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> run</span><span style="color:#9ECBFF"> storybook</span></span></code></pre>
<p>Each component had a <code>*.stories.js</code> file:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> React </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;react&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { Button } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;./Button&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#E1E4E8"> { title: </span><span style="color:#9ECBFF">&#39;Button&#39;</span><span style="color:#E1E4E8"> };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> const</span><span style="color:#B392F0"> Primary</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#79B8FF">Button</span><span style="color:#B392F0"> type</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">&quot;primary&quot;</span><span style="color:#E1E4E8">&gt;Save&lt;/</span><span style="color:#79B8FF">Button</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> const</span><span style="color:#B392F0"> Secondary</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#79B8FF">Button</span><span style="color:#B392F0"> type</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">&quot;secondary&quot;</span><span style="color:#E1E4E8">&gt;Cancel&lt;/</span><span style="color:#79B8FF">Button</span><span style="color:#E1E4E8">&gt;;</span></span></code></pre>
<p>Storybook made it easier to:</p>
<ul>
<li>Showcase different states</li>
<li>Review components with designers</li>
<li>Test visual regressions</li>
</ul>
<h2 id="guidelines-and-tokens">Guidelines and Tokens</h2>
<p>We created a <code>tokens.js</code> file for spacing, colors, and typography:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> const</span><span style="color:#79B8FF"> spacing</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  xs: </span><span style="color:#9ECBFF">&#39;4px&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  sm: </span><span style="color:#9ECBFF">&#39;8px&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  md: </span><span style="color:#9ECBFF">&#39;16px&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  lg: </span><span style="color:#9ECBFF">&#39;24px&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> const</span><span style="color:#79B8FF"> colors</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  primary: </span><span style="color:#9ECBFF">&#39;#0070f3&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  secondary: </span><span style="color:#9ECBFF">&#39;#1c1c1e&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  background: </span><span style="color:#9ECBFF">&#39;#ffffff&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  text: </span><span style="color:#9ECBFF">&#39;#111111&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p>Tokens kept styles consistent and easy to update.</p>
<h2 id="results">Results</h2>
<p>After a few weeks of effort:</p>
<ul>
<li>We reused components across multiple apps</li>
<li>New devs had examples to follow</li>
<li>Designers gave feedback directly in Storybook</li>
<li>QA had clear expectations for UI behavior</li>
</ul>
<hr/>
<p>Building a small design system brought structure to our UI and sped up development. It didn’t need to be fancy—it just needed to be consistent and shared.</p>]]></content:encoded>
    </item>
    <item>
      <title>Moving from REST to GraphQL – A Case Study</title>
      <link>https://letanure.dev/writing/moving-from-rest-to-graphql/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/moving-from-rest-to-graphql/</guid>
      <pubDate>Mon, 20 Aug 2018 00:00:00 GMT</pubDate>
      <description>A practical look at replacing REST with GraphQL in a real frontend project using Apollo Client and query-based data fetching.</description>
      <content:encoded><![CDATA[<p>GraphQL’s flexibility in allowing clients to request exactly what they need has been a game changer. This post walks through the process of migrating from REST APIs to GraphQL in a real-world frontend project.</p>
<h2 id="why-we-considered-graphql">Why We Considered GraphQL</h2>
<p>REST was working, but we were facing some problems:</p>
<ul>
<li>Over-fetching or under-fetching data</li>
<li>Multiple roundtrips to load related entities</li>
<li>Rigid server endpoints and response formats</li>
</ul>
<p>GraphQL offered:</p>
<ul>
<li>A single endpoint</li>
<li>Control over the shape of the data returned</li>
<li>Strong tooling and type safety</li>
</ul>
<h2 id="setting-up-apollo-client">Setting Up Apollo Client</h2>
<p>We used Apollo Client for data management on the frontend. Basic setup looked like this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#9ECBFF"> @apollo/client</span><span style="color:#9ECBFF"> graphql</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { ApolloClient, InMemoryCache, ApolloProvider } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;@apollo/client&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> client</span><span style="color:#F97583"> =</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> ApolloClient</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">  uri: </span><span style="color:#9ECBFF">&#39;/graphql&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  cache: </span><span style="color:#F97583">new</span><span style="color:#B392F0"> InMemoryCache</span><span style="color:#E1E4E8">(),</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<p>Then we wrapped the app with the provider:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#79B8FF">ApolloProvider</span><span style="color:#B392F0"> client</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{client}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#79B8FF">App</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#79B8FF">ApolloProvider</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<h2 id="writing-queries">Writing Queries</h2>
<p>Instead of calling multiple endpoints, we used queries like this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="graphql"><code><span class="line"><span style="color:#F97583">query</span><span style="color:#B392F0"> GetUser</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  user</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">id</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;123&quot;</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#FFAB70">    name</span></span>
<span class="line"><span style="color:#FFAB70">    email</span></span>
<span class="line"><span style="color:#FFAB70">    posts</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">      title</span></span>
<span class="line"><span style="color:#FFAB70">      createdAt</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Apollo gave us <code>useQuery</code> to fetch this easily:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { useQuery, gql } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;@apollo/client&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> GET_USER</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> gql</span><span style="color:#9ECBFF">`</span></span>
<span class="line"><span style="color:#9ECBFF">  query GetUser {</span></span>
<span class="line"><span style="color:#9ECBFF">    user(id: &quot;123&quot;) {</span></span>
<span class="line"><span style="color:#9ECBFF">      name</span></span>
<span class="line"><span style="color:#9ECBFF">      email</span></span>
<span class="line"><span style="color:#9ECBFF">      posts {</span></span>
<span class="line"><span style="color:#9ECBFF">        title</span></span>
<span class="line"><span style="color:#9ECBFF">        createdAt</span></span>
<span class="line"><span style="color:#9ECBFF">      }</span></span>
<span class="line"><span style="color:#9ECBFF">    }</span></span>
<span class="line"><span style="color:#9ECBFF">  }</span></span>
<span class="line"><span style="color:#9ECBFF">`</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">loading</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">error</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">data</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#B392F0"> useQuery</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">GET_USER</span><span style="color:#E1E4E8">);</span></span></code></pre>
<h2 id="mutations">Mutations</h2>
<p>Updating data was just as clean:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="graphql"><code><span class="line"><span style="color:#F97583">mutation</span><span style="color:#B392F0"> AddPost</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">$title</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">String</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#FFAB70">  addPost</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">title</span><span style="color:#E1E4E8">: </span><span style="color:#FFAB70">$title</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#FFAB70">    id</span></span>
<span class="line"><span style="color:#FFAB70">    title</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h2 id="benefits-observed">Benefits Observed</h2>
<p>After switching:</p>
<ul>
<li>Fewer network requests overall</li>
<li>Easier frontend development</li>
<li>Better performance on low-bandwidth devices</li>
<li>Stronger type safety across the stack</li>
</ul>
<hr/>
<p>Migrating to GraphQL simplified data handling and improved developer experience. It wasn’t instant, but the gains were clear once we integrated it into real features.</p>]]></content:encoded>
    </item>
    <item>
      <title>WebAssembly 101 – High-Performance Web Apps</title>
      <link>https://letanure.dev/writing/webassembly-101/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/webassembly-101/</guid>
      <pubDate>Tue, 12 Jun 2018 00:00:00 GMT</pubDate>
      <description>A beginner-friendly overview of WebAssembly and how it enables fast, low-level code to run in the browser alongside JavaScript.</description>
      <content:encoded><![CDATA[<p>WebAssembly (Wasm) is a low-level bytecode format designed to run code at near-native speed in modern browsers. It allows developers to compile code from languages like C, C++, or Rust and execute it on the web alongside JavaScript.</p>
<p>WebAssembly reached its 1.0 release and was supported in all major browsers, marking a big step toward making the web a platform for high-performance apps.</p>
<h2 id="what-is-webassembly">What is WebAssembly?</h2>
<p>WebAssembly is:</p>
<ul>
<li>A binary format for the web</li>
<li>Designed for speed and efficiency</li>
<li>Executed in a safe, sandboxed environment</li>
<li>Meant to work alongside JavaScript</li>
</ul>
<p>It’s not meant to replace JavaScript, but to handle tasks where performance is critical—like image manipulation, games, simulations, or video editing.</p>
<h2 id="why-webassembly-matters">Why WebAssembly Matters</h2>
<ul>
<li>It allows reuse of existing C/C++/Rust codebases on the web.</li>
<li>It dramatically improves performance for CPU-intensive tasks.</li>
<li>It expands what’s possible in the browser.</li>
</ul>
<h2 id="basic-javascript-interop">Basic JavaScript Interop</h2>
<p>Once a <code>.wasm</code> file is compiled, you can load and run it with JavaScript:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> fs</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> require</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;fs&quot;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> wasmBuffer</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> fs.</span><span style="color:#B392F0">readFileSync</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&quot;./example.wasm&quot;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">WebAssembly.</span><span style="color:#B392F0">instantiate</span><span style="color:#E1E4E8">(wasmBuffer).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">wasmModule</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> result</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> wasmModule.instance.exports.</span><span style="color:#B392F0">add</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">10</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">15</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(result); </span><span style="color:#6A737D">// 25</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<h2 id="a-simple-example-in-c">A Simple Example in C</h2>
<p>This C code compiles to WebAssembly:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="c"><code><span class="line"><span style="color:#F97583">int</span><span style="color:#B392F0"> add</span><span style="color:#E1E4E8">(</span><span style="color:#F97583">int</span><span style="color:#FFAB70"> a</span><span style="color:#E1E4E8">, </span><span style="color:#F97583">int</span><span style="color:#FFAB70"> b</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> a </span><span style="color:#F97583">+</span><span style="color:#E1E4E8"> b;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>You can use a tool like Emscripten to compile it:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">emcc</span><span style="color:#9ECBFF"> add.c</span><span style="color:#79B8FF"> -s</span><span style="color:#9ECBFF"> WASM=</span><span style="color:#79B8FF">1</span><span style="color:#79B8FF"> -o</span><span style="color:#9ECBFF"> add.wasm</span></span></code></pre>
<p>Then call it from JavaScript as shown above.</p>
<h2 id="use-cases">Use Cases</h2>
<ul>
<li>Game engines and emulators</li>
<li>Real-time audio/video processing</li>
<li>Image processing</li>
<li>Scientific simulations</li>
<li>Running existing C/C++ libraries in the browser</li>
</ul>
<hr/>
<p>WebAssembly opened up a new world of performance for the web. It’s not just for C++ developers—it’s a tool that front-end devs can use to unlock new capabilities.</p>]]></content:encoded>
    </item>
    <item>
      <title>JAMstack in Action – Building a Static Site with Gatsby</title>
      <link>https://letanure.dev/writing/jamstack-in-action-gatsby/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/jamstack-in-action-gatsby/</guid>
      <pubDate>Tue, 10 Apr 2018 00:00:00 GMT</pubDate>
      <description>Learn how to build a fast, secure static site using Gatsby and the JAMstack approach.</description>
      <content:encoded><![CDATA[<p>In recent years, the JAMstack architecture has gained popularity for building fast and secure websites. JAMstack stands for JavaScript, APIs, and Markup. It emphasizes decoupling the frontend from the backend, pre-rendering pages for speed and security.</p>
<p>Gatsby is a React-based static site generator that aligns well with the JAMstack philosophy. It allows developers to build static websites using modern tools and practices.</p>
<h2 id="getting-started-with-gatsby">Getting Started with Gatsby</h2>
<p>To create a new Gatsby site, you’ll need Node.js installed. Then, you can use the Gatsby CLI to set up your project.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> -g</span><span style="color:#9ECBFF"> gatsby-cli</span></span>
<span class="line"><span style="color:#B392F0">gatsby</span><span style="color:#9ECBFF"> new</span><span style="color:#9ECBFF"> my-gatsby-site</span></span>
<span class="line"><span style="color:#79B8FF">cd</span><span style="color:#9ECBFF"> my-gatsby-site</span></span>
<span class="line"><span style="color:#B392F0">gatsby</span><span style="color:#9ECBFF"> develop</span></span></code></pre>
<p>This will start a development server at <code>http://localhost:8000</code>, where you can view your site.</p>
<h2 id="creating-pages">Creating Pages</h2>
<p>Gatsby uses React components for pages. Create a new file at <code>src/pages/about.js</code>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> React </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &quot;react&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> About</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;About us&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>This will create a page accessible at <code>http://localhost:8000/about</code>.</p>
<h2 id="adding-markdown-content">Adding Markdown Content</h2>
<p>You can source content from Markdown files using plugins. First, install the necessary plugins:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#9ECBFF"> gatsby-source-filesystem</span><span style="color:#9ECBFF"> gatsby-transformer-remark</span></span></code></pre>
<p>Then, configure them in <code>gatsby-config.js</code>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#79B8FF">module</span><span style="color:#E1E4E8">.</span><span style="color:#79B8FF">exports</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  plugins: [</span></span>
<span class="line"><span style="color:#E1E4E8">    {</span></span>
<span class="line"><span style="color:#E1E4E8">      resolve: </span><span style="color:#9ECBFF">`gatsby-source-filesystem`</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">      options: {</span></span>
<span class="line"><span style="color:#E1E4E8">        name: </span><span style="color:#9ECBFF">`pages`</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">        path: </span><span style="color:#9ECBFF">`${</span><span style="color:#E1E4E8">__dirname</span><span style="color:#9ECBFF">}/src/pages/`</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">      },</span></span>
<span class="line"><span style="color:#E1E4E8">    },</span></span>
<span class="line"><span style="color:#9ECBFF">    `gatsby-transformer-remark`</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  ],</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Now, you can create Markdown files in <code>src/pages/</code>, and Gatsby will transform them into pages.</p>
<h2 id="deploying-the-site">Deploying the Site</h2>
<p>Once your site is ready, you can build it:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">gatsby</span><span style="color:#9ECBFF"> build</span></span></code></pre>
<p>This will generate static files in the <code>public</code> directory, which you can deploy to any static hosting service.</p>
<hr/>
<p>By leveraging Gatsby and the JAMstack architecture, you can build fast, secure, and scalable websites with modern development practices.</p>]]></content:encoded>
    </item>
    <item>
      <title>TypeScript for JavaScript Developers – Getting Started</title>
      <link>https://letanure.dev/writing/typescript-for-js-devs/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/typescript-for-js-devs/</guid>
      <pubDate>Wed, 14 Feb 2018 00:00:00 GMT</pubDate>
      <description>Add static types to JavaScript for safer, maintainable code and better tooling.</description>
      <content:encoded><![CDATA[<p>TypeScript is a typed superset of JavaScript that compiles down to plain JS.<br/>
By 2018 it was no longer niche: major frameworks (Angular, Nest, Ionic) adopted it, and surveys showed rising usage.</p>
<hr/>
<h2 id="install-the-compiler">Install the compiler</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> --save-dev</span><span style="color:#9ECBFF"> typescript</span></span>
<span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> tsc</span><span style="color:#79B8FF"> --init</span></span></code></pre>
<p><code>tsconfig.json</code> controls compiler options.</p>
<hr/>
<h2 id="basic-types">Basic types</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">let</span><span style="color:#E1E4E8"> age</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> number</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 30</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">let</span><span style="color:#E1E4E8"> name</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> &#39;Luiz&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">let</span><span style="color:#E1E4E8"> isActive</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> boolean</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> true</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">let</span><span style="color:#E1E4E8"> tags</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">[] </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> [</span><span style="color:#9ECBFF">&#39;css&#39;</span><span style="color:#E1E4E8">, </span><span style="color:#9ECBFF">&#39;html&#39;</span><span style="color:#E1E4E8">];</span></span></code></pre>
<p>The compiler flags type mismatches before code runs.</p>
<hr/>
<h2 id="interfaces">Interfaces</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> number</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  name</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  email</span><span style="color:#F97583">?:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;      </span><span style="color:#6A737D">// optional</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> greet</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">u</span><span style="color:#F97583">:</span><span style="color:#B392F0"> User</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#9ECBFF"> `Hi ${</span><span style="color:#E1E4E8">u</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">name</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Interfaces describe shapes of objects for safer contracts.</p>
<hr/>
<h2 id="classes-with-access-modifiers">Classes with access modifiers</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">class</span><span style="color:#B392F0"> Counter</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  private</span><span style="color:#FFAB70"> count</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">  inc</span><span style="color:#E1E4E8">()</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> number</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#F97583"> ++</span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">.count;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p><code>private</code> and <code>public</code> make intent clear, unlike plain JS objects.</p>
<hr/>
<h2 id="enums">Enums</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#F97583">enum</span><span style="color:#B392F0"> Status</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">Open</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">Closed</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">Pending</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> ticket</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> { status: Status.Open };</span></span></code></pre>
<hr/>
<h2 id="compile-to-javascript">Compile to JavaScript</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> tsc</span></span></code></pre>
<p>The compiler emits <code>*.js</code> files matching the input structure.</p>
<hr/>
<h2 id="integrating-with-webpack">Integrating with Webpack</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> --save-dev</span><span style="color:#9ECBFF"> ts-loader</span></span></code></pre>
<p><strong>webpack.config.js</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#79B8FF">module</span><span style="color:#E1E4E8">.</span><span style="color:#79B8FF">exports</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  module: {</span></span>
<span class="line"><span style="color:#E1E4E8">    rules: [{ test:</span><span style="color:#9ECBFF"> /</span><span style="color:#85E89D;font-weight:bold">\.</span><span style="color:#DBEDFF">ts</span><span style="color:#F97583">$</span><span style="color:#9ECBFF">/</span><span style="color:#E1E4E8">, use: </span><span style="color:#9ECBFF">&#39;ts-loader&#39;</span><span style="color:#E1E4E8">, exclude:</span><span style="color:#9ECBFF"> /</span><span style="color:#DBEDFF">node_modules</span><span style="color:#9ECBFF">/</span><span style="color:#E1E4E8"> }]</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#E1E4E8">  resolve: { extensions: [</span><span style="color:#9ECBFF">&#39;.ts&#39;</span><span style="color:#E1E4E8">, </span><span style="color:#9ECBFF">&#39;.js&#39;</span><span style="color:#E1E4E8">] }</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<hr/>
<h2 id="benefits-in-large-codebases">Benefits in large codebases</h2>
<ul>
<li><strong>Early error detection</strong> reduces runtime bugs.</li>
<li><strong>IDE tooling</strong>: autocomplete, inline docs, safe refactor.</li>
<li><strong>Self‑documenting code</strong> thanks to explicit types.</li>
<li><strong>Gradual adoption</strong>: rename files to <code>.ts</code> one at a time, use <code>// @ts-check</code> in JS.</li>
</ul>
<p>TypeScript lets teams scale JavaScript projects confidently while still shipping standard JS to the browser.</p>]]></content:encoded>
    </item>
    <item>
      <title>GraphQL Basics – Querying APIs the Modern Way</title>
      <link>https://letanure.dev/writing/graphql-basics/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/graphql-basics/</guid>
      <pubDate>Wed, 15 Nov 2017 00:00:00 GMT</pubDate>
      <description>Learn how GraphQL lets clients ask for just the data they need and avoid over‑fetching common with REST.</description>
      <content:encoded><![CDATA[<p>GraphQL offers a single endpoint where clients send <strong>queries</strong> describing the exact fields they require.<br/>
The server returns a JSON object with that shape—no more, no less.</p>
<hr/>
<h2 id="restvsgraphql">REST vs GraphQL</h2>
<h3 id="typical-rest-flow">Typical REST flow</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="text"><code><span class="line"><span>GET /users/42          → user object</span></span>
<span class="line"><span>GET /users/42/repos    → list of repos</span></span>
<span class="line"><span>GET /users/42/followers → list of followers</span></span></code></pre>
<p>Multiple round‑trips fetch related data, often including fields the UI never shows.</p>
<h3 id="graphql-equivalent">GraphQL equivalent</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="graphql"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#FFAB70">  user</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">id</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">42</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#FFAB70">    name</span></span>
<span class="line"><span style="color:#FFAB70">    repos</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">limit</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">3</span><span style="color:#E1E4E8">) { </span><span style="color:#FFAB70">name</span><span style="color:#FFAB70"> stars</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#FFAB70">    followers</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">limit</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">5</span><span style="color:#E1E4E8">) { </span><span style="color:#FFAB70">name</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>One request gets everything, trimmed to what the UI needs.</p>
<hr/>
<h2 id="query-structure">Query structure</h2>
<ul>
<li><strong>Fields</strong>: properties you want returned.</li>
<li><strong>Arguments</strong>: refine results (<code>limit</code>, <code>order</code>).</li>
<li><strong>Fragments</strong>: reusable field sets.</li>
<li><strong>Variables</strong>: externalise arguments to avoid string interpolation.</li>
</ul>
<p>Example with variables:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="graphql"><code><span class="line"><span style="color:#F97583">query</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">$id</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">ID</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#FFAB70">  user</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">id</span><span style="color:#E1E4E8">: </span><span style="color:#FFAB70">$id</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#FFAB70">    name</span></span>
<span class="line"><span style="color:#FFAB70">    avatar</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Send <code>{ &quot;id&quot;: 42 }</code> in the request body under <code>variables</code>.</p>
<hr/>
<h2 id="try-it-yourself-github-api">Try it yourself (GitHub API)</h2>
<ol>
<li>Create a personal token with <code>read:user</code> scope.</li>
<li>POST to <code>https://api.github.com/graphql</code> with header <code>Authorization: bearer &lt;token&gt;</code>.</li>
<li>Send the query above to fetch your profile fields.</li>
</ol>
<hr/>
<h2 id="schema-language">Schema language</h2>
<p>A server publishes types:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="graphql"><code><span class="line"><span style="color:#F97583">type</span><span style="color:#79B8FF"> User</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  id</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">ID</span><span style="color:#F97583">!</span></span>
<span class="line"><span style="color:#FFAB70">  name</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">String</span><span style="color:#F97583">!</span></span>
<span class="line"><span style="color:#FFAB70">  repos</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">limit</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">Int</span><span style="color:#E1E4E8"> = </span><span style="color:#79B8FF">5</span><span style="color:#E1E4E8">): [</span><span style="color:#79B8FF">Repo</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">]</span><span style="color:#F97583">!</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">type</span><span style="color:#79B8FF"> Repo</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  id</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">ID</span><span style="color:#F97583">!</span></span>
<span class="line"><span style="color:#FFAB70">  name</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">String</span><span style="color:#F97583">!</span></span>
<span class="line"><span style="color:#FFAB70">  stars</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">Int</span><span style="color:#F97583">!</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">type</span><span style="color:#79B8FF"> Query</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  user</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">id</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">ID</span><span style="color:#F97583">!</span><span style="color:#E1E4E8">): </span><span style="color:#79B8FF">User</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>The client introspects this schema to know which fields exist and their types.</p>
<hr/>
<h2 id="benefits-for-frontend-devs">Benefits for front‑end devs</h2>
<ul>
<li><strong>Exact data</strong> – smaller payloads, faster rendering.</li>
<li><strong>Single round‑trip</strong> – fewer spinners.</li>
<li><strong>Strong typing</strong> – tools like autocomplete and compile‑time checks.</li>
<li><strong>Versionless</strong> – add fields without breaking clients.</li>
</ul>
<hr/>
<h2 id="building-a-simple-schema-node">Building a simple schema (Node)</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> init</span><span style="color:#79B8FF"> -y</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#9ECBFF"> graphql</span><span style="color:#9ECBFF"> express</span><span style="color:#9ECBFF"> express-graphql</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">graphqlHTTP</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#B392F0"> require</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;express-graphql&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">buildSchema</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#B392F0"> require</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;graphql&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> express</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> require</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;express&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> schema</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> buildSchema</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`</span></span>
<span class="line"><span style="color:#9ECBFF">  type Query {</span></span>
<span class="line"><span style="color:#9ECBFF">    hello: String</span></span>
<span class="line"><span style="color:#9ECBFF">  }</span></span>
<span class="line"><span style="color:#9ECBFF">`</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> root</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> { </span><span style="color:#B392F0">hello</span><span style="color:#E1E4E8">: () </span><span style="color:#F97583">=&gt;</span><span style="color:#9ECBFF"> &#39;Hello GraphQL&#39;</span><span style="color:#E1E4E8"> };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">express</span><span style="color:#E1E4E8">()</span></span>
<span class="line"><span style="color:#E1E4E8">  .</span><span style="color:#B392F0">use</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;/graphql&#39;</span><span style="color:#E1E4E8">, </span><span style="color:#B392F0">graphqlHTTP</span><span style="color:#E1E4E8">({ schema, rootValue: root, graphiql: </span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8"> }))</span></span>
<span class="line"><span style="color:#E1E4E8">  .</span><span style="color:#B392F0">listen</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">4000</span><span style="color:#E1E4E8">);</span></span></code></pre>
<p>Navigate to <code>http://localhost:4000/graphql</code> and run <code>{ hello }</code>.</p>
<hr/>
<p>GraphQL gained traction in 2017 as teams realised its power to streamline data fetching and reduce boilerplate compared with traditional REST endpoints.</p>]]></content:encoded>
    </item>
    <item>
      <title>Async/Await – Simplifying Asynchronous JavaScript</title>
      <link>https://letanure.dev/writing/async-await-simplified/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/async-await-simplified/</guid>
      <pubDate>Tue, 10 Oct 2017 00:00:00 GMT</pubDate>
      <description>Refactor promise chains into clean async functions with try/catch error handling.</description>
      <content:encoded><![CDATA[<p><code>async</code> and <code>await</code> landed in ES2017, letting developers write asynchronous code that reads like synchronous steps.</p>
<h2 id="before-promise-chain">Before: Promise chain</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> fetchUser</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">id</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`/api/users/${</span><span style="color:#E1E4E8">id</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">res</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">())</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">data</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">      console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;User:&#39;</span><span style="color:#E1E4E8">, data);</span></span>
<span class="line"><span style="color:#E1E4E8">    })</span></span>
<span class="line"><span style="color:#E1E4E8">    .</span><span style="color:#B392F0">catch</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">err</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> console.</span><span style="color:#B392F0">error</span><span style="color:#E1E4E8">(err));</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Nested <code>.then()</code> calls grow quickly and push error handling to the end.</p>
<h2 id="after-async--await">After: async / await</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">async</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> fetchUser</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">id</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  try</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> res</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`/api/users/${</span><span style="color:#E1E4E8">id</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> data</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> res.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#E1E4E8">    console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;User:&#39;</span><span style="color:#E1E4E8">, data);</span></span>
<span class="line"><span style="color:#E1E4E8">  } </span><span style="color:#F97583">catch</span><span style="color:#E1E4E8"> (err) {</span></span>
<span class="line"><span style="color:#E1E4E8">    console.</span><span style="color:#B392F0">error</span><span style="color:#E1E4E8">(err);</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h3 id="how-it-works">How it works</h3>
<ul>
<li><code>async</code> marks the function, returning a promise automatically.</li>
<li><code>await</code> pauses execution until the promise resolves, yielding the result.</li>
<li><code>try/catch</code> handles both network errors and thrown exceptions.</li>
</ul>
<h2 id="sequential-vs-parallel">Sequential vs parallel</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#6A737D">// sequential</span></span>
<span class="line"><span style="color:#F97583">await</span><span style="color:#B392F0"> stepOne</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#F97583">await</span><span style="color:#B392F0"> stepTwo</span><span style="color:#E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// parallel</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">a</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">b</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#F97583"> await</span><span style="color:#79B8FF"> Promise</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">all</span><span style="color:#E1E4E8">([</span><span style="color:#B392F0">stepOne</span><span style="color:#E1E4E8">(), </span><span style="color:#B392F0">stepTwo</span><span style="color:#E1E4E8">()]);</span></span></code></pre>
<p>Use <code>Promise.all</code> to start tasks together, then await their combined result.</p>
<h2 id="tips">Tips</h2>
<ul>
<li>Always wrap awaited code in <code>try/catch</code> for proper error handling.</li>
<li>Combine with <code>Promise.allSettled</code> for bulk operations where some may fail.</li>
<li>Keep <code>async</code> functions small; extract chunks to maintain readability.</li>
</ul>
<p>Async/await became mainstream in 2017, replacing many callback and promise chains with clear top‑to‑bottom control flow.</p>]]></content:encoded>
    </item>
    <item>
      <title>Embracing Mobile‑First Design</title>
      <link>https://letanure.dev/writing/embracing-mobile-first-design/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/embracing-mobile-first-design/</guid>
      <pubDate>Mon, 18 Sep 2017 00:00:00 GMT</pubDate>
      <description>Start layouts on small screens, then enhance upward for speed, usability, and Google’s mobile‑first index.</description>
      <content:encoded><![CDATA[<p>Google moved to <strong>mobile‑first indexing</strong> in 2017, using the mobile version of pages for ranking and crawling. This shift echoed traffic trends showing mobile visits overtaking desktop early that year.</p>
<p>Designing <strong>mobile‑first</strong> means writing base CSS for narrow screens first, then layering on styles for larger breakpoints. It results in smaller payloads and faster first paints on phones.</p>
<hr/>
<h2 id="stepbystep-example">Step‑by‑step example</h2>
<h3 id="base-mobile-styles">Base (mobile) styles</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#6A737D">/* styles.css */</span></span>
<span class="line"><span style="color:#85E89D">body</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  font-family</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">system-ui</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">sans-serif</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  margin</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.card</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  border-bottom</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#79B8FF"> #ddd</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h3 id="enhance-for-tablets">Enhance for tablets</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#F97583">@media</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">min-width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">600</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#B392F0">  .cards</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">    display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">    flex-wrap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">wrap</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">    gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#B392F0">  .card</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">    flex</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#79B8FF"> 1</span><span style="color:#79B8FF"> calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">50</span><span style="color:#F97583">%</span><span style="color:#F97583"> -</span><span style="color:#79B8FF"> 1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF">    border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#79B8FF"> #ddd</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h3 id="desktop-upgrade">Desktop upgrade</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#F97583">@media</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">min-width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">960</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#B392F0">  .card</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">    flex</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#79B8FF"> 1</span><span style="color:#79B8FF"> calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">33.333</span><span style="color:#F97583">%</span><span style="color:#F97583"> -</span><span style="color:#79B8FF"> 1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Media queries add complexity <em>after</em> the core experience works, keeping small‑screen CSS lean.</p>
<hr/>
<h2 id="practical-checklist">Practical checklist</h2>
<ul>
<li><strong>Content first</strong>: prioritise copy and actions most important on phones.</li>
<li><strong>Fluid images</strong>: set <code>img { max-width: 100%; height: auto; }</code>.</li>
<li><strong>Touch targets</strong>: minimum 48 × 48 px tap area.</li>
<li><strong>Font sizes</strong>: avoid fixed pixel fonts; use <code>rem</code> or viewport units.</li>
<li><strong>Test real devices</strong>: DevTools emulation catches layout, not touch ergonomics.</li>
<li><strong>Performance budgets</strong>: keep initial CSS under 14 KB uncompressed to fit the first TCP round‑trip.</li>
</ul>
<hr/>
<h2 id="seo-and-analytics-reminders">SEO and analytics reminders</h2>
<p>Google’s crawler evaluates mobile HTML for ranking, so parity between mobile and desktop markup is crucial. Check Search Console for the “Mobile‑first indexing enabled” flag. Use analytics segments to confirm that mobile now dominates sessions on most sites.</p>
<hr/>
<p>Mobile‑first design aligns code weight with user reality: phones lead traffic, and search engines judge mobile output first. Starting small and enhancing upward keeps experiences fast and inclusive.</p>]]></content:encoded>
    </item>
    <item>
      <title>Inside React 16 (Fiber) – What’s Changing?</title>
      <link>https://letanure.dev/writing/inside-react16-fiber/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/inside-react16-fiber/</guid>
      <pubDate>Thu, 20 Jul 2017 00:00:00 GMT</pubDate>
      <description>High‑level look at React’s new Fiber engine, error boundaries, and other practical improvements.</description>
      <content:encoded><![CDATA[<p>React 16 ships with <strong>Fiber</strong>, a total rewrite of the reconciliation engine aimed at smoother UIs and better error handling.</p>
<h2 id="what-is-fiber">What is Fiber?</h2>
<ul>
<li>Breaks rendering into small units of work called <em>fibers</em>.</li>
<li>Allows React to <strong>pause, resume, and prioritise</strong> rendering, preventing long blocks.</li>
<li>Enables future features like time‑slicing and concurrent rendering.</li>
</ul>
<h2 id="practical-wins-in-react16">Practical wins in React 16</h2>
<ol>
<li><strong>Error boundaries</strong> – components can catch render errors and show fallback UI.</li>
<li><strong>Return arrays from render</strong> – no extra wrapper elements needed.</li>
<li><strong>Portals</strong> – render children into a different DOM subtree.</li>
<li><strong>Smaller bundle</strong> – core size dropped compared with React 15.</li>
<li><strong>Better SSR</strong> – streaming server‑side rendering support.</li>
</ol>
<h2 id="minimal-error-boundary">Minimal error boundary</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#F97583">class</span><span style="color:#B392F0"> ErrorBoundary</span><span style="color:#F97583"> extends</span><span style="color:#B392F0"> React</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">Component</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  state</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> { hasError: </span><span style="color:#79B8FF">false</span><span style="color:#E1E4E8"> };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">  componentDidCatch</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">error</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">info</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#79B8FF">    this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">setState</span><span style="color:#E1E4E8">({ hasError: </span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#6A737D">    // log error or send to monitoring</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">  render</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">    if</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">.state.hasError) {</span></span>
<span class="line"><span style="color:#F97583">      return</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;Something went wrong.&lt;/</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;;</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.props.children;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Wrap parts of your app:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#79B8FF">ErrorBoundary</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#79B8FF">ProfilePage</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#79B8FF">ErrorBoundary</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<h2 id="returning-multiple-elements">Returning multiple elements</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> List</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> [</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">li</span><span style="color:#B392F0"> key</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">&quot;a&quot;</span><span style="color:#E1E4E8">&gt;A&lt;/</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;,</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">li</span><span style="color:#B392F0"> key</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">&quot;b&quot;</span><span style="color:#E1E4E8">&gt;B&lt;/</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  ];</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Later versions added the shorter <code>&lt;&gt;…&lt;/&gt;</code> fragment syntax.</p>
<h2 id="when-fiber-matters">When Fiber matters</h2>
<ul>
<li>Complex updates like animations or rich editors benefit from interruptible rendering.</li>
<li>Apps with heavy trees gain smoother scrolling and gestures.</li>
<li>Error boundaries keep the rest of the UI running after a crash.</li>
</ul>
<h2 id="upgrade-notes">Upgrade notes</h2>
<ul>
<li>Public API is mostly unchanged; update warnings from React 15 should be resolved first.</li>
<li>Old lifecycle hooks (<code>componentWillMount</code>, etc.) may show deprecation warnings.</li>
<li>Third‑party libraries generally work; check those touching internals.</li>
</ul>
<p>React 16’s Fiber engine lays the groundwork for future concurrent features while already improving stability and developer experience.</p>]]></content:encoded>
    </item>
    <item>
      <title>Layouts Reinvented – CSS Grid Tutorial</title>
      <link>https://letanure.dev/writing/css-grid-layouts-reinvented/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/css-grid-layouts-reinvented/</guid>
      <pubDate>Wed, 12 Apr 2017 00:00:00 GMT</pubDate>
      <description>Build responsive, two‑dimensional layouts with the new CSS Grid module.</description>
      <content:encoded><![CDATA[<p>CSS Grid reached stable status in 2017, unlocking direct control over rows and columns without float or flex hacks.</p>
<h2 id="core-ideas">Core ideas</h2>
<ul>
<li>A <strong>grid container</strong> establishes rows and columns.</li>
<li>Child elements become <strong>grid items</strong> you can place precisely.</li>
<li>Gaps create gutters without extra markup.</li>
<li>Media queries or the <code>repeat()</code> function adapt layouts easily.</li>
</ul>
<h2 id="basic-grid">Basic grid</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#B392F0">.gallery</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">grid</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  grid-template-columns</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">repeat</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">3</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">1</span><span style="color:#F97583">fr</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF">  grid-template-rows</span><span style="color:#E1E4E8">: masonry;</span></span>
<span class="line"><span style="color:#79B8FF">  gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">section</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;gallery&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">img</span><span style="color:#B392F0"> src</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;img1.jpg&quot;</span><span style="color:#B392F0"> alt</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;…&quot;</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">img</span><span style="color:#B392F0"> src</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;img2.jpg&quot;</span><span style="color:#B392F0"> alt</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;…&quot;</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">img</span><span style="color:#B392F0"> src</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;img3.jpg&quot;</span><span style="color:#B392F0"> alt</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;…&quot;</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#6A737D">  &lt;!-- more --&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">section</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<ul>
<li><code>repeat(3, 1fr)</code> creates three equal columns.</li>
<li><code>gap</code> adds uniform spacing.</li>
</ul>
<h2 id="named-areas">Named areas</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#B392F0">.article</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">grid</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  grid-template-areas</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#9ECBFF">    &quot;header header&quot;</span></span>
<span class="line"><span style="color:#9ECBFF">    &quot;sidebar main&quot;</span></span>
<span class="line"><span style="color:#9ECBFF">    &quot;footer footer&quot;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  grid-template-columns</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">250</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> 1</span><span style="color:#F97583">fr</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.header</span><span style="color:#E1E4E8">  { </span><span style="color:#79B8FF">grid-area</span><span style="color:#E1E4E8">: header; }</span></span>
<span class="line"><span style="color:#B392F0">.sidebar</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">grid-area</span><span style="color:#E1E4E8">: sidebar; }</span></span>
<span class="line"><span style="color:#B392F0">.main</span><span style="color:#E1E4E8">    { </span><span style="color:#79B8FF">grid-area</span><span style="color:#E1E4E8">: main; }</span></span>
<span class="line"><span style="color:#B392F0">.footer</span><span style="color:#E1E4E8">  { </span><span style="color:#79B8FF">grid-area</span><span style="color:#E1E4E8">: footer; }</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">article</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;article&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">header</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;header&quot;</span><span style="color:#E1E4E8">&gt;Header&lt;/</span><span style="color:#85E89D">header</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">aside</span><span style="color:#B392F0">  class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;sidebar&quot;</span><span style="color:#E1E4E8">&gt;Sidebar&lt;/</span><span style="color:#85E89D">aside</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">section</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;main&quot;</span><span style="color:#E1E4E8">&gt;Main content&lt;/</span><span style="color:#85E89D">section</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">footer</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;footer&quot;</span><span style="color:#E1E4E8">&gt;Footer&lt;/</span><span style="color:#85E89D">footer</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">article</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>The template string describes layout visually.</p>
<h2 id="autoplacing-cards">Auto‑placing cards</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#B392F0">.cards</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">grid</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  grid-template-columns</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">repeat</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">auto-fit</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">minmax</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">200</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">1</span><span style="color:#F97583">fr</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#79B8FF">  gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Cards wrap and stretch to fill available space, ideal for responsive dashboards.</p>
<h2 id="aligning-and-spacing">Aligning and spacing</h2>
<ul>
<li><code>justify-items</code> controls horizontal alignment inside cells.</li>
<li><code>align-items</code> handles vertical alignment.</li>
<li><code>justify-content</code> and <code>align-content</code> distribute the entire grid if track sizes do not fill the container.</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#B392F0">.centered</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">grid</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  place-items</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">center</span><span style="color:#E1E4E8">; </span><span style="color:#6A737D">/* shorthand for align-items + justify-items */</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h2 id="grid--flexbox">Grid + Flexbox</h2>
<p>Use Grid for overall page structure, then Flexbox inside items for one‑dimensional alignment, such as centering content within a card.</p>
<h2 id="browser-support-checklist">Browser support checklist</h2>
<ul>
<li>Works in modern Chrome, Firefox, Safari, and Edge released in 2017.</li>
<li>Use <code>@supports (display: grid)</code> to progressively enhance older browsers.</li>
<li>Fallbacks: fall back to flex layouts or single‑column flow when Grid unsupported.</li>
</ul>
<h2 id="next-steps">Next steps</h2>
<ol>
<li>Experiment with <code>grid-auto-flow: dense</code> for masonry effects.</li>
<li>Combine Grid with <code>minmax()</code> and <code>auto-fit</code> to create fluid layouts.</li>
<li>Use fragment identifiers like <code>grid-column: 1 / -1</code> to span full width when needed.</li>
</ol>
<p>CSS Grid frees layouts from the limitations of floats and complex media queries, giving you direct, powerful tools for two‑dimensional design.</p>]]></content:encoded>
    </item>
    <item>
      <title>Vue.js for Beginners – Building Your First Component</title>
      <link>https://letanure.dev/writing/vue-for-beginners-first-component/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/vue-for-beginners-first-component/</guid>
      <pubDate>Wed, 15 Mar 2017 00:00:00 GMT</pubDate>
      <description>Create a simple to‑do list in Vue 2 and learn its template syntax and reactivity model.</description>
      <content:encoded><![CDATA[<p>Vue gained major attention in 2017 for its balance of simplicity and power.<br/>
This guide walks through building a tiny to‑do list using <strong>Vue 2</strong>.</p>
<hr/>
<h2 id="why-vue-feels-approachable">Why Vue feels approachable</h2>
<ul>
<li>Script tag drops you straight into coding; no build needed.</li>
<li>HTML‑based templates with <code>{{ }}</code> interpolation feel natural.</li>
<li>Reactive data binding updates the DOM automatically.</li>
<li>Component API is small—just <code>data</code>, <code>methods</code>, and lifecycle hooks.</li>
<li>File size is light compared with other frameworks of the time.</li>
</ul>
<hr/>
<h2 id="set-up">Set up</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">script</span><span style="color:#B392F0"> src</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;https://cdn.jsdelivr.net/npm/vue@2.2.6/dist/vue.js&quot;</span><span style="color:#E1E4E8">&gt;&lt;/</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;app&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;My Todos&lt;/</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">form</span><span style="color:#B392F0"> v-on:submit.prevent</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;add&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> v-model</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;newTodo&quot;</span><span style="color:#B392F0"> placeholder</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;Add item&quot;</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;Add&lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;/</span><span style="color:#85E89D">form</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">li</span><span style="color:#B392F0"> v-for</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;(todo, i) in todos&quot;</span><span style="color:#B392F0"> :key</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;i&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      {{ todo.text }}</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> v-on:click</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;remove(i)&quot;</span><span style="color:#E1E4E8">&gt;×&lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;/</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#F97583">new</span><span style="color:#B392F0"> Vue</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">  el: </span><span style="color:#9ECBFF">&#39;#app&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  data: {</span></span>
<span class="line"><span style="color:#E1E4E8">    newTodo: </span><span style="color:#9ECBFF">&#39;&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    todos: []</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#E1E4E8">  methods: {</span></span>
<span class="line"><span style="color:#B392F0">    add</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">      if</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">.newTodo.</span><span style="color:#B392F0">trim</span><span style="color:#E1E4E8">()) {</span></span>
<span class="line"><span style="color:#79B8FF">        this</span><span style="color:#E1E4E8">.todos.</span><span style="color:#B392F0">push</span><span style="color:#E1E4E8">({ text: </span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">.newTodo.</span><span style="color:#B392F0">trim</span><span style="color:#E1E4E8">() });</span></span>
<span class="line"><span style="color:#79B8FF">        this</span><span style="color:#E1E4E8">.newTodo </span><span style="color:#F97583">=</span><span style="color:#9ECBFF"> &#39;&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">      }</span></span>
<span class="line"><span style="color:#E1E4E8">    },</span></span>
<span class="line"><span style="color:#B392F0">    remove</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">index</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#79B8FF">      this</span><span style="color:#E1E4E8">.todos.</span><span style="color:#B392F0">splice</span><span style="color:#E1E4E8">(index, </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">    }</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<h3 id="key-parts">Key parts</h3>
<ul>
<li><code>v-model</code> binds the input value to <code>newTodo</code>.</li>
<li><code>v-on:submit.prevent</code> intercepts the form submit.</li>
<li><code>v-for</code> renders list items reactively.</li>
<li>Direct DOM updates are not needed; Vue tracks changes.</li>
</ul>
<hr/>
<h2 id="extending-with-components">Extending with components</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">Vue.</span><span style="color:#B392F0">component</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;todo-item&#39;</span><span style="color:#E1E4E8">, {</span></span>
<span class="line"><span style="color:#E1E4E8">  props: [</span><span style="color:#9ECBFF">&#39;todo&#39;</span><span style="color:#E1E4E8">, </span><span style="color:#9ECBFF">&#39;index&#39;</span><span style="color:#E1E4E8">],</span></span>
<span class="line"><span style="color:#E1E4E8">  template: </span><span style="color:#9ECBFF">`</span></span>
<span class="line"><span style="color:#9ECBFF">    &lt;li&gt;</span></span>
<span class="line"><span style="color:#9ECBFF">      {{ todo.text }}</span></span>
<span class="line"><span style="color:#9ECBFF">      &lt;button @click=&quot;$emit(&#39;remove&#39;, index)&quot;&gt;×&lt;/button&gt;</span></span>
<span class="line"><span style="color:#9ECBFF">    &lt;/li&gt;</span></span>
<span class="line"><span style="color:#9ECBFF">  `</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>Replace the <code>&lt;li&gt;</code> in the previous template with:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">todo-item</span></span>
<span class="line"><span style="color:#B392F0">  v-for</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;(todo, i) in todos&quot;</span></span>
<span class="line"><span style="color:#B392F0">  :key</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;i&quot;</span></span>
<span class="line"><span style="color:#B392F0">  :todo</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;todo&quot;</span></span>
<span class="line"><span style="color:#B392F0">  :index</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;i&quot;</span></span>
<span class="line"><span style="color:#B392F0">  @remove</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;remove&quot;</span></span>
<span class="line"><span style="color:#E1E4E8">/&gt;</span></span></code></pre>
<p>Components help split the UI into reusable pieces while keeping state in the parent.</p>
<hr/>
<h2 id="reactivity-behind-the-scenes">Reactivity behind the scenes</h2>
<p>Vue converts each property in <code>data</code> to a getter and setter.<br/>
When you read <code>this.todos</code>, Vue records the dependency; when you push or splice, it triggers an update.</p>
<hr/>
<h2 id="next-steps">Next steps</h2>
<ol>
<li>Persist todos with <code>localStorage</code> in the <code>created</code> hook.</li>
<li>Move to Single‑File Components with <code>.vue</code> files and a build tool.</li>
<li>Explore Vuex for larger apps requiring shared state.</li>
</ol>
<p>Vue’s gentle learning curve and clear data flow make it a strong first framework for newcomers, while still scaling up with components, CLI tooling, and ecosystem add‑ons.</p>]]></content:encoded>
    </item>
    <item>
      <title>Progressive Web Apps – Installable &amp; Offline Web Experiences</title>
      <link>https://letanure.dev/writing/progressive-web-apps/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/progressive-web-apps/</guid>
      <pubDate>Thu, 12 Jan 2017 00:00:00 GMT</pubDate>
      <description>Make a site work offline, show an install prompt, and feel like a native app.</description>
      <content:encoded><![CDATA[<p>Progressive Web Apps (PWAs) combine the reach of the web with the smooth feel of native apps, offering offline support, install prompts, and push notifications.</p>
<h2 id="what-defines-a-pwa">What defines a PWA?</h2>
<ul>
<li>Site served over <strong>HTTPS</strong></li>
<li><strong>Web App Manifest</strong> for install metadata</li>
<li><strong>Service Worker</strong> controlling requests and caching assets</li>
<li>Optional <strong>Push Notifications</strong> for re‑engagement</li>
<li>Good performance scores in tools like Lighthouse</li>
</ul>
<hr/>
<h2 id="1-create-a-manifest">1 – Create a manifest</h2>
<p><strong>manifest.json</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;name&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Todo PWA&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;short_name&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;Todo&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;start_url&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;/index.html&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;display&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;standalone&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;background_color&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;#ffffff&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;theme_color&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;#1976d2&quot;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;icons&quot;</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#E1E4E8">    { </span><span style="color:#79B8FF">&quot;src&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;/icons/icon-192.png&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">&quot;sizes&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;192x192&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">&quot;type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;image/png&quot;</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#E1E4E8">    { </span><span style="color:#79B8FF">&quot;src&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;/icons/icon-512.png&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">&quot;sizes&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;512x512&quot;</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">&quot;type&quot;</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">&quot;image/png&quot;</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">  ]</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Add in your HTML head:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">link</span><span style="color:#B392F0"> rel</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;manifest&quot;</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;/manifest.json&quot;</span><span style="color:#E1E4E8"> /&gt;</span></span></code></pre>
<hr/>
<h2 id="2-register-a-service-worker">2 – Register a service worker</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">if</span><span style="color:#E1E4E8"> (</span><span style="color:#9ECBFF">&#39;serviceWorker&#39;</span><span style="color:#F97583"> in</span><span style="color:#E1E4E8"> navigator) {</span></span>
<span class="line"><span style="color:#E1E4E8">  window.</span><span style="color:#B392F0">addEventListener</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;load&#39;</span><span style="color:#E1E4E8">, () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">    navigator.serviceWorker.</span><span style="color:#B392F0">register</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;/sw.js&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  });</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<hr/>
<h2 id="3-cache-assets">3 – Cache assets</h2>
<p><strong>sw.js</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> CACHE</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> &#39;v1&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> ASSETS</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> [</span></span>
<span class="line"><span style="color:#9ECBFF">  &#39;/&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#9ECBFF">  &#39;/index.html&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#9ECBFF">  &#39;/styles.css&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#9ECBFF">  &#39;/app.js&#39;</span></span>
<span class="line"><span style="color:#E1E4E8">];</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">self.</span><span style="color:#B392F0">addEventListener</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;install&#39;</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">event</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  event.</span><span style="color:#B392F0">waitUntil</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#E1E4E8">    caches.</span><span style="color:#B392F0">open</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">CACHE</span><span style="color:#E1E4E8">).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">cache</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> cache.</span><span style="color:#B392F0">addAll</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">ASSETS</span><span style="color:#E1E4E8">))</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">self.</span><span style="color:#B392F0">addEventListener</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;fetch&#39;</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">event</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  event.</span><span style="color:#B392F0">respondWith</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#E1E4E8">    caches.</span><span style="color:#B392F0">match</span><span style="color:#E1E4E8">(event.request).</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">resp</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> resp </span><span style="color:#F97583">||</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(event.request))</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<hr/>
<h2 id="4-add-push-notifications-optional">4 – Add push notifications (optional)</h2>
<ol>
<li>Ask permission with <code>Notification.requestPermission()</code>.</li>
<li>Subscribe using <code>registration.pushManager.subscribe()</code>.</li>
<li>Send messages from your server with Web Push.</li>
</ol>
<hr/>
<h2 id="5-test-your-pwa">5 – Test your PWA</h2>
<ul>
<li>Run Lighthouse with the PWA preset.</li>
<li>Switch Chrome DevTools to <em>Offline</em> and reload; content should still display.</li>
<li>Visit twice, then look for an <em>Install</em> option in the browser’s menu.</li>
</ul>
<hr/>
<p>PWAs shine in areas with spotty connectivity and on sites that want repeat engagement without forcing app‑store installs.</p>]]></content:encoded>
    </item>
    <item>
      <title>Going Mobile with React Native (Basics)</title>
      <link>https://letanure.dev/writing/react-native-basics/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/react-native-basics/</guid>
      <pubDate>Sun, 20 Nov 2016 00:00:00 GMT</pubDate>
      <description>Use familiar React skills to build your first native mobile app.</description>
      <content:encoded><![CDATA[<p>React Native lets you write JavaScript and render <strong>real native</strong> UI components on iOS and Android.<br/>
By late 2016 the framework had stabilised (v0.39, November 2016) and many teams moved prototypes to production.</p>
<h2 id="why-react-native">Why React Native</h2>
<ul>
<li>Share business logic with web React projects.</li>
<li>Hot Reload speeds up iteration without recompiling Xcode or Android Studio.</li>
<li>Access native APIs (camera, GPS) through a growing library ecosystem.</li>
<li>Performance close to fully native, thanks to true platform widgets.</li>
</ul>
<h2 id="install-the-cli">Install the CLI</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Global CLI (historical 2.x line)</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> -g</span><span style="color:#9ECBFF"> react-native-cli@2</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Create a project</span></span>
<span class="line"><span style="color:#B392F0">react-native</span><span style="color:#9ECBFF"> init</span><span style="color:#9ECBFF"> HelloMobile</span></span>
<span class="line"><span style="color:#79B8FF">cd</span><span style="color:#9ECBFF"> HelloMobile</span></span></code></pre>
<p>Open the project in one terminal and run:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># iOS simulator (macOS only)</span></span>
<span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> react-native</span><span style="color:#9ECBFF"> run-ios</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Android emulator</span></span>
<span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> react-native</span><span style="color:#9ECBFF"> run-android</span></span></code></pre>
<h2 id="hello-world-component">Hello World component</h2>
<p>Edit <strong>App.js</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> React </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;react&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { View, Text, StyleSheet } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;react-native&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> App</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#79B8FF">View</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{styles.container}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#79B8FF">Text</span><span style="color:#B392F0"> style</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{styles.title}&gt;Hello React Native&lt;/</span><span style="color:#79B8FF">Text</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#79B8FF">View</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> styles</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> StyleSheet.</span><span style="color:#B392F0">create</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">  container: { flex: </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">, justifyContent: </span><span style="color:#9ECBFF">&#39;center&#39;</span><span style="color:#E1E4E8">, alignItems: </span><span style="color:#9ECBFF">&#39;center&#39;</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#E1E4E8">  title: { fontSize: </span><span style="color:#79B8FF">24</span><span style="color:#E1E4E8">, color: </span><span style="color:#9ECBFF">&#39;#333&#39;</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<p><code>View</code> and <code>Text</code> are native equivalents of <code>&lt;div&gt;</code> and text nodes.<br/>
<code>StyleSheet.create</code> uses a subset of CSS with camel‑cased properties.</p>
<h2 id="parallels-with-web-react">Parallels with web React</h2>
<ul>
<li>Components and props work the same.</li>
<li>State and hooks/API (<code>useState</code>, <code>useEffect</code>) behave identically.</li>
<li>Instead of HTML, you compose native primitives (<code>View</code>, <code>ScrollView</code>, <code>TextInput</code>).</li>
<li>Styling uses inline objects rather than external CSS files.</li>
<li>Navigation handled by libraries like <strong>react‑navigation</strong>, similar to React Router.</li>
</ul>
<h2 id="next-steps">Next steps</h2>
<ol>
<li>Add interaction with <code>Button</code> and <code>Alert</code>.</li>
<li>Fetch data using <code>fetch</code> (same API as browsers).</li>
<li>Try <strong>Expo</strong> for a zero‑build workflow and over‑the‑air updates.</li>
<li>Explore native modules to access sensors or platform features.</li>
</ol>
<p>React Native bridges the gap between web experience and native performance, opening mobile development to anyone who already knows React.</p>
]]></content:encoded>
    </item>
    <item>
      <title>From Gulp to Webpack – Evolving Build Tools</title>
      <link>https://letanure.dev/writing/from-gulp-to-webpack/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/from-gulp-to-webpack/</guid>
      <pubDate>Sat, 15 Oct 2016 00:00:00 GMT</pubDate>
      <description>Move from code‑driven task runners to config‑driven bundling with Webpack, plus a task‑by‑task cheat sheet.</description>
      <content:encoded><![CDATA[<p>Many projects that started with <strong>Grunt</strong> or <strong>Gulp</strong> switched to <strong>Webpack</strong> by late 2016 to get built‑in module bundling, dev server live reload, and smarter code splitting.</p>
<h2 id="two-mental-models">Two mental models</h2>
<h3 id="gulp--grunt">Gulp / Grunt</h3>
<ul>
<li>You write <strong>JavaScript tasks</strong> (<code>gulp.task(&#39;sass&#39;, …)</code>) that pipe files through a series of plugins.</li>
<li>Output goes to <code>dist/</code>, then you include built assets with <code>&lt;script&gt;</code> tags.</li>
<li>Responsibility for dependency graph and live reload belongs to plugins (<code>gulp‑watch</code>, <code>browser‑sync</code>).</li>
</ul>
<h3 id="webpack">Webpack</h3>
<ul>
<li>You describe <strong>what</strong> the final bundles should look like (<code>entry</code>, <code>output</code>) and let Webpack walk the dependency graph.</li>
<li>Transforms happen through <strong>loaders</strong> (e.g. <code>babel-loader</code>).</li>
<li><code>webpack-dev-server</code> serves bundles from memory and applies <strong>Hot Module Replacement</strong> automatically.</li>
</ul>
<p>Both tools use Node streams, but Gulp focuses on file pipelines, while Webpack focuses on module graphs. citeturn0search0turn0search4</p>
<hr/>
<h2 id="quick-migration-cheat-sheet">Quick migration cheat sheet</h2>



































<table><thead><tr><th>Need</th><th>Gulp/Grunt plugin</th><th>Webpack recipe</th></tr></thead><tbody><tr><td>ES6 → ES5</td><td><code>gulp-babel</code></td><td><code>babel-loader</code> + <code>.babelrc</code></td></tr><tr><td>Sass → CSS</td><td><code>gulp-sass</code></td><td><code>sass-loader</code> + <code>MiniCssExtractPlugin</code></td></tr><tr><td>Minify JS</td><td><code>gulp-uglify</code></td><td><code>TerserPlugin</code> (built‑in in prod mode)</td></tr><tr><td>Live reload</td><td><code>browser-sync</code> / <code>gulp-livereload</code></td><td><code>webpack-dev-server --hot</code></td></tr><tr><td>Cache‑bust file names</td><td><code>gulp-rev</code></td><td><code>[contenthash]</code> in <code>output.filename</code></td></tr></tbody></table>
<p><em>(WebPack cheat sheet adapted from Devhints)</em> citeturn0search6</p>
<hr/>
<h2 id="minimal-webpack-setup">Minimal Webpack setup</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> init</span><span style="color:#79B8FF"> -y</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Core</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> --save-dev</span><span style="color:#9ECBFF"> webpack@1</span><span style="color:#9ECBFF"> webpack-cli@1</span><span style="color:#9ECBFF"> webpack-dev-server@1</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Transpile ES6</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> --save-dev</span><span style="color:#9ECBFF"> babel-core</span><span style="color:#9ECBFF"> babel-loader</span><span style="color:#9ECBFF"> babel-preset-es2015</span></span></code></pre>
<p>Create <strong>webpack.config.js</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#79B8FF">module</span><span style="color:#E1E4E8">.</span><span style="color:#79B8FF">exports</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  entry: </span><span style="color:#9ECBFF">&#39;./src/index.js&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  output: { filename: </span><span style="color:#9ECBFF">&#39;bundle.[hash].js&#39;</span><span style="color:#E1E4E8">, path: __dirname </span><span style="color:#F97583">+</span><span style="color:#9ECBFF"> &#39;/dist&#39;</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#E1E4E8">  module: {</span></span>
<span class="line"><span style="color:#E1E4E8">    loaders: [{ test:</span><span style="color:#9ECBFF"> /</span><span style="color:#85E89D;font-weight:bold">\.</span><span style="color:#DBEDFF">js</span><span style="color:#F97583">$</span><span style="color:#9ECBFF">/</span><span style="color:#E1E4E8">, loader: </span><span style="color:#9ECBFF">&#39;babel&#39;</span><span style="color:#E1E4E8">, exclude:</span><span style="color:#9ECBFF"> /</span><span style="color:#DBEDFF">node_modules</span><span style="color:#9ECBFF">/</span><span style="color:#E1E4E8"> }]</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#E1E4E8">  devServer: { hot: </span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8">, inline: </span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p>Start in dev mode:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">webpack-dev-server</span><span style="color:#79B8FF"> --hot</span><span style="color:#79B8FF"> --open</span></span></code></pre>
<hr/>
<h2 id="common-tasks-rewritten">Common tasks rewritten</h2>
<h3 id="transpile--bundle-js">Transpile &amp; bundle JS</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Gulp</span></span>
<span class="line"><span style="color:#B392F0">gulp</span><span style="color:#9ECBFF"> babel</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Webpack – just run build, loader handles Babel</span></span>
<span class="line"><span style="color:#B392F0">webpack</span><span style="color:#79B8FF"> --mode</span><span style="color:#9ECBFF"> production</span></span></code></pre>
<h3 id="autoreload-on-file-save">Auto‑reload on file save</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Gulp + BrowserSync</span></span>
<span class="line"><span style="color:#B392F0">browser-sync</span><span style="color:#9ECBFF"> reload</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Webpack dev server</span></span>
<span class="line"><span style="color:#B392F0">webpack-dev-server</span><span style="color:#79B8FF"> --hot</span></span></code></pre>
<h3 id="minify-for-production">Minify for production</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Gulp</span></span>
<span class="line"><span style="color:#B392F0">gulp-uglify</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Webpack prod mode enables TerserPlugin automatically</span></span>
<span class="line"><span style="color:#B392F0">webpack</span><span style="color:#79B8FF"> --mode</span><span style="color:#9ECBFF"> production</span></span></code></pre>
<hr/>
<h2 id="tips-for-smoother-migration">Tips for smoother migration</h2>
<ol>
<li>Keep the old Gulp build for a sprint; serve the same HTML with Webpack bundle side‑by‑side.</li>
<li>Move <strong>JS first</strong>, then styles/images.</li>
<li>Replace plugin chains with equivalent loaders one at a time.</li>
<li>Use <strong>source maps</strong> (<code>devtool: &#39;source-map&#39;</code>) to debug transpiled code.</li>
<li>Leverage <strong>webpack‑merge</strong> to separate dev and prod configs.</li>
</ol>
<p>Webpack’s declarative approach cuts down boilerplate and enables advanced optimisations that are hard to replicate with ad‑hoc task runners.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Introduction to Vue.js 2.0</title>
      <link>https://letanure.dev/writing/introduction-to-vue2/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/introduction-to-vue2/</guid>
      <pubDate>Fri, 30 Sep 2016 00:00:00 GMT</pubDate>
      <description>First look at Vue 2 a lightweight, flexible alternative to heavier frameworks.</description>
      <content:encoded><![CDATA[<p>Vue.js 2.0 landed in <strong>September 2016</strong> — a major rewrite focused on speed, smaller size, and a more predictable API. The release post highlights the new virtual‑DOM core and improved rendering performance. <a href="https://medium.com/the-vue-point/vue-2-0-is-here-ef1f26acf4b8">Vue 2.0 release blog post</a></p>
<hr/>
<h2 id="why-vue-draws-attention">Why Vue draws attention</h2>
<ul>
<li><strong>Approachable</strong> – just drop a script tag and start coding; no build setup needed. <a href="https://v2.vuejs.org/v2/guide/installation">Vue 2 install guide</a></li>
<li><strong>Incremental adoption</strong> – sprinkle Vue on parts of an existing page or build a full SPA.</li>
<li><strong>Sensible defaults</strong> – templates use plain HTML with special attributes (<code>v-if</code>, <code>v-for</code>).</li>
<li><strong>Lightweight</strong> – around 20 KB min + gzip, smaller than React + Redux bundles of the day.</li>
<li><strong>Two‑way binding</strong> where it helps, combined with unidirectional parent → child data flow.</li>
</ul>
<hr/>
<h2 id="basic-component-example">Basic component example</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#6A737D">&lt;!-- Include Vue from CDN --&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">script</span><span style="color:#B392F0"> src</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;https://cdn.jsdelivr.net/npm/vue@2.0.3/dist/vue.js&quot;</span><span style="color:#E1E4E8">&gt;&lt;/</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;app&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">button-counter</span><span style="color:#E1E4E8">&gt;&lt;/</span><span style="color:#85E89D">button-counter</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">Vue.</span><span style="color:#B392F0">component</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;button-counter&#39;</span><span style="color:#E1E4E8">, {</span></span>
<span class="line"><span style="color:#B392F0">  data</span><span style="color:#E1E4E8">: </span><span style="color:#F97583">function</span><span style="color:#E1E4E8"> () {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> { count: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#E1E4E8">  template: </span><span style="color:#9ECBFF">&#39;&lt;button v-on:click=&quot;count++&quot;&gt;Clicked {{ count }} times&lt;/button&gt;&#39;</span></span>
<span class="line"><span style="color:#E1E4E8">})</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">new</span><span style="color:#B392F0"> Vue</span><span style="color:#E1E4E8">({ el: </span><span style="color:#9ECBFF">&#39;#app&#39;</span><span style="color:#E1E4E8"> })</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>Key points:</p>
<ul>
<li><code>Vue.component</code> registers a reusable component.</li>
<li><code>data</code> is <strong>a function</strong> that returns an object, ensuring each instance has its own state.</li>
<li>Template syntax is familiar HTML, not JSX.</li>
</ul>
<hr/>
<h2 id="reactivity-and-templating-vs-react">Reactivity and templating vs React</h2>



































<table><thead><tr><th>Aspect</th><th>Vue 2</th><th>React 15 (2016)</th></tr></thead><tbody><tr><td>Syntax</td><td>HTML‑based templates with directives (<code>v-bind</code>)</td><td>JSX (JavaScript + XML)</td></tr><tr><td>Data binding</td><td>Reactive getters/setters generated at init</td><td>State/props + <code>setState</code></td></tr><tr><td>Virtual DOM</td><td>Yes, rewritten for 2.0 (“blazing‑fast”)</td><td>Yes</td></tr><tr><td>State Mgmt</td><td>Built‑in reactivity; Vuex optional</td><td>External libraries (Redux, MobX)</td></tr><tr><td>Learning curve</td><td>Lower – starts in a <code>&lt;script&gt;</code> tag</td><td>Requires Babel / bundler for JSX</td></tr></tbody></table>
<p>Vue adopts a template‑first syntax, while React treats UI as functions of state in plain JavaScript. Both use a virtual DOM diff, but Vue’s reactivity system tracks dependencies automatically, avoiding manual <code>shouldComponentUpdate</code> optimisations.</p>
<hr/>
<h2 id="getting-started-with-the-cli">Getting started with the CLI</h2>
<p>For larger projects use <strong>Vue CLI</strong> (beta in late 2016):</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> -g</span><span style="color:#9ECBFF"> @vue/cli@2.9.6</span><span style="color:#6A737D">   # historical v2 line</span></span>
<span class="line"><span style="color:#B392F0">vue</span><span style="color:#9ECBFF"> init</span><span style="color:#9ECBFF"> webpack</span><span style="color:#9ECBFF"> my-app</span></span>
<span class="line"><span style="color:#79B8FF">cd</span><span style="color:#9ECBFF"> my-app</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> run</span><span style="color:#9ECBFF"> dev</span></span></code></pre>
<p>The CLI scaffolds a Webpack/Babel setup with hot reload and single‑file <code>.vue</code> components.</p>
<hr/>
<h2 id="when-to-pick-vue">When to pick Vue</h2>
<ul>
<li>Need progressive enhancement on a legacy server‑rendered app.</li>
<li>Want component‑based architecture without heavy build overhead.</li>
<li>Prefer readable templates over JSX.</li>
<li>Team values clear docs and a gentle learning curve.</li>
</ul>
<p>Vue 2’s release marked its jump from enthusiast circles to mainstream adoption, offering a middle ground between the simplicity of jQuery widgets and the power of full frameworks like Angular.</p>
]]></content:encoded>
    </item>
    <item>
      <title>State Management with Redux – Managing App State Made Easier</title>
      <link>https://letanure.dev/writing/state-management-with-redux/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/state-management-with-redux/</guid>
      <pubDate>Wed, 15 Jun 2016 00:00:00 GMT</pubDate>
      <description>Learn Redux core ideas and wire it into a small React app.</description>
      <content:encoded><![CDATA[<p>Redux became the most popular Flux‑inspired state library during 2016, thanks to Dan Abramov’s time‑travel demo at React Europe and rapid community adoption.</p>
<hr/>
<h2 id="core-concepts">Core concepts</h2>
<ul>
<li><strong>Store</strong> – holds one immutable state tree.</li>
<li><strong>Action</strong> – plain object that describes “what happened”.</li>
<li><strong>Reducer</strong> – pure function <code>(state, action) ⇒ newState</code>.</li>
<li><strong>Dispatch</strong> – send an action to update state.</li>
<li><strong>Provider</strong> – React binding that makes the store available.</li>
</ul>
<hr/>
<h2 id="install-and-set-up">Install and set up</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Add Redux and React bindings</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#9ECBFF"> redux</span><span style="color:#9ECBFF"> react-redux</span><span style="color:#79B8FF"> --save</span></span></code></pre>
<p>Create <strong>src/store.js</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { createStore } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;redux&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> rootReducer </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;./reducer&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> store</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> createStore</span><span style="color:#E1E4E8">(rootReducer);</span></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#E1E4E8"> store;</span></span></code></pre>
<hr/>
<h2 id="write-a-reducer">Write a reducer</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#6A737D">// src/reducer.js</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> initial</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> { count: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8"> };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> reducer</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">state</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> initial, </span><span style="color:#FFAB70">action</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  switch</span><span style="color:#E1E4E8"> (action.type) {</span></span>
<span class="line"><span style="color:#F97583">    case</span><span style="color:#9ECBFF"> &#39;counter/inc&#39;</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#F97583">      return</span><span style="color:#E1E4E8"> { </span><span style="color:#F97583">...</span><span style="color:#E1E4E8">state, count: state.count </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8"> };</span></span>
<span class="line"><span style="color:#F97583">    default</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#F97583">      return</span><span style="color:#E1E4E8"> state;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Reducers return new objects; they never mutate the old state.</p>
<hr/>
<h2 id="define-an-action-creator">Define an action creator</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> const</span><span style="color:#B392F0"> inc</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> () </span><span style="color:#F97583">=&gt;</span><span style="color:#E1E4E8"> ({ type: </span><span style="color:#9ECBFF">&#39;counter/inc&#39;</span><span style="color:#E1E4E8"> });</span></span></code></pre>
<p>Actions are serialisable, making time‑travel debugging possible.</p>
<hr/>
<h2 id="wire-redux-into-react">Wire Redux into React</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> React </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;react&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { Provider, useSelector, useDispatch } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;react-redux&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> store, { inc } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;./store&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> Counter</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> count</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> useSelector</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">s</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> s.count);</span></span>
<span class="line"><span style="color:#F97583">  const</span><span style="color:#79B8FF"> dispatch</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> useDispatch</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> onClick</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{() </span><span style="color:#F97583">=&gt;</span><span style="color:#B392F0"> dispatch</span><span style="color:#E1E4E8">(</span><span style="color:#B392F0">inc</span><span style="color:#E1E4E8">())}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      Clicked {count}</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> App</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#79B8FF">Provider</span><span style="color:#B392F0"> store</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{store}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#79B8FF">Counter</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;/</span><span style="color:#79B8FF">Provider</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p><code>useSelector</code> reads from the store, and <code>dispatch</code> sends actions. React components stay stateless; Redux owns the data flow.</p>
<hr/>
<h2 id="why-redux-gained-traction">Why Redux gained traction</h2>
<ul>
<li><strong>Predictability</strong> – single source of truth and pure reducers make bugs easier to trace.</li>
<li><strong>DevTools time travel</strong> – rewind and replay actions while editing code.</li>
<li><strong>Tiny API</strong> – just a handful of functions compared with heavier Flux variants.</li>
<li><strong>Strong React pairing</strong> – <code>react-redux</code> 5.0 landed late 2016, optimised for React 15+.</li>
<li><strong>Community learning</strong> – free Egghead course and countless tutorials helped newcomers.</li>
<li><strong>Survey love</strong> – State of JS 2016 showed Redux leading satisfaction charts.</li>
</ul>
<hr/>
<h2 id="keep-it-simple">Keep it simple</h2>
<p>Start with one reducer; split later with <code>combineReducers</code>.<br/>
Avoid over‑architecting small apps—Redux shines when state is shared across many components.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Dealing with JavaScript Fatigue</title>
      <link>https://letanure.dev/writing/dealing-with-javascript-fatigue/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/dealing-with-javascript-fatigue/</guid>
      <pubDate>Fri, 15 Apr 2016 00:00:00 GMT</pubDate>
      <description>Strategies to stay productive when new frameworks and tools appear every month.</description>
      <content:encoded><![CDATA[<p>By early 2016 developers were talking about <strong>“JavaScript fatigue”</strong>—the feeling of exhaustion caused by the rapid release cycle of frameworks, build tools, and best‑practice articles. The term spread after essays and discussions on Medium, Hacker News, and conference talks that asked whether anyone could keep up with the pace.</p>
<h2 id="why-fatigue-set-in">Why fatigue set in</h2>
<ul>
<li>Tooling stacks grew from jQuery + script tags to complex pipelines involving <strong>Babel, Webpack, ESLint, Karma, and more</strong>. </li>
<li>Framework churn: Angular → React → Vue → Redux → MobX, each marketed as a must‑know skill. </li>
<li>Social pressure: blog posts, meet‑ups, and job ads spotlighting the “next big thing.” </li>
</ul>
<h2 id="signs-you-might-feel-it">Signs you might feel it</h2>
<ul>
<li>Tutorials abandon last month’s setup for a new boilerplate. </li>
<li>Time spent configuring build scripts outweighs time spent writing features. </li>
<li>Fear of missing out when a new RFC hits Twitter. </li>
</ul>
<h2 id="five-steps-to-stay-sane">Five steps to stay sane</h2>
<ol>
<li>
<p><strong>Focus on fundamentals</strong><br/>
Vanilla JS, the DOM, CSS, HTTP, and accessibility outlive tooling waves. </p>
</li>
<li>
<p><strong>Set learning goals</strong><br/>
Pick one stack per project and finish the project before evaluating alternatives.</p>
</li>
<li>
<p><strong>Use stable presets</strong></p>
<ul>
<li><code>create-react-app</code> for React</li>
<li><code>@angular/cli</code> for Angular</li>
<li><code>vite</code> for Vue or vanilla apps<br/>
These hide most build config so you code, not babysit Webpack.</li>
</ul>
</li>
<li>
<p><strong>Batch your exploration</strong><br/>
Schedule a weekly hour to read release notes or watch talks, instead of chasing Twitter all day.</p>
</li>
<li>
<p><strong>Prune dependencies</strong><br/>
Review your <code>package.json</code> quarterly; remove libs that modern browsers now cover.</p>
</li>
</ol>
<h2 id="choosing-tools-that-fit">Choosing tools that fit</h2>
<p>Ask three questions before adopting anything new:</p>
<ul>
<li><strong>Does it solve a pain I have today?</strong></li>
<li><strong>Will it be maintained at least as long as I maintain my code?</strong></li>
<li><strong>Can my team learn it without stalling delivery?</strong></li>
</ul>
<p>If the answer is “maybe,” defer. Proven tech ages well, hype fades.</p>
<h2 id="looking-ahead">Looking ahead</h2>
<p>Framework velocity is unlikely to slow down. What changes is <strong>your filter</strong>:</p>
<ul>
<li>Track stable references like <strong>MDN</strong>, <strong>Can I use</strong>, and the official docs of your chosen framework.</li>
<li>Follow curated newsletters instead of raw feeds.</li>
<li>Keep pet projects small for experimentation; keep production stacks boring. </li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>TypeScript and Angular 2 – A New Era of Front‑End</title>
      <link>https://letanure.dev/writing/typescript-angular2-new-era/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/typescript-angular2-new-era/</guid>
      <pubDate>Wed, 10 Feb 2016 00:00:00 GMT</pubDate>
      <description>TypeScript becomes the language of choice for Angular 2, bringing static typing and better tooling to the framework.</description>
      <content:encoded><![CDATA[<p>Angular 2’s adoption of <strong>TypeScript</strong> as its primary language marks a significant shift in front-end development. The combination brings static typing, better tooling, and improved maintainability to large-scale applications.</p>
<hr/>
<h2 id="why-typescript-matters">Why TypeScript matters</h2>
<ul>
<li><strong>Static typing</strong> – catch errors at compile time rather than runtime</li>
<li><strong>Better IDE support</strong> – autocomplete, refactoring, and navigation</li>
<li><strong>Enhanced maintainability</strong> – self-documenting code and clearer interfaces</li>
<li><strong>Future-proof</strong> – TypeScript implements ECMAScript proposals early</li>
</ul>
<hr/>
<h2 id="key-typescript-features-in-angular-2">Key TypeScript features in Angular 2</h2>
<ul>
<li><strong>Decorators</strong> for component and module definitions</li>
<li><strong>Interfaces</strong> for type-safe dependency injection</li>
<li><strong>Generics</strong> for reusable components and services</li>
<li><strong>Type definitions</strong> for better third-party library integration</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#E1E4E8">@</span><span style="color:#B392F0">Component</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8">  selector: </span><span style="color:#9ECBFF">&#39;app-hero&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  template: </span><span style="color:#9ECBFF">`</span></span>
<span class="line"><span style="color:#9ECBFF">    &lt;h2&gt;{{hero.name}} details!&lt;/h2&gt;</span></span>
<span class="line"><span style="color:#9ECBFF">    &lt;div&gt;&lt;label&gt;id: &lt;/label&gt;{{hero.id}}&lt;/div&gt;</span></span>
<span class="line"><span style="color:#9ECBFF">    &lt;div&gt;</span></span>
<span class="line"><span style="color:#9ECBFF">      &lt;label&gt;name: &lt;/label&gt;</span></span>
<span class="line"><span style="color:#9ECBFF">      &lt;input [(ngModel)]=&quot;hero.name&quot; placeholder=&quot;name&quot;&gt;</span></span>
<span class="line"><span style="color:#9ECBFF">    &lt;/div&gt;</span></span>
<span class="line"><span style="color:#9ECBFF">  `</span></span>
<span class="line"><span style="color:#E1E4E8">})</span></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> class</span><span style="color:#B392F0"> HeroComponent</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  hero</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Hero</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">    id: </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    name: </span><span style="color:#9ECBFF">&#39;Windstorm&#39;</span></span>
<span class="line"><span style="color:#E1E4E8">  };</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<hr/>
<h2 id="migration-path">Migration path</h2>
<ol>
<li>Start with JavaScript files and add type annotations gradually</li>
<li>Use the TypeScript compiler’s <code>--allowJs</code> flag to mix JS and TS</li>
<li>Enable strict mode once the codebase is fully typed</li>
<li>Leverage Angular CLI for TypeScript configuration</li>
</ol>
<hr/>
<h2 id="best-practices">Best practices</h2>
<ul>
<li>Keep interfaces close to their implementations</li>
<li>Use type inference where possible</li>
<li>Leverage union types for flexible APIs</li>
<li>Document complex types with JSDoc comments</li>
</ul>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="typescript"><code><span class="line"><span style="color:#F97583">interface</span><span style="color:#B392F0"> Hero</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70">  id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> number</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  name</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70">  power</span><span style="color:#F97583">?:</span><span style="color:#79B8FF"> string</span><span style="color:#E1E4E8">;  </span><span style="color:#6A737D">// Optional property</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">type</span><span style="color:#B392F0"> HeroResponse</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> Hero</span><span style="color:#F97583"> |</span><span style="color:#B392F0"> Error</span><span style="color:#E1E4E8">;  </span><span style="color:#6A737D">// Union type</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">async</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> getHero</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">id</span><span style="color:#F97583">:</span><span style="color:#79B8FF"> number</span><span style="color:#E1E4E8">)</span><span style="color:#F97583">:</span><span style="color:#B392F0"> Promise</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">HeroResponse</span><span style="color:#E1E4E8">&gt; {</span></span>
<span class="line"><span style="color:#F97583">  try</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">    const</span><span style="color:#79B8FF"> response</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#B392F0"> fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`/api/heroes/${</span><span style="color:#E1E4E8">id</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> response.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#E1E4E8">  } </span><span style="color:#F97583">catch</span><span style="color:#E1E4E8"> (error) {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Error</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;Failed to fetch hero&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<hr/>
<h2 id="tooling-improvements">Tooling improvements</h2>
<ul>
<li><strong>VS Code</strong> integration with TypeScript</li>
<li><strong>Angular Language Service</strong> for template type checking</li>
<li><strong>Source maps</strong> for debugging</li>
<li><strong>Tree shaking</strong> for smaller bundles</li>
</ul>
<p>The combination of TypeScript and Angular 2 represents a maturing of front-end development, bringing enterprise-grade tooling and practices to web applications.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Goodbye IE, Hello Edge – What the End of Internet Explorer Means</title>
      <link>https://letanure.dev/writing/goodbye-ie-hello-edge/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/goodbye-ie-hello-edge/</guid>
      <pubDate>Tue, 10 Nov 2015 00:00:00 GMT</pubDate>
      <description>Microsoft moves from Internet Explorer to the new Edge browser, easing life for web developers.</description>
      <content:encoded><![CDATA[<p>Windows 10 ships with <strong>Microsoft Edge</strong> as its default browser, replacing Internet Explorer for everyday browsing.<br/>
Edge started the year under the codename <em>Project Spartan</em> and was confirmed as IE’s successor at Microsoft’s Build conference.</p>
<hr/>
<h2 id="why-this-matters">Why this matters</h2>
<ul>
<li><strong>Legacy headaches shrink</strong> – many hacks for Internet Explorer 10 and below can be retired.</li>
<li><strong>Standards progress</strong> – Edge implements modern APIs (ES6, Flexbox, SVG filters) without the quirks that haunted IE.</li>
<li><strong>Evergreen updates</strong> – Edge updates through Windows Update, closing the gap with Chrome and Firefox release cycles.</li>
<li><strong>Security</strong> – dropping IE’s outdated engine reduces attack surface.</li>
</ul>
<hr/>
<h2 id="what-to-keep-in-mind">What to keep in mind</h2>
<ul>
<li>Some enterprises still rely on old ActiveX or proprietary features.</li>
<li>IE 11 remains on Windows 10 for legacy needs and can be launched from Edge’s <em>“Open with Internet Explorer”</em> option.</li>
<li>Always test critical apps in IE 11 until usage stats fall below your project’s support threshold.</li>
</ul>
<hr/>
<h2 id="moving-forward">Moving forward</h2>
<ol>
<li>Audit CSS and JavaScript for IE‑specific work‑arounds.</li>
<li>Replace conditional comments with feature detection (e.g., <code>@supports</code> in CSS, <code>Modernizr</code> in JS).</li>
<li>Use <strong>ES6</strong> and modern layout (Flexbox, soon Grid) with a transpiler/polyfill fallback only where analytics show need.</li>
<li>Drop obsolete prefixes (e.g., <code>-ms-</code>) from new code.</li>
</ol>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#6A737D">/* Was: */</span></span>
<span class="line"><span style="color:#F97583">@media</span><span style="color:#79B8FF"> screen</span><span style="color:#F97583"> and</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">-ms-high-contrast</span><span style="color:#E1E4E8">: none) { … }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">/* Now: */</span></span>
<span class="line"><span style="color:#F97583">@supports</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#B392F0">  .nav</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">; }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Edge’s standards focus lets developers ship cleaner code sooner.</p>
<hr/>
<h2 id="timeline-highlights">Timeline highlights</h2>
<ul>
<li><strong>Jan 2015</strong> – <em>Spartan</em> shown running on Windows 10 phones.</li>
<li><strong>Apr 2015</strong> – Official name <strong>Microsoft Edge</strong> announced at Build.</li>
<li><strong>Jul 2015</strong> – Windows 10 launches with Edge set as default and IE 11 kept for compatibility.</li>
<li><strong>Nov 2015</strong> – Microsoft begins messaging that future features land in Edge, not IE.</li>
</ul>
<p>Edge marks a clean break from the legacy that held the web back for years. Developers can start targeting a modern, evergreen browser on Windows and leave many IE‑only fixes behind.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Babel 6 – First Look at the New Transpiler</title>
      <link>https://letanure.dev/writing/babel-6-first-look/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/babel-6-first-look/</guid>
      <pubDate>Mon, 02 Nov 2015 00:00:00 GMT</pubDate>
      <description>Babel 6 just landed. See what changed and how to upgrade.</description>
      <content:encoded><![CDATA[<p><strong>Babel 6</strong> was released on <strong>2015‑10‑29</strong>.</p>
<p>The team rewrote the tool into smaller, scoped packages and added presets.</p>
<h2 id="key-changes">Key changes</h2>
<ul>
<li>No single <code>babel</code> package. Use scoped packages instead</li>
<li>Everything is a plugin; nothing happens by default</li>
<li>Presets (like <code>@babel/preset-env</code>) group common plugins</li>
</ul>
<h2 id="fresh-setup">Fresh setup</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> --save-dev</span><span style="color:#9ECBFF"> @babel/core</span><span style="color:#9ECBFF"> @babel/cli</span><span style="color:#9ECBFF"> @babel/preset-env</span><span style="color:#9ECBFF"> @babel/preset-react</span></span>
<span class="line"><span style="color:#79B8FF">echo</span><span style="color:#9ECBFF"> &#39;{ &quot;presets&quot;: [&quot;@babel/preset-env&quot;, &quot;@babel/preset-react&quot;] }&#39;</span><span style="color:#F97583"> &gt;</span><span style="color:#9ECBFF"> .babelrc</span></span>
<span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> babel</span><span style="color:#9ECBFF"> src</span><span style="color:#79B8FF"> --out-dir</span><span style="color:#9ECBFF"> dist</span></span></code></pre>
<h2 id="upgrade-tip-from-babel5">Upgrade tip from Babel 5</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> uninstall</span><span style="color:#9ECBFF"> babel</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> --save-dev</span><span style="color:#9ECBFF"> @babel/core</span></span></code></pre>
<p>Swap the old <code>es2015</code> preset for <code>@babel/preset-env</code>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Flexible Layouts Made Easy with CSS Flexbox</title>
      <link>https://letanure.dev/writing/css-flexbox-layouts/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/css-flexbox-layouts/</guid>
      <pubDate>Sat, 10 Oct 2015 00:00:00 GMT</pubDate>
      <description>Build responsive navbars, columns, and centered blocks with the Flexbox module.</description>
      <content:encoded><![CDATA[<p>Flexbox gives you a one‑dimensional layout system that aligns, distributes, and reorders items with just a few lines of CSS.<br/>
By late 2015 most evergreen browsers shipped full Flexbox support, replacing many float or table hacks. </p>
<hr/>
<h2 id="core-ideas">Core ideas</h2>
<ul>
<li>A <strong>flex container</strong> establishes a new layout context using <code>display: flex</code> or <code>inline-flex</code>.</li>
<li>Items inside can grow, shrink, and wrap automatically along the <strong>main axis</strong>. </li>
<li>Alignment happens along two axes with <code>justify-content</code> and <code>align-items</code>. </li>
<li>The order of items is independent of source order via the <code>order</code> property. </li>
</ul>
<hr/>
<h2 id="common-patterns">Common patterns</h2>
<h3 id="1-perfect-centering">1. Perfect centering</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#B392F0">.centered</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  justify-content</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">center</span><span style="color:#E1E4E8">; </span><span style="color:#6A737D">/* horizontal */</span></span>
<span class="line"><span style="color:#79B8FF">  align-items</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">center</span><span style="color:#E1E4E8">;     </span><span style="color:#6A737D">/* vertical   */</span></span>
<span class="line"><span style="color:#79B8FF">  min-height</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">100</span><span style="color:#F97583">vh</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;centered&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;Centered with Flexbox&lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<h3 id="2-responsive-navbar">2. Responsive navbar</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#B392F0">.navbar</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  justify-content</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">space-between</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  align-items</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">center</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.5</span><span style="color:#F97583">rem</span><span style="color:#79B8FF"> 1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.navbar</span><span style="color:#85E89D"> ul</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  list-style</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">none</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  margin</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">@media</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">max-width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">600</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#B392F0">  .navbar</span><span style="color:#85E89D"> ul</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">    flex-direction</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">column</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">    align-items</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex-start</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">header</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;navbar&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">strong</span><span style="color:#E1E4E8">&gt;Logo&lt;/</span><span style="color:#85E89D">strong</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;&lt;</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;/&quot;</span><span style="color:#E1E4E8">&gt;Home&lt;/</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">&gt;&lt;/</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;&lt;</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;/&quot;</span><span style="color:#E1E4E8">&gt;Docs&lt;/</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">&gt;&lt;/</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;&lt;</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;/&quot;</span><span style="color:#E1E4E8">&gt;About&lt;/</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">&gt;&lt;/</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;/</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">header</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>The menu shifts from a row to a stacked column on narrow screens without extra markup. </p>
<h3 id="3-simple-equalheight-columns">3. Simple equal‑height columns</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#B392F0">.columns</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.columns</span><span style="color:#F97583"> &gt;</span><span style="color:#85E89D"> article</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  flex</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">;              </span><span style="color:#6A737D">/* same width */</span></span>
<span class="line"><span style="color:#79B8FF">  background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">#fafafa</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">section</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;columns&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">article</span><span style="color:#E1E4E8">&gt;Left&lt;/</span><span style="color:#85E89D">article</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">article</span><span style="color:#E1E4E8">&gt;Center&lt;/</span><span style="color:#85E89D">article</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">article</span><span style="color:#E1E4E8">&gt;Right&lt;/</span><span style="color:#85E89D">article</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">section</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>Each column stretches to the same height because flex items default to <code>align-stretch</code>. </p>
<h3 id="4-autowrapping-card-grid">4. Auto‑wrapping card grid</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#B392F0">.grid</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  flex-wrap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">wrap</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.card</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  flex</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#79B8FF"> 1</span><span style="color:#79B8FF"> 200</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">; </span><span style="color:#6A737D">/* grow, shrink, base width */</span></span>
<span class="line"><span style="color:#79B8FF">  background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">#fff</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#79B8FF"> #ddd</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;grid&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;card&quot;</span><span style="color:#E1E4E8">&gt;Card&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;card&quot;</span><span style="color:#E1E4E8">&gt;Card&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;card&quot;</span><span style="color:#E1E4E8">&gt;Card&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#6A737D">  &lt;!-- more cards --&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p><code>flex-wrap: wrap</code> lets items flow to a new line once they hit the minimum <code>200px</code> size, ideal for gallery or dashboard layouts. </p>
<hr/>
<h2 id="tips">Tips</h2>
<ul>
<li>Use <code>gap</code> to add consistent spacing between items; fallback with margins for very old browsers. </li>
<li>Keep <code>flex: 1</code> shorthand as <code>flex: grow shrink basis</code> (<code>auto</code> for basis by default).</li>
<li>Provide a graceful fallback (<code>display: block</code>) for IE9 and below. </li>
<li>For complex grids, combine Flexbox with media queries or move to CSS Grid once support is stable. </li>
</ul>
<hr/>
<p>Flexbox removes many layout headaches, bringing concise, predictable rules to everyday UI patterns.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Flexible Layouts Made Easy with CSS Flexbox</title>
      <link>https://letanure.dev/writing/flexible-layouts-with-flexbox/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/flexible-layouts-with-flexbox/</guid>
      <pubDate>Sat, 10 Oct 2015 00:00:00 GMT</pubDate>
      <description>Learn core Flexbox properties and build navbars, columns, and centered elements without floats.</description>
      <content:encoded><![CDATA[<p>Flexbox (the <strong>Flexible Box Layout Module</strong>) simplifies responsive design.<br/>
By late 2015 it was supported in all evergreen browsers, replacing many float and table hacks.</p>
<hr/>
<h2 id="core-ideas">Core ideas</h2>
<ul>
<li>Container and items: set <code>display: flex</code> on a parent, then its children become flex items.</li>
<li>Main axis vs cross axis: direction depends on <code>flex-direction</code>.</li>
<li>Space distribution and alignment happen with a small set of properties.</li>
</ul>
<hr/>
<h2 id="essential-container-properties">Essential container properties</h2>
<ul>
<li><code>display: flex</code> — activate Flexbox on the parent.</li>
<li><code>flex-direction</code> — row (default) or column layout.</li>
<li><code>flex-wrap</code> — allow items to wrap onto multiple lines.</li>
<li><code>justify-content</code> — align items on the <strong>main axis</strong> (<code>flex-start</code>, <code>center</code>, <code>space-between</code>, etc.).</li>
<li><code>align-items</code> — align items on the <strong>cross axis</strong> (perpendicular to main).</li>
<li><code>align-content</code> — multi‑line cross‑axis spacing (only when wrapping).</li>
</ul>
<hr/>
<h2 id="essential-item-properties">Essential item properties</h2>
<ul>
<li><code>flex</code> — shorthand for <code>flex-grow flex-shrink flex-basis</code>.</li>
<li><code>flex-basis</code> — preferred size before free space is distributed.</li>
<li><code>align-self</code> — override <code>align-items</code> for a single item.</li>
<li><code>order</code> — change visual order without changing markup.</li>
</ul>
<hr/>
<h2 id="pattern1-center-anything">Pattern 1 – Center anything</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#B392F0">.center</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  justify-content</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">center</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  align-items</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">center</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  min-height</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">100</span><span style="color:#F97583">vh</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;center&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;Perfectly centred&lt;/</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<hr/>
<h2 id="pattern2-responsive-navbar">Pattern 2 – Responsive navbar</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#B392F0">.nav</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  justify-content</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">space-between</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  align-items</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">center</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.nav</span><span style="color:#85E89D"> ul</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  list-style</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">none</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  margin</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">header</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;nav&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;Logo&lt;/</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;&lt;</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;/&quot;</span><span style="color:#E1E4E8">&gt;Home&lt;/</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">&gt;&lt;/</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;&lt;</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;/blog&quot;</span><span style="color:#E1E4E8">&gt;Blog&lt;/</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">&gt;&lt;/</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    &lt;</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;&lt;</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;/about&quot;</span><span style="color:#E1E4E8">&gt;About&lt;/</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">&gt;&lt;/</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;/</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">header</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>Items stay in a single row, and spacing adjusts automatically.</p>
<hr/>
<h2 id="pattern3-equalheight-columns">Pattern 3 – Equal‑height columns</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#B392F0">.columns</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.columns</span><span style="color:#F97583"> &gt;</span><span style="color:#85E89D"> article</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  flex</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">;        </span><span style="color:#6A737D">/* all articles share free space equally */</span></span>
<span class="line"><span style="color:#79B8FF">  padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">#f3f3f3</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">section</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;columns&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">article</span><span style="color:#E1E4E8">&gt;One&lt;/</span><span style="color:#85E89D">article</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">article</span><span style="color:#E1E4E8">&gt;Two&lt;/</span><span style="color:#85E89D">article</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">article</span><span style="color:#E1E4E8">&gt;Three&lt;/</span><span style="color:#85E89D">article</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">section</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>Each column grows to the same height without extra hacks.</p>
<hr/>
<h2 id="pattern4-simple-card-grid-with-wrap">Pattern 4 – Simple card grid with wrap</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="css"><code><span class="line"><span style="color:#B392F0">.cards</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  flex-wrap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">wrap</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.card</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF">  flex</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#79B8FF"> 1</span><span style="color:#79B8FF"> 200</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">; </span><span style="color:#6A737D">/* grow, shrink, basis */</span></span>
<span class="line"><span style="color:#79B8FF">  background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">#fff</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF">  border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#79B8FF"> #ccc</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;cards&quot;</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;card&quot;</span><span style="color:#E1E4E8">&gt;Card 1&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;card&quot;</span><span style="color:#E1E4E8">&gt;Card 2&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;card&quot;</span><span style="color:#E1E4E8">&gt;Card 3&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">  &lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;card&quot;</span><span style="color:#E1E4E8">&gt;Card 4&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>Cards wrap automatically as the viewport shrinks.</p>
<hr/>
<h2 id="browser-support">Browser support</h2>
<ul>
<li>Chrome, Firefox, Safari, Edge (Chromium) support the final syntax.</li>
<li>Older IE 10/11 versions use an outdated spec with vendor prefixes; check before dropping floats completely.</li>
</ul>
<hr/>
<h2 id="further-reading">Further reading</h2>
<ul>
<li>CSS Tricks <strong>“A Guide to Flexbox”</strong> – complete reference with visuals.</li>
<li>MDN <strong>flexbox</strong> docs – property‑by‑property explanations.</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Module Bundling 101 with Webpack</title>
      <link>https://letanure.dev/writing/module-bundling-101-webpack/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/module-bundling-101-webpack/</guid>
      <pubDate>Tue, 18 Aug 2015 00:00:00 GMT</pubDate>
      <description>Learn why bundling matters and set up Webpack 1 for a small ES6 app with hot‑reload.</description>
      <content:encoded><![CDATA[<p>Webpack is a <strong>module bundler</strong> that crawls your dependency graph, applies transforms, and emits one or more bundles ready for the browser. <a href="https://letanure.dev/">Docs</a></p>
<h2 id="why-bundle">Why bundle?</h2>
<ul>
<li>Resolve <code>import</code> / <code>require()</code> at build‑time so browsers get plain scripts.</li>
<li>Combine many files into fewer HTTP requests which speeds up first load.</li>
<li>Transform code with <strong>loaders</strong> (e.g. Babel turns ES6 → ES5, Sass → CSS, images → base64).</li>
<li>Optimise output with minification, dead‑code elimination, and code‑splitting.</li>
<li>Enable live editing with <strong>Hot Module Replacement (HMR)</strong> — update modules in‑place without a full refresh.</li>
</ul>
<h2 id="key-terms">Key terms</h2>

































<table><thead><tr><th>Term</th><th>Purpose</th></tr></thead><tbody><tr><td>Entry</td><td>Starting file for building the dependency graph</td></tr><tr><td>Output</td><td>Where Webpack writes the final bundle files</td></tr><tr><td>Loader</td><td>Function that transforms matched file types during the build</td></tr><tr><td>Plugin</td><td>Hook that extends Webpack (minification, env vars, etc.)</td></tr><tr><td>Dev Server</td><td>Memory‑only server that serves bundles and supports HMR</td></tr><tr><td>HMR</td><td>Runtime patching of changed modules without page reload</td></tr></tbody></table>
<h2 id="project-structure">Project structure</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="plaintext"><code><span class="line"><span>my-app/</span></span>
<span class="line"><span>├─ src/</span></span>
<span class="line"><span>│  ├─ index.js</span></span>
<span class="line"><span>│  └─ message.js</span></span>
<span class="line"><span>├─ dist/</span></span>
<span class="line"><span>└─ webpack.config.js</span></span></code></pre>
<h2 id="install-webpack-1-and-babel">Install Webpack 1 and Babel</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Initialise package.json</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> init</span><span style="color:#79B8FF"> -y</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Core bundler and dev server</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> --save-dev</span><span style="color:#9ECBFF"> webpack@1</span><span style="color:#9ECBFF"> webpack-dev-server@1</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Transpile ES6 to ES5</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> --save-dev</span><span style="color:#9ECBFF"> babel-core</span><span style="color:#9ECBFF"> babel-loader</span><span style="color:#9ECBFF"> babel-preset-es2015</span></span></code></pre>
<p>Create a <strong>.babelrc</strong>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;presets&quot;</span><span style="color:#E1E4E8">: [</span><span style="color:#9ECBFF">&quot;es2015&quot;</span><span style="color:#E1E4E8">]</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h2 id="webpackconfigjs">webpack.config.js</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> path</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> require</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;path&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF">module</span><span style="color:#E1E4E8">.</span><span style="color:#79B8FF">exports</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  entry: </span><span style="color:#9ECBFF">&#39;./src/index.js&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">  output: {</span></span>
<span class="line"><span style="color:#E1E4E8">    path: path.</span><span style="color:#B392F0">join</span><span style="color:#E1E4E8">(__dirname, </span><span style="color:#9ECBFF">&#39;dist&#39;</span><span style="color:#E1E4E8">),</span></span>
<span class="line"><span style="color:#E1E4E8">    filename: </span><span style="color:#9ECBFF">&#39;bundle.js&#39;</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">  module: {</span></span>
<span class="line"><span style="color:#E1E4E8">    loaders: [</span></span>
<span class="line"><span style="color:#E1E4E8">      {</span></span>
<span class="line"><span style="color:#E1E4E8">        test:</span><span style="color:#9ECBFF"> /</span><span style="color:#85E89D;font-weight:bold">\.</span><span style="color:#DBEDFF">js</span><span style="color:#F97583">$</span><span style="color:#9ECBFF">/</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">        loader: </span><span style="color:#9ECBFF">&#39;babel&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">        exclude:</span><span style="color:#9ECBFF"> /</span><span style="color:#DBEDFF">node_modules</span><span style="color:#9ECBFF">/</span></span>
<span class="line"><span style="color:#E1E4E8">      }</span></span>
<span class="line"><span style="color:#E1E4E8">    ]</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">  devServer: {</span></span>
<span class="line"><span style="color:#E1E4E8">    static: </span><span style="color:#9ECBFF">&#39;dist&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    inline: </span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">    hot: </span><span style="color:#79B8FF">true</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<h2 id="demo-code">Demo code</h2>
<p><strong>src/index.js</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> message </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;./message&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">document.body.innerHTML </span><span style="color:#F97583">=</span><span style="color:#9ECBFF"> `&lt;h1&gt;${</span><span style="color:#E1E4E8">message</span><span style="color:#9ECBFF">}&lt;/h1&gt;`</span><span style="color:#E1E4E8">;</span></span></code></pre>
<p><strong>src/message.js</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#9ECBFF"> &#39;Hello, Webpack!&#39;</span><span style="color:#E1E4E8">;</span></span></code></pre>
<h2 id="build-and-run">Build and run</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Production bundle</span></span>
<span class="line"><span style="color:#B392F0">webpack</span><span style="color:#79B8FF"> --mode</span><span style="color:#9ECBFF"> production</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Development server with hot‑reload</span></span>
<span class="line"><span style="color:#B392F0">webpack-dev-server</span><span style="color:#79B8FF"> --hot</span><span style="color:#79B8FF"> --open</span></span></code></pre>
<p>Open the local URL printed in the terminal, edit <code>src/message.js</code>, and watch HMR update the page instantly.</p>
<hr/>
]]></content:encoded>
    </item>
    <item>
      <title>Writing Future‑Proof Code with Babel</title>
      <link>https://letanure.dev/writing/future-proof-with-babel/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/future-proof-with-babel/</guid>
      <pubDate>Fri, 12 Jun 2015 00:00:00 GMT</pubDate>
      <description>Use Babel to compile ES6+ JavaScript into browser‑friendly ES5.</description>
      <content:encoded><![CDATA[<p>Babel is a JavaScript compiler.<br/>
It converts modern syntax into code that older browsers understand.<br/>
In 2015 this made it possible to use ES6 features in production while IE‑only engines were still common.</p>
<hr/>
<h2 id="why-babel-matters">Why Babel matters</h2>
<ul>
<li><strong>Early access</strong> – arrow functions, classes, modules, and more without waiting for native support</li>
<li><strong>Config file</strong> – <code>.babelrc</code> keeps presets and plugins in one place</li>
<li><strong>Plugin system</strong> – choose only the transforms you need</li>
<li><strong>Multiple outputs</strong> – turn ES modules into CommonJS, AMD, or System formats</li>
</ul>
<hr/>
<h2 id="project-setup">Project setup</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># Install CLI and the ES2015 preset locally</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> --save-dev</span><span style="color:#9ECBFF"> babel-cli</span><span style="color:#9ECBFF"> babel-core</span><span style="color:#9ECBFF"> babel-preset-es2015</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Optional: watcher for automatic rebuilds</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> --save-dev</span><span style="color:#9ECBFF"> babel-watch</span></span></code></pre>
<p>Create <strong>.babelrc</strong>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="json"><code><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF">  &quot;presets&quot;</span><span style="color:#E1E4E8">: [</span><span style="color:#9ECBFF">&quot;es2015&quot;</span><span style="color:#E1E4E8">]</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<hr/>
<h2 id="example-transpile-a-small-module">Example: Transpile a small module</h2>
<p><strong>src/math.js</strong></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> const</span><span style="color:#79B8FF"> PI</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 3.14</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> const</span><span style="color:#B392F0"> double</span><span style="color:#F97583"> =</span><span style="color:#FFAB70"> n</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> n </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 2</span><span style="color:#E1E4E8">;</span></span></code></pre>
<p>Build the file:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#6A737D"># One‑off build</span></span>
<span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> babel</span><span style="color:#9ECBFF"> src</span><span style="color:#79B8FF"> --out-dir</span><span style="color:#9ECBFF"> lib</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"># Continuous build during development</span></span>
<span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> babel-watch</span><span style="color:#9ECBFF"> src</span><span style="color:#79B8FF"> --out-dir</span><span style="color:#9ECBFF"> lib</span></span></code></pre>
<p><strong>lib/math.js</strong> (output)</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#9ECBFF">&#39;use strict&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">Object.</span><span style="color:#B392F0">defineProperty</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">exports</span><span style="color:#E1E4E8">, </span><span style="color:#9ECBFF">&quot;__esModule&quot;</span><span style="color:#E1E4E8">, {</span></span>
<span class="line"><span style="color:#E1E4E8">  value: </span><span style="color:#79B8FF">true</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span>
<span class="line"><span style="color:#F97583">var</span><span style="color:#79B8FF"> PI</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> exports</span><span style="color:#E1E4E8">.</span><span style="color:#79B8FF">PI</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 3.14</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">var</span><span style="color:#E1E4E8"> double </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> exports</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">double</span><span style="color:#F97583"> =</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> double</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">n</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> n </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 2</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p>The ES6 <code>export</code> statements become CommonJS assignments, ready for Node or older browsers after bundling.</p>
<hr/>
<h2 id="common-build-integrations">Common build integrations</h2>
<ul>
<li><strong>Browserify</strong> – add <code>babelify</code> as a transform</li>
<li><strong>Grunt / Gulp</strong> – run <code>grunt-babel</code> or <code>gulp-babel</code> in the task pipeline</li>
</ul>
<hr/>
<h2 id="key-es6-features-you-can-ship-today">Key ES6 features you can ship today</h2>
<ul>
<li><code>let</code> and <code>const</code> block‑scoped variables</li>
<li>Arrow functions with lexical <code>this</code></li>
<li>Classes with concise method syntax</li>
<li>Template literals with <code>${}</code> interpolation</li>
<li>Destructuring for arrays and objects</li>
</ul>
<p>Each transform is handled by the preset, so the workflow stays simple after the initial install.</p>
<hr/>
<p>Babel removes the waiting game.<br/>
Write modern JavaScript, compile once, and run everywhere.</p>]]></content:encoded>
    </item>
    <item>
      <title>Building UIs with React.js – A Beginner’s Tutorial</title>
      <link>https://letanure.dev/writing/beginner-react-ui/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/beginner-react-ui/</guid>
      <pubDate>Fri, 20 Mar 2015 00:00:00 GMT</pubDate>
      <description>Learn the core ideas of React 0.13 and build a small interactive UI.</description>
      <content:encoded><![CDATA[<p>React is a library for creating user interfaces with a <strong>component‑based</strong> approach and a <strong>virtual DOM</strong> diffing engine.</p>
<p>React 0.13 (released March 2015) added optional ES6 class support but <code>React.createClass</code> remains the common style.</p>
<hr/>
<h2 id="why-react-changes-frontend-work">Why React changes front‑end work</h2>
<ul>
<li><strong>Component isolation</strong> – each piece of UI is a self‑contained function of props and state.</li>
<li><strong>Virtual DOM</strong> – React builds an in‑memory tree and updates only the changed parts on the real DOM, avoiding full page reflows.</li>
<li><strong>One‑way data flow</strong> – parent → child props keep data reasoning straight.</li>
<li><strong>Declarative rendering</strong> – describe <em>what</em> the UI looks like; React figures out <em>how</em> to update it.</li>
</ul>
<p><em>(Check the React v0.13 release notes for details on class support and goals.)</em></p>
<hr/>
<h2 id="quick-setup">Quick setup</h2>
<p>Add React, ReactDOM, and JSX transformer via CDN:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="html"><code><span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">script</span><span style="color:#B392F0"> src</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/react.js&quot;</span><span style="color:#E1E4E8">&gt;&lt;/</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">script</span><span style="color:#B392F0"> src</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/react-dom.js&quot;</span><span style="color:#E1E4E8">&gt;&lt;/</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">script</span><span style="color:#B392F0"> src</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js&quot;</span><span style="color:#E1E4E8">&gt;&lt;/</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">&quot;app&quot;</span><span style="color:#E1E4E8">&gt;&lt;/</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">&gt;</span></span></code></pre>
<p>Write components in a <code>&lt;script type=&quot;text/babel&quot;&gt;</code> block.<br/>
The browser runs Babel in‑place to transform JSX into plain JavaScript.</p>
<hr/>
<h2 id="component-list">Component list</h2>
<ul>
<li><a href="#counter-component">Counter component</a></li>
<li><a href="#app-wrapper">App wrapper</a></li>
<li><a href="#rendering">Rendering</a></li>
</ul>
<hr/>
<h3 id="counter-component">Counter component</h3>
<p>Uses <code>React.createClass</code> and local state.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> Counter</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> React.</span><span style="color:#B392F0">createClass</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#B392F0">  getInitialState</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> { count: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8"> };</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#B392F0">  add</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#79B8FF">    this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">setState</span><span style="color:#E1E4E8">({ count: </span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">.state.count </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8">  },</span></span>
<span class="line"><span style="color:#B392F0">  render</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> onClick</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{</span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">.add}&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">        Clicked {</span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">.state.count} times</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;/</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    );</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<hr/>
<h3 id="app-wrapper">App wrapper</h3>
<p>Holds the Counter and shows a heading.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> App</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> React.</span><span style="color:#B392F0">createClass</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#B392F0">  render</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;</span><span style="color:#85E89D">section</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">        &lt;</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;Demo: React Counter&lt;/</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">        &lt;</span><span style="color:#79B8FF">Counter</span><span style="color:#E1E4E8"> /&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">      &lt;/</span><span style="color:#85E89D">section</span><span style="color:#E1E4E8">&gt;</span></span>
<span class="line"><span style="color:#E1E4E8">    );</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<hr/>
<h3 id="rendering">Rendering</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#E1E4E8">ReactDOM.</span><span style="color:#B392F0">render</span><span style="color:#E1E4E8">(&lt;</span><span style="color:#79B8FF">App</span><span style="color:#E1E4E8"> /&gt;, document.</span><span style="color:#B392F0">getElementById</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;app&#39;</span><span style="color:#E1E4E8">));</span></span></code></pre>
<p>React builds a virtual DOM tree from <code>App</code>, compares it with the previous tree on every <code>setState</code>, and patches only the node that displays the count.</p>
<hr/>
<h3 id="jsx-syntax">JSX syntax</h3>
<p>JSX lets you write HTML‑like tags in JavaScript. Babel turns this syntax into <code>React.createElement</code> calls.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="jsx"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> element</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> &lt;</span><span style="color:#85E89D">h1</span><span style="color:#B392F0"> className</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">&quot;title&quot;</span><span style="color:#E1E4E8">&gt;Hello React&lt;/</span><span style="color:#85E89D">h1</span><span style="color:#E1E4E8">&gt;;</span></span></code></pre>
<p>The code above compiles to:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> element</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> React.</span><span style="color:#B392F0">createElement</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#9ECBFF">  &#39;h1&#39;</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8">  { className: </span><span style="color:#9ECBFF">&#39;title&#39;</span><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#9ECBFF">  &#39;Hello React&#39;</span></span>
<span class="line"><span style="color:#E1E4E8">);</span></span></code></pre>
<hr/>
<h3 id="props-versus-state">Props versus state</h3>
<ul>
<li><strong>Props</strong>: read‑only data passed from parent to child.</li>
<li><strong>State</strong>: mutable data local to a component.</li>
</ul>
<p>State changes with <code>setState()</code> cause React to re‑render the component and its children. Props flow down; state stays inside.</p>
<h2 id="key-takeaways">Key takeaways</h2>
<ul>
<li>Components bundle markup, logic, and state.</li>
<li>State changes trigger efficient re‑renders through the virtual DOM diff.</li>
<li>Composition lets small pieces form complex UIs.</li>
</ul>
<p>This counter shows the minimum needed to start. Expand with more components, props, and events to grow a full application.</p>]]></content:encoded>
    </item>
    <item>
      <title>Exploring ECMAScript 2015 (ES6) Features</title>
      <link>https://letanure.dev/writing/exploring-es6-features/</link>
      <guid isPermaLink="true">https://letanure.dev/writing/exploring-es6-features/</guid>
      <pubDate>Thu, 15 Jan 2015 00:00:00 GMT</pubDate>
      <description>Deep dive into every ES6 feature with concise examples.</description>
      <content:encoded><![CDATA[<p>ECMAScript 2015 (ES6) adds modern syntax, safer defaults, and built‑in tools for async and modular code.</p>
<p>Transpile with <strong>Babel</strong>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> init</span><span style="color:#79B8FF"> -y</span></span>
<span class="line"><span style="color:#B392F0">npm</span><span style="color:#9ECBFF"> install</span><span style="color:#79B8FF"> --save-dev</span><span style="color:#9ECBFF"> @babel/core</span><span style="color:#9ECBFF"> @babel/cli</span><span style="color:#9ECBFF"> @babel/preset-env</span></span>
<span class="line"><span style="color:#79B8FF">echo</span><span style="color:#9ECBFF"> &#39;{ &quot;presets&quot;: [&quot;@babel/preset-env&quot;] }&#39;</span><span style="color:#F97583"> &gt;</span><span style="color:#9ECBFF"> .babelrc</span></span>
<span class="line"><span style="color:#B392F0">npx</span><span style="color:#9ECBFF"> babel</span><span style="color:#9ECBFF"> src</span><span style="color:#79B8FF"> --out-dir</span><span style="color:#9ECBFF"> dist</span></span></code></pre>
<p>Place ES6 files in <strong>src/</strong>, run the command, and load the output from <strong>dist/</strong> in older browsers.</p>
<hr/>
<h2 id="feature-list">Feature list</h2>
<ul>
<li><a href="#let-and-const">let and const</a></li>
<li><a href="#arrow-functions">Arrow functions</a></li>
<li><a href="#template-literals">Template literals</a></li>
<li><a href="#destructuring">Destructuring</a></li>
<li><a href="#default-rest-spread">Default, rest, spread</a></li>
<li><a href="#enhanced-object-literals">Enhanced object literals</a></li>
<li><a href="#classes">Classes</a></li>
<li><a href="#modules">Modules</a></li>
<li><a href="#promises">Promises</a></li>
<li><a href="#iterators-and-forof">Iterators and for..of</a></li>
<li><a href="#generators">Generators</a></li>
<li><a href="#map-set-weakmap-weakset">Map, Set, WeakMap, WeakSet</a></li>
<li><a href="#symbols">Symbols</a></li>
<li><a href="#unicode--binaryoctal">Unicode &amp; binary/octal</a></li>
<li><a href="#new-apis">New APIs</a></li>
<li><a href="#proxies">Proxies</a></li>
<li><a href="#reflect-api">Reflect API</a></li>
<li><a href="#tail-call-optimisation">Tail‑call optimisation</a></li>
</ul>
<hr/>
<h3 id="let-and-const">let and const</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">for</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">let</span><span style="color:#E1E4E8"> i </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">; i </span><span style="color:#F97583">&lt;</span><span style="color:#79B8FF"> 3</span><span style="color:#E1E4E8">; i</span><span style="color:#F97583">++</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#6A737D">  // i scoped to loop only</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> API_URL</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> &#39;/api&#39;</span><span style="color:#E1E4E8">;</span></span></code></pre>
<hr/>
<h3 id="arrow-functions">Arrow functions</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> doubled</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">2</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">3</span><span style="color:#E1E4E8">].</span><span style="color:#B392F0">map</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">n</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> n </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 2</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">button.</span><span style="color:#B392F0">addEventListener</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;click&#39;</span><span style="color:#E1E4E8">, () </span><span style="color:#F97583">=&gt;</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">save</span><span style="color:#E1E4E8">());</span></span></code></pre>
<hr/>
<h3 id="template-literals">Template literals</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> &#39;Luiz&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> msg</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> `Hi, ${</span><span style="color:#E1E4E8">user</span><span style="color:#9ECBFF">}</span></span>
<span class="line"><span style="color:#9ECBFF">Welcome to ES6.`</span><span style="color:#E1E4E8">;</span></span></code></pre>
<hr/>
<h3 id="destructuring">Destructuring</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">red</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">green</span><span style="color:#E1E4E8">] </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> [</span><span style="color:#9ECBFF">&#39;#f00&#39;</span><span style="color:#E1E4E8">, </span><span style="color:#9ECBFF">&#39;#0f0&#39;</span><span style="color:#E1E4E8">];</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> user</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> { id: </span><span style="color:#79B8FF">7</span><span style="color:#E1E4E8">, role: </span><span style="color:#9ECBFF">&#39;admin&#39;</span><span style="color:#E1E4E8"> };</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">id</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">role</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> user;</span></span></code></pre>
<hr/>
<h3 id="default-rest-spread">Default, rest, spread</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> greet</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">name</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> &#39;guest&#39;</span><span style="color:#E1E4E8">) { </span><span style="color:#F97583">return</span><span style="color:#9ECBFF"> `Hi ${</span><span style="color:#E1E4E8">name</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">; }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> nums</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">2</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">3</span><span style="color:#E1E4E8">];</span></span>
<span class="line"><span style="color:#B392F0">sum</span><span style="color:#E1E4E8">(</span><span style="color:#F97583">...</span><span style="color:#E1E4E8">nums); </span><span style="color:#6A737D">// spread into args</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> logAll</span><span style="color:#E1E4E8">(</span><span style="color:#F97583">...</span><span style="color:#FFAB70">args</span><span style="color:#E1E4E8">) { console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(args); }</span></span></code></pre>
<hr/>
<h3 id="enhanced-object-literals">Enhanced object literals</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> name</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> &#39;x&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> obj</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">  name,                </span><span style="color:#6A737D">// shorthand</span></span>
<span class="line"><span style="color:#E1E4E8">  [</span><span style="color:#9ECBFF">`prop_${</span><span style="color:#E1E4E8">name</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">]: </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">, </span><span style="color:#6A737D">// computed key</span></span>
<span class="line"><span style="color:#B392F0">  toString</span><span style="color:#E1E4E8">() { </span><span style="color:#F97583">return</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.name; }</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<hr/>
<h3 id="classes">Classes</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">class</span><span style="color:#B392F0"> Counter</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583">  constructor</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">start</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">) { </span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">.count </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> start; }</span></span>
<span class="line"><span style="color:#B392F0">  inc</span><span style="color:#E1E4E8">() { </span><span style="color:#F97583">return</span><span style="color:#F97583"> ++</span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">.count; }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<hr/>
<h3 id="modules">Modules</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#6A737D">// math.js</span></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> const</span><span style="color:#79B8FF"> PI</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 3.14</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">// app.js</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { PI } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> &#39;./math.js&#39;</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">PI</span><span style="color:#E1E4E8">);</span></span></code></pre>
<p><em>Run through Babel or a bundler to use modules in the browser.</em></p>
<hr/>
<h3 id="promises">Promises</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#B392F0">fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;/data.json&#39;</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8">  .</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">r</span><span style="color:#F97583"> =&gt;</span><span style="color:#E1E4E8"> r.</span><span style="color:#B392F0">json</span><span style="color:#E1E4E8">())</span></span>
<span class="line"><span style="color:#E1E4E8">  .</span><span style="color:#B392F0">then</span><span style="color:#E1E4E8">(show)</span></span>
<span class="line"><span style="color:#E1E4E8">  .</span><span style="color:#B392F0">catch</span><span style="color:#E1E4E8">(console.error);</span></span></code></pre>
<hr/>
<h3 id="iterators-and-forof">Iterators and for..of</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">for</span><span style="color:#E1E4E8"> (</span><span style="color:#F97583">const</span><span style="color:#79B8FF"> n</span><span style="color:#F97583"> of</span><span style="color:#E1E4E8"> [</span><span style="color:#79B8FF">10</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">20</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">30</span><span style="color:#E1E4E8">]) {</span></span>
<span class="line"><span style="color:#E1E4E8">  console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(n);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<hr/>
<h3 id="generators">Generators</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">function*</span><span style="color:#B392F0"> idMaker</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583">  let</span><span style="color:#E1E4E8"> id </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">  while</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">true</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">yield</span><span style="color:#E1E4E8"> id</span><span style="color:#F97583">++</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> gen</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> idMaker</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#E1E4E8">gen.</span><span style="color:#B392F0">next</span><span style="color:#E1E4E8">().value; </span><span style="color:#6A737D">// 0</span></span></code></pre>
<hr/>
<h3 id="map-set-weakmap-weakset">Map, Set, WeakMap, WeakSet</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> ids</span><span style="color:#F97583"> =</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Set</span><span style="color:#E1E4E8">([</span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">2</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">2</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">3</span><span style="color:#E1E4E8">]); </span><span style="color:#6A737D">// {1,2,3}</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> dict</span><span style="color:#F97583"> =</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Map</span><span style="color:#E1E4E8">([[</span><span style="color:#9ECBFF">&#39;key&#39;</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">42</span><span style="color:#E1E4E8">]]);</span></span></code></pre>
<hr/>
<h3 id="symbols">Symbols</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> secret</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> Symbol</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;secret&#39;</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> obj</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> { [secret]: </span><span style="color:#79B8FF">123</span><span style="color:#E1E4E8"> };</span></span></code></pre>
<hr/>
<h3 id="unicode--binaryoctal">Unicode &amp; binary/octal</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#9ECBFF">&#39;𝌆&#39;</span><span style="color:#E1E4E8">.</span><span style="color:#79B8FF">length</span><span style="color:#E1E4E8">; </span><span style="color:#6A737D">// 2 in ES5, fixed helpers in ES6</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF">0b1010</span><span style="color:#E1E4E8">; </span><span style="color:#6A737D">// 10</span></span>
<span class="line"><span style="color:#79B8FF">0o755</span><span style="color:#E1E4E8">;  </span><span style="color:#6A737D">// 493</span></span></code></pre>
<hr/>
<h3 id="new-apis">New APIs</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#E1E4E8">Number.</span><span style="color:#B392F0">isNaN</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">NaN</span><span style="color:#E1E4E8">);      </span><span style="color:#6A737D">// true</span></span>
<span class="line"><span style="color:#E1E4E8">[</span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">2</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">3</span><span style="color:#E1E4E8">].</span><span style="color:#B392F0">includes</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">2</span><span style="color:#E1E4E8">);  </span><span style="color:#6A737D">// true</span></span>
<span class="line"><span style="color:#E1E4E8">Math.</span><span style="color:#B392F0">trunc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">4.8</span><span style="color:#E1E4E8">);        </span><span style="color:#6A737D">// 4</span></span>
<span class="line"><span style="color:#E1E4E8">Object.</span><span style="color:#B392F0">assign</span><span style="color:#E1E4E8">({}, { a: </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8"> });</span></span></code></pre>
<hr/>
<h3 id="proxies">Proxies</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> monitor</span><span style="color:#F97583"> =</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Proxy</span><span style="color:#E1E4E8">({}, {</span></span>
<span class="line"><span style="color:#B392F0">  get</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">target</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">prop</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#E1E4E8">    console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">&#39;read&#39;</span><span style="color:#E1E4E8">, prop);</span></span>
<span class="line"><span style="color:#F97583">    return</span><span style="color:#E1E4E8"> target[prop];</span></span>
<span class="line"><span style="color:#E1E4E8">  }</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span>
<span class="line"><span style="color:#E1E4E8">monitor.x </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> 5</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">monitor.x; </span><span style="color:#6A737D">// logs &quot;read x&quot;</span></span></code></pre>
<hr/>
<h3 id="reflectapi">Reflect API</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> obj</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {};</span></span>
<span class="line"><span style="color:#E1E4E8">Reflect.</span><span style="color:#B392F0">set</span><span style="color:#E1E4E8">(obj, </span><span style="color:#9ECBFF">&#39;x&#39;</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">Reflect.</span><span style="color:#B392F0">get</span><span style="color:#E1E4E8">(obj, </span><span style="color:#9ECBFF">&#39;x&#39;</span><span style="color:#E1E4E8">); </span><span style="color:#6A737D">// 1</span></span></code></pre>
<hr/>
<h3 id="tailcall-optimisation">Tail‑call optimisation</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8;overflow-x:auto" tabindex="0" data-language="js"><code><span class="line"><span style="color:#F97583">function</span><span style="color:#B392F0"> factorial</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">n</span><span style="color:#E1E4E8">, </span><span style="color:#FFAB70">acc</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583">  return</span><span style="color:#E1E4E8"> n </span><span style="color:#F97583">===</span><span style="color:#79B8FF"> 0</span><span style="color:#F97583"> ?</span><span style="color:#E1E4E8"> acc </span><span style="color:#F97583">:</span><span style="color:#B392F0"> factorial</span><span style="color:#E1E4E8">(n </span><span style="color:#F97583">-</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">, n </span><span style="color:#F97583">*</span><span style="color:#E1E4E8"> acc);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Tail‑recursive functions can run without growing the call stack in compliant engines.</p>]]></content:encoded>
    </item>
  </channel>
</rss>
