<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Full-Stack on David Lang</title>
    <link>https://www.davidlang.tech/tags/full-stack/</link>
    <description>Recent content in Full-Stack on David Lang</description>
    <generator>Hugo</generator>
    <language>en</language>
    <lastBuildDate>Fri, 10 Apr 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://www.davidlang.tech/tags/full-stack/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Context Window Strategies: Making the Most of Long-Context LLMs</title>
      <link>https://www.davidlang.tech/posts/context-window-strategies-making-the-most-of-long-context-llms/</link>
      <pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/context-window-strategies-making-the-most-of-long-context-llms/</guid>
      <description>&lt;p&gt;Million-token context windows tempt teams to dump entire repos into prompts. That is expensive, slow, and often less accurate than targeted retrieval.&lt;/p&gt;&#xA;&lt;h2 id=&#34;when-full-context-helps&#34;&gt;When Full Context Helps&lt;/h2&gt;&#xA;&lt;p&gt;Single-file refactors, analyzing one large document, comparing a few long contracts.&lt;/p&gt;&#xA;&lt;h2 id=&#34;when-retrieval-wins&#34;&gt;When Retrieval Wins&lt;/h2&gt;&#xA;&lt;p&gt;Whole codebases, ticket backlogs, and wiki sites-embed, filter, rerank, then pass top-k chunks.&lt;/p&gt;&#xA;&lt;h2 id=&#34;compression-techniques&#34;&gt;Compression Techniques&lt;/h2&gt;&#xA;&lt;p&gt;Summarize conversation history. Use hierarchical memory (session summary + recent turns). Strip comments and generated noise from code context.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Building Reliable AI Agents: Lessons from Production</title>
      <link>https://www.davidlang.tech/posts/building-reliable-ai-agents-lessons-from-production/</link>
      <pubDate>Sat, 28 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/building-reliable-ai-agents-lessons-from-production/</guid>
      <description>&lt;p&gt;Production agents fail in boring ways: timeouts, tool errors, runaway loops, and silent wrong answers. Reliability engineering applies to agents too.&lt;/p&gt;&#xA;&lt;h2 id=&#34;hardening-checklist&#34;&gt;Hardening Checklist&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Max steps and token budgets per session&lt;/li&gt;&#xA;&lt;li&gt;Idempotent tools with clear error messages&lt;/li&gt;&#xA;&lt;li&gt;Checkpoint state for long workflows&lt;/li&gt;&#xA;&lt;li&gt;Circuit breakers when external APIs fail&lt;/li&gt;&#xA;&lt;li&gt;Structured logging of every tool call&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;graceful-degradation&#34;&gt;Graceful Degradation&lt;/h2&gt;&#xA;&lt;p&gt;When the agent fails, fall back to search-only RAG or human handoff-never an empty error.&lt;/p&gt;</description>
    </item>
    <item>
      <title>The State of AI Coding Assistants in 2026</title>
      <link>https://www.davidlang.tech/posts/the-state-of-ai-coding-assistants-in-2026/</link>
      <pubDate>Thu, 15 Jan 2026 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/the-state-of-ai-coding-assistants-in-2026/</guid>
      <description>&lt;p&gt;By 2026, AI coding assistants are standard in professional workflows-not experiments. The landscape consolidated around a few patterns: inline completion, IDE agents, and terminal agents.&lt;/p&gt;&#xA;&lt;h2 id=&#34;market-snapshot&#34;&gt;Market Snapshot&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;Cursor&lt;/strong&gt; leads among developers who want an AI-native editor with codebase-wide context. &lt;strong&gt;GitHub Copilot&lt;/strong&gt; remains the enterprise default tied to GitHub and Microsoft ecosystems. &lt;strong&gt;Claude Code&lt;/strong&gt; and similar terminal agents dominate backend and automation workflows. &lt;strong&gt;Windsurf, Cody, and others&lt;/strong&gt; compete on price and niche features.&lt;/p&gt;</description>
    </item>
    <item>
      <title>From RAG to Agentic AI: What&#39;s Next for LLM-Powered Apps</title>
      <link>https://www.davidlang.tech/posts/from-rag-to-agentic-ai-whats-next-for-llm-powered-apps/</link>
      <pubDate>Mon, 01 Dec 2025 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/from-rag-to-agentic-ai-whats-next-for-llm-powered-apps/</guid>
      <description>&lt;p&gt;The industry moved from chatbots → RAG → agents. Understanding the progression helps you invest in the right layer for your product maturity.&lt;/p&gt;&#xA;&lt;h2 id=&#34;rag-era&#34;&gt;RAG Era&lt;/h2&gt;&#xA;&lt;p&gt;Ground models in private data. Mature patterns: chunking, hybrid search, citations. Still the right default for Q&amp;amp;A and search.&lt;/p&gt;&#xA;&lt;h2 id=&#34;agent-era&#34;&gt;Agent Era&lt;/h2&gt;&#xA;&lt;p&gt;Models call tools, plan multi-step workflows, and maintain state. Higher capability, higher risk.&lt;/p&gt;&#xA;&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Evals-as-code&lt;/strong&gt; in every pipeline&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Smaller specialist models&lt;/strong&gt; routed by orchestrators&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;On-device&lt;/strong&gt; for privacy-sensitive steps&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Human-agent collaboration&lt;/strong&gt; UIs, not just chat&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;migration-path&#34;&gt;Migration Path&lt;/h2&gt;&#xA;&lt;p&gt;Master RAG and evals first. Add one well-scoped agent tool. Measure task completion before expanding autonomy.&lt;/p&gt;</description>
    </item>
    <item>
      <title>AI-First Development: Rethinking Your Engineering Workflow</title>
      <link>https://www.davidlang.tech/posts/ai-first-development-rethinking-your-engineering-workflow/</link>
      <pubDate>Tue, 22 Jul 2025 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/ai-first-development-rethinking-your-engineering-workflow/</guid>
      <description>&lt;p&gt;AI-first development means designing processes assuming LLMs and agents participate in design, implementation, and review-not bolting a chatbot onto waterfall.&lt;/p&gt;&#xA;&lt;h2 id=&#34;shifts-in-practice&#34;&gt;Shifts in Practice&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;Specs&lt;/strong&gt; - Write acceptance criteria LLMs can verify (tests, schemas).&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Architecture&lt;/strong&gt; - Smaller modules with clear boundaries agents can reason about.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Reviews&lt;/strong&gt; - AI first pass, human mandatory for security and product judgment.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Documentation&lt;/strong&gt; - Keep &lt;code&gt;AGENTS.md&lt;/code&gt; or rules files current so tools understand conventions.&lt;/p&gt;&#xA;&lt;h2 id=&#34;team-rituals&#34;&gt;Team Rituals&lt;/h2&gt;&#xA;&lt;p&gt;Start stories with a prompt draft. Pair with AI for spikes; human pair for production-critical paths. Track AI-assisted PR defect rates.&lt;/p&gt;</description>
    </item>
    <item>
      <title>MCP (Model Context Protocol): The Future of AI Tool Integration</title>
      <link>https://www.davidlang.tech/posts/mcp-model-context-protocol-the-future-of-ai-tool-integration/</link>
      <pubDate>Tue, 08 Apr 2025 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/mcp-model-context-protocol-the-future-of-ai-tool-integration/</guid>
      <description>&lt;p&gt;Model Context Protocol (MCP) standardizes how AI applications connect to data sources and tools-filesystems, databases, APIs, and IDEs speak a common protocol.&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-mcp-matters&#34;&gt;Why MCP Matters&lt;/h2&gt;&#xA;&lt;p&gt;Before MCP, every agent framework invented its own plugin format. MCP provides discoverable tools and resources with typed schemas-like LSP for AI tools.&lt;/p&gt;&#xA;&lt;h2 id=&#34;architecture&#34;&gt;Architecture&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Host&lt;/strong&gt; - Cursor, Claude Desktop, custom agent&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;MCP Server&lt;/strong&gt; - Exposes tools (&lt;code&gt;query_db&lt;/code&gt;, &lt;code&gt;read_file&lt;/code&gt;) and resources&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Transport&lt;/strong&gt; - stdio or SSE&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Developers implement servers once; any MCP-compatible host can use them.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Improving LLM Accuracy: Techniques Beyond Prompt Engineering</title>
      <link>https://www.davidlang.tech/posts/improving-llm-accuracy-techniques-beyond-prompt-engineering/</link>
      <pubDate>Tue, 25 Mar 2025 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/improving-llm-accuracy-techniques-beyond-prompt-engineering/</guid>
      <description>&lt;p&gt;When prompts plateau, these engineering levers move accuracy more than another adjective in the system message.&lt;/p&gt;&#xA;&lt;h2 id=&#34;better-retrieval&#34;&gt;Better Retrieval&lt;/h2&gt;&#xA;&lt;p&gt;Hybrid search (BM25 + vectors), rerankers (Cohere, cross-encoders), and metadata filters reduce wrong context reaching the model.&lt;/p&gt;&#xA;&lt;h2 id=&#34;structured-outputs&#34;&gt;Structured Outputs&lt;/h2&gt;&#xA;&lt;p&gt;Force JSON with schemas (Zod, Pydantic, OpenAI structured outputs). Parse failures trigger retry with repair prompts.&lt;/p&gt;&#xA;&lt;h2 id=&#34;model-routing&#34;&gt;Model Routing&lt;/h2&gt;&#xA;&lt;p&gt;Small models classify intent; large models answer hard questions. Cuts cost and reduces overconfident rambling on simple queries.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How to Validate and Measure LLM Accuracy in Production</title>
      <link>https://www.davidlang.tech/posts/how-to-validate-and-measure-llm-accuracy-in-production/</link>
      <pubDate>Tue, 18 Feb 2025 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/how-to-validate-and-measure-llm-accuracy-in-production/</guid>
      <description>&lt;p&gt;Shipping an LLM feature without measurement is shipping a bug generator. Production validation combines automated metrics, human review, and business KPIs.&lt;/p&gt;&#xA;&lt;h2 id=&#34;levels-of-evaluation&#34;&gt;Levels of Evaluation&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Unit-level&lt;/strong&gt; - Schema validation, regex checks, refusal detection&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Golden set&lt;/strong&gt; - Curated Q&amp;amp;A pairs scored automatically&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Online&lt;/strong&gt; - User thumbs, task completion, support escalations&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Human&lt;/strong&gt; - Expert rubrics on sampled traffic&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;metrics-that-matter&#34;&gt;Metrics That Matter&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Faithfulness&lt;/strong&gt; - Answer grounded in retrieved context (RAG)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Relevance&lt;/strong&gt; - Addresses the user question&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Toxicity / PII&lt;/strong&gt; - Safety filters&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Latency and cost&lt;/strong&gt; - p95 tokens and dollars per session&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;implementation-sketch&#34;&gt;Implementation Sketch&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;validate_response&lt;/span&gt;(answer: &lt;span style=&#34;color:#b58900&#34;&gt;str&lt;/span&gt;, context: &lt;span style=&#34;color:#b58900&#34;&gt;str&lt;/span&gt;) &lt;span style=&#34;color:#719e07&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#b58900&#34;&gt;dict&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#719e07&#34;&gt;return&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;has_citation&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;[source:&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;in&lt;/span&gt; answer,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;length_ok&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;50&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#b58900&#34;&gt;len&lt;/span&gt;(answer) &lt;span style=&#34;color:#719e07&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;4000&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;grounded&amp;#34;&lt;/span&gt;: entailment_score(context, answer) &lt;span style=&#34;color:#719e07&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;0.7&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Log scores to your observability stack (Datadog, LangSmith, Phoenix).&lt;/p&gt;</description>
    </item>
    <item>
      <title>Multi-Modal AI: Working with Images and Text</title>
      <link>https://www.davidlang.tech/posts/multi-modal-ai-working-with-images-and-text/</link>
      <pubDate>Tue, 05 Nov 2024 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/multi-modal-ai-working-with-images-and-text/</guid>
      <description>&lt;p&gt;Multi-modal models accept images and text in one request-enabling document OCR, UI screenshot analysis, and visual Q&amp;amp;A.&lt;/p&gt;&#xA;&lt;h2 id=&#34;vision-api-example&#34;&gt;Vision API Example&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; response &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;await&lt;/span&gt; openai.chat.completions.create({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  model&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;gpt-4o&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  messages&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      role&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;user&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      content&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        { &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;text&amp;#39;&lt;/span&gt;, text&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;What error is shown in this screenshot?&amp;#39;&lt;/span&gt; },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        { &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;image_url&amp;#39;&lt;/span&gt;, image_url&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; { url: &lt;span style=&#34;color:#dc322f&#34;&gt;imageDataUrl&lt;/span&gt; } },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;use-cases&#34;&gt;Use Cases&lt;/h2&gt;&#xA;&lt;p&gt;Receipt parsing, diagram explanation, accessibility alt-text generation, and visual regression triage.&lt;/p&gt;</description>
    </item>
    <item>
      <title>AI-Powered Code Review: Integrating LLMs into Dev Workflows</title>
      <link>https://www.davidlang.tech/posts/ai-powered-code-review-integrating-llms-into-dev-workflows/</link>
      <pubDate>Sun, 22 Sep 2024 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/ai-powered-code-review-integrating-llms-into-dev-workflows/</guid>
      <description>&lt;p&gt;LLMs can summarize diffs, flag security smells, and suggest tests-but they should augment human review, not replace it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;ci-integration&#34;&gt;CI Integration&lt;/h2&gt;&#xA;&lt;p&gt;Post PR diffs to an LLM with a structured prompt. Output JSON findings consumed by GitHub Actions or GitLab CI. Fail builds only on high-severity, high-confidence issues to reduce noise.&lt;/p&gt;&#xA;&lt;h2 id=&#34;prompt-design-for-reviews&#34;&gt;Prompt Design for Reviews&lt;/h2&gt;&#xA;&lt;p&gt;Include: changed files, diff hunks, coding standards doc, and explicit instruction to cite line numbers and avoid nits.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Building AI Agents with LangChain and OpenAI</title>
      <link>https://www.davidlang.tech/posts/building-ai-agents-with-langchain-and-openai/</link>
      <pubDate>Sun, 28 Jul 2024 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/building-ai-agents-with-langchain-and-openai/</guid>
      <description>&lt;p&gt;AI agents loop: observe, plan, act with tools, observe again. They handle multi-step tasks like research, booking, or code changes.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tool-definition&#34;&gt;Tool Definition&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;from&lt;/span&gt; langchain.tools &lt;span style=&#34;color:#719e07&#34;&gt;import&lt;/span&gt; tool&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;@tool&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;search_docs&lt;/span&gt;(query: &lt;span style=&#34;color:#b58900&#34;&gt;str&lt;/span&gt;) &lt;span style=&#34;color:#719e07&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#b58900&#34;&gt;str&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;&amp;#39;&amp;#39;Search internal documentation.&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#719e07&#34;&gt;return&lt;/span&gt; vector_store&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;similarity_search(query, k&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;5&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Bind tools to the model; the model returns tool calls you execute and feed back as observations.&lt;/p&gt;&#xA;&lt;h2 id=&#34;control-and-safety&#34;&gt;Control and Safety&lt;/h2&gt;&#xA;&lt;p&gt;Set max iterations. Require human approval for destructive tools. Log every step for audit.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;Agents are powerful and unpredictable. Start with a fixed workflow (chain); graduate to agents when the task path genuinely varies per request.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Next.js App Router: Complete Migration Guide</title>
      <link>https://www.davidlang.tech/posts/nextjs-app-router-complete-migration-guide/</link>
      <pubDate>Mon, 10 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/nextjs-app-router-complete-migration-guide/</guid>
      <description>&lt;p&gt;Migrating from Pages Router to App Router unlocks RSC, layouts, and improved data fetching-but requires deliberate planning.&lt;/p&gt;&#xA;&lt;h2 id=&#34;folder-structure&#34;&gt;Folder Structure&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  layout.tsx      # Root layout&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  page.tsx        # /&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  blog/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [slug]/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      page.tsx    # /blog/:slug&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  api/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    hello/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      route.ts    # Route Handlers&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;data-fetching&#34;&gt;Data Fetching&lt;/h2&gt;&#xA;&lt;p&gt;Replace &lt;code&gt;getServerSideProps&lt;/code&gt; with async Server Components. Replace &lt;code&gt;getStaticProps&lt;/code&gt; with &lt;code&gt;fetch&lt;/code&gt; and &lt;code&gt;revalidate&lt;/code&gt; options. Client data still uses SWR or React Query in Client Components.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Vector Databases: Pinecone, Weaviate, and Chroma Compared</title>
      <link>https://www.davidlang.tech/posts/vector-databases-pinecone-weaviate-and-chroma-compared/</link>
      <pubDate>Mon, 22 Apr 2024 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/vector-databases-pinecone-weaviate-and-chroma-compared/</guid>
      <description>&lt;p&gt;Vector databases store embeddings and perform similarity search-the retrieval layer in RAG and recommendation systems.&lt;/p&gt;&#xA;&lt;h2 id=&#34;comparison&#34;&gt;Comparison&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;Pinecone&lt;/th&gt;&#xA;          &lt;th&gt;Weaviate&lt;/th&gt;&#xA;          &lt;th&gt;Chroma&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Hosting&lt;/td&gt;&#xA;          &lt;td&gt;Managed cloud&lt;/td&gt;&#xA;          &lt;td&gt;Self-host or cloud&lt;/td&gt;&#xA;          &lt;td&gt;Embedded / local&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Best for&lt;/td&gt;&#xA;          &lt;td&gt;Production scale&lt;/td&gt;&#xA;          &lt;td&gt;Hybrid search + GraphQL&lt;/td&gt;&#xA;          &lt;td&gt;Prototyping&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ops burden&lt;/td&gt;&#xA;          &lt;td&gt;Low&lt;/td&gt;&#xA;          &lt;td&gt;Medium&lt;/td&gt;&#xA;          &lt;td&gt;Low&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;pgvector-alternative&#34;&gt;pgvector Alternative&lt;/h2&gt;&#xA;&lt;p&gt;PostgreSQL with pgvector keeps vectors beside relational data-excellent when you already run Postgres and need ACID transactions.&lt;/p&gt;&#xA;&lt;h2 id=&#34;selection-criteria&#34;&gt;Selection Criteria&lt;/h2&gt;&#xA;&lt;p&gt;Consider QPS, filtering (metadata predicates), hybrid keyword + vector search, cost, and data residency. Prototype on Chroma or pgvector; migrate to Pinecone or Weaviate at scale.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Streaming AI Responses with OpenAI API in Next.js</title>
      <link>https://www.davidlang.tech/posts/streaming-ai-responses-with-openai-api-in-nextjs/</link>
      <pubDate>Sat, 30 Mar 2024 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/streaming-ai-responses-with-openai-api-in-nextjs/</guid>
      <description>&lt;p&gt;Streaming improves chat UX by showing tokens as they are generated. Next.js Route Handlers make it straightforward to proxy streams securely.&lt;/p&gt;&#xA;&lt;h2 id=&#34;route-handler&#34;&gt;Route Handler&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;// app/api/chat/route.ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;import&lt;/span&gt; OpenAI &lt;span style=&#34;color:#268bd2&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;openai&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;function&lt;/span&gt; POST(req: &lt;span style=&#34;color:#dc322f&#34;&gt;Request&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; { messages } &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;await&lt;/span&gt; req.json();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; openai &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;new&lt;/span&gt; OpenAI();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; stream &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;await&lt;/span&gt; openai.chat.completions.create({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    model&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;gpt-4&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    messages,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    stream: &lt;span style=&#34;color:#dc322f&#34;&gt;true&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; encoder &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;new&lt;/span&gt; TextEncoder();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; readable &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;new&lt;/span&gt; ReadableStream({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#268bd2&#34;&gt;async&lt;/span&gt; start(controller) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#719e07&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;await&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; chunk &lt;span style=&#34;color:#719e07&#34;&gt;of&lt;/span&gt; stream) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; text &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; chunk.choices[&lt;span style=&#34;color:#2aa198&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;color:#719e07&#34;&gt;?&lt;/span&gt;.delta&lt;span style=&#34;color:#719e07&#34;&gt;?&lt;/span&gt;.content &lt;span style=&#34;color:#719e07&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#719e07&#34;&gt;if&lt;/span&gt; (text) controller.enqueue(encoder.encode(text));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      controller.close();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;new&lt;/span&gt; Response(readable, {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    headers&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; { &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;text/plain; charset=utf-8&amp;#39;&lt;/span&gt; },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;client-consumption&#34;&gt;Client Consumption&lt;/h2&gt;&#xA;&lt;p&gt;Use &lt;code&gt;fetch&lt;/code&gt; with a reader loop or libraries like Vercel AI SDK&amp;rsquo;s &lt;code&gt;useChat&lt;/code&gt; for React state management.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Building RAG Systems: Retrieval-Augmented Generation Explained</title>
      <link>https://www.davidlang.tech/posts/building-rag-systems-retrieval-augmented-generation-explained/</link>
      <pubDate>Thu, 18 Jan 2024 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/building-rag-systems-retrieval-augmented-generation-explained/</guid>
      <description>&lt;p&gt;RAG grounds LLM responses in your private data by retrieving relevant documents before generation. It reduces hallucinations and keeps answers current without retraining models.&lt;/p&gt;&#xA;&lt;h2 id=&#34;pipeline-overview&#34;&gt;Pipeline Overview&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ingest&lt;/strong&gt; - Load PDFs, wikis, tickets into chunks (500–1000 tokens).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Embed&lt;/strong&gt; - Convert chunks to vectors with an embedding model.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Store&lt;/strong&gt; - Save vectors in Pinecone, pgvector, or Chroma.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Retrieve&lt;/strong&gt; - On query, embed the question and find top-k similar chunks.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Generate&lt;/strong&gt; - Pass chunks as context to the LLM.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;context &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;.join(retrieved_chunks)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;prompt &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Use only this context:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{context}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Question: {user_query}&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;chunking-strategy&#34;&gt;Chunking Strategy&lt;/h2&gt;&#xA;&lt;p&gt;Overlap chunks by 10–20% to avoid cutting sentences. Metadata (source, page) helps citations and debugging.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Prompt Engineering Fundamentals for Developers</title>
      <link>https://www.davidlang.tech/posts/prompt-engineering-fundamentals-for-developers/</link>
      <pubDate>Sat, 14 Oct 2023 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/prompt-engineering-fundamentals-for-developers/</guid>
      <description>&lt;p&gt;Prompt engineering is the practice of designing inputs so LLMs produce reliable, useful outputs. Developers who treat prompts as code ship better AI features.&lt;/p&gt;&#xA;&lt;h2 id=&#34;structure-your-prompts&#34;&gt;Structure Your Prompts&lt;/h2&gt;&#xA;&lt;p&gt;Use clear sections: role, context, task, format, and constraints.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;You are a code reviewer for a TypeScript React codebase.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Context: PR diff below.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Task: List bugs, security issues, and style problems.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Format: JSON array of { severity, file, message }.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Constraints: Max 10 items. No speculation beyond the diff.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;few-shot-examples&#34;&gt;Few-Shot Examples&lt;/h2&gt;&#xA;&lt;p&gt;Include 2–3 input/output pairs for classification or extraction tasks. Examples beat lengthy instructions for format adherence.&lt;/p&gt;</description>
    </item>
    <item>
      <title>React Server Components: The Future of Data Fetching</title>
      <link>https://www.davidlang.tech/posts/react-server-components-the-future-of-data-fetching/</link>
      <pubDate>Sun, 20 Aug 2023 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/react-server-components-the-future-of-data-fetching/</guid>
      <description>&lt;p&gt;React Server Components (RSC) run on the server only-they never ship component logic to the client. That enables direct database access and smaller JavaScript bundles.&lt;/p&gt;&#xA;&lt;h2 id=&#34;server-vs-client-components&#34;&gt;Server vs Client Components&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-jsx&#34; data-lang=&#34;jsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;// app/page.js - Server Component (default in App Router)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;function&lt;/span&gt; ProductList() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; products &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;await&lt;/span&gt; db.products.findMany();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;return&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#268bd2&#34;&gt;ul&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      {products.map((p) =&amp;gt; &amp;lt;&lt;span style=&#34;color:#268bd2&#34;&gt;li&lt;/span&gt; key&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;{p.id}&amp;gt;{p.name}&amp;lt;/&lt;span style=&#34;color:#268bd2&#34;&gt;li&lt;/span&gt;&amp;gt;)}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#268bd2&#34;&gt;ul&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  );&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Add &lt;code&gt;&#39;use client&#39;&lt;/code&gt; only when you need hooks, event handlers, or browser APIs.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Getting Started with the OpenAI API in Node.js</title>
      <link>https://www.davidlang.tech/posts/getting-started-with-the-openai-api-in-nodejs/</link>
      <pubDate>Thu, 12 Jan 2023 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/getting-started-with-the-openai-api-in-nodejs/</guid>
      <description>&lt;p&gt;The OpenAI API brought large language models to application developers through a simple HTTP interface. Node.js remains a natural fit for BFF layers that call LLMs.&lt;/p&gt;&#xA;&lt;h2 id=&#34;installation-and-first-request&#34;&gt;Installation and First Request&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npm install openai&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;import&lt;/span&gt; OpenAI &lt;span style=&#34;color:#268bd2&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;openai&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; client &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;new&lt;/span&gt; OpenAI({ apiKey: &lt;span style=&#34;color:#dc322f&#34;&gt;process.env.OPENAI_API_KEY&lt;/span&gt; });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; completion &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;await&lt;/span&gt; client.chat.completions.create({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  model&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;gpt-4&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  messages&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    { role&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;system&amp;#39;&lt;/span&gt;, content&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;You are a helpful coding assistant.&amp;#39;&lt;/span&gt; },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    { role&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;user&amp;#39;&lt;/span&gt;, content&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;Explain async/await in JavaScript.&amp;#39;&lt;/span&gt; },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.log(completion.choices[&lt;span style=&#34;color:#2aa198&#34;&gt;0&lt;/span&gt;].message.content);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;production-considerations&#34;&gt;Production Considerations&lt;/h2&gt;&#xA;&lt;p&gt;Never expose API keys in frontend bundles. Proxy requests through your backend. Set &lt;code&gt;max_tokens&lt;/code&gt;, timeouts, and retry policies. Log token usage for cost control.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Serverless Architecture with AWS Lambda</title>
      <link>https://www.davidlang.tech/posts/serverless-architecture-with-aws-lambda/</link>
      <pubDate>Tue, 03 May 2022 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/serverless-architecture-with-aws-lambda/</guid>
      <description>&lt;p&gt;Serverless lets you run code without provisioning servers. AWS Lambda executes functions in response to HTTP, queue, or schedule events-you pay per invocation.&lt;/p&gt;&#xA;&lt;h2 id=&#34;handler-example&#34;&gt;Handler Example&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exports.handler &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;async&lt;/span&gt; (event) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; body &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; JSON.parse(event.body &lt;span style=&#34;color:#719e07&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;{}&amp;#39;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; result &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;await&lt;/span&gt; processOrder(body);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;return&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    statusCode&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;200&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    headers&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; { &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;application/json&amp;#39;&lt;/span&gt; },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    body&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; JSON.stringify(result),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;architecture-patterns&#34;&gt;Architecture Patterns&lt;/h2&gt;&#xA;&lt;p&gt;API Gateway + Lambda for REST endpoints. S3 triggers for image processing. EventBridge for scheduled jobs. Keep functions small and cold-start aware-choose appropriate memory and runtime (Node 20).&lt;/p&gt;</description>
    </item>
    <item>
      <title>React 18: Concurrent Features and the New Root API</title>
      <link>https://www.davidlang.tech/posts/react-18-concurrent-features-and-the-new-root-api/</link>
      <pubDate>Sat, 15 Jan 2022 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/react-18-concurrent-features-and-the-new-root-api/</guid>
      <description>&lt;p&gt;React 18 introduced concurrent rendering, automatic batching, and a new root API. These changes improve perceived performance without rewriting your entire app.&lt;/p&gt;&#xA;&lt;h2 id=&#34;createroot&#34;&gt;createRoot&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-jsx&#34; data-lang=&#34;jsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;import&lt;/span&gt; { createRoot } from &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;react-dom/client&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;import&lt;/span&gt; App from &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;./App&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; root &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; createRoot(&lt;span style=&#34;color:#b58900&#34;&gt;document&lt;/span&gt;.getElementById(&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;root&amp;#39;&lt;/span&gt;));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root.render(&amp;lt;&lt;span style=&#34;color:#268bd2&#34;&gt;App&lt;/span&gt; /&amp;gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The legacy &lt;code&gt;ReactDOM.render&lt;/code&gt; is deprecated. &lt;code&gt;createRoot&lt;/code&gt; enables concurrent features.&lt;/p&gt;&#xA;&lt;h2 id=&#34;suspense-and-transitions&#34;&gt;Suspense and Transitions&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;useTransition&lt;/code&gt; marks updates as non-urgent-keeping the UI responsive during heavy re-renders:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-jsx&#34; data-lang=&#34;jsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; [isPending, startTransition] &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; useTransition();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;function&lt;/span&gt; handleTab(tab) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  startTransition(() =&amp;gt; setActiveTab(tab));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;strict-mode-changes&#34;&gt;Strict Mode Changes&lt;/h2&gt;&#xA;&lt;p&gt;Strict Mode double-invokes effects in development to surface side-effect bugs. Audit &lt;code&gt;useEffect&lt;/code&gt; cleanup functions before upgrading.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Prisma ORM: Modern Database Access in Node.js</title>
      <link>https://www.davidlang.tech/posts/prisma-orm-modern-database-access-in-nodejs/</link>
      <pubDate>Tue, 07 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/prisma-orm-modern-database-access-in-nodejs/</guid>
      <description>&lt;p&gt;Prisma provides type-safe database access, migrations, and a visual data browser-popular in TypeScript full stack projects.&lt;/p&gt;&#xA;&lt;h2 id=&#34;schema-definition&#34;&gt;Schema Definition&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;model User {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  id        String   @id @default(cuid())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  email     String   @unique&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  posts     Post[]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  createdAt DateTime @default(now())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;model Post {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  id       String @id @default(cuid())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  title    String&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  author   User   @relation(fields: [authorId], references: [id])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  authorId String&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;queries&#34;&gt;Queries&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; users &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;await&lt;/span&gt; prisma.user.findMany({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  include&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; { posts: &lt;span style=&#34;color:#dc322f&#34;&gt;true&lt;/span&gt; },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  where&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; { email&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; { contains&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;@company.com&amp;#39;&lt;/span&gt; } },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;migrations&#34;&gt;Migrations&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;npx prisma migrate dev&lt;/code&gt; applies schema changes in development. Use &lt;code&gt;prisma generate&lt;/code&gt; after schema edits to refresh the client.&lt;/p&gt;</description>
    </item>
    <item>
      <title>MongoDB Best Practices: Schema Design and Indexing</title>
      <link>https://www.davidlang.tech/posts/mongodb-best-practices-schema-design-and-indexing/</link>
      <pubDate>Mon, 25 Oct 2021 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/mongodb-best-practices-schema-design-and-indexing/</guid>
      <description>&lt;p&gt;MongoDB&amp;rsquo;s flexible documents are powerful-but schema design still matters for performance and maintainability.&lt;/p&gt;&#xA;&lt;h2 id=&#34;embedding-vs-referencing&#34;&gt;Embedding vs Referencing&lt;/h2&gt;&#xA;&lt;p&gt;Embed when data is read together and has a one-to-few relationship (user preferences inside a user doc). Reference when data grows unbounded or is shared (comments on posts).&lt;/p&gt;&#xA;&lt;h2 id=&#34;indexing&#34;&gt;Indexing&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;db.orders.createIndex({ customerId&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt;, createdAt&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Compound indexes support queries that filter and sort on the same fields. Use &lt;code&gt;.explain()&lt;/code&gt; to verify index usage.&lt;/p&gt;&#xA;&lt;h2 id=&#34;validation-and-migrations&#34;&gt;Validation and Migrations&lt;/h2&gt;&#xA;&lt;p&gt;Use JSON Schema validation at the collection level. Version documents with a &lt;code&gt;schemaVersion&lt;/code&gt; field for gradual migrations.&lt;/p&gt;</description>
    </item>
    <item>
      <title>AWS for Full Stack Developers: Core Services</title>
      <link>https://www.davidlang.tech/posts/aws-for-full-stack-developers-core-services/</link>
      <pubDate>Fri, 10 Sep 2021 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/aws-for-full-stack-developers-core-services/</guid>
      <description>&lt;p&gt;Amazon Web Services powers a large share of production full stack apps. Knowing a focused subset of services beats memorizing the entire catalog.&lt;/p&gt;&#xA;&lt;h2 id=&#34;essential-services&#34;&gt;Essential Services&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Service&lt;/th&gt;&#xA;          &lt;th&gt;Use case&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;EC2 / ECS / Lambda&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Compute&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;S3&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Static assets, uploads&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;RDS / DynamoDB&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Databases&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;CloudFront&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;CDN&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;IAM&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Permissions&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Route 53&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;DNS&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;a-typical-architecture&#34;&gt;A Typical Architecture&lt;/h2&gt;&#xA;&lt;p&gt;React on S3 + CloudFront, API on ECS Fargate or Lambda behind API Gateway, PostgreSQL on RDS, secrets in Secrets Manager, logs in CloudWatch.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Advanced TypeScript: Generics and Utility Types</title>
      <link>https://www.davidlang.tech/posts/advanced-typescript-generics-and-utility-types/</link>
      <pubDate>Sat, 28 Aug 2021 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/advanced-typescript-generics-and-utility-types/</guid>
      <description>&lt;p&gt;Generics make functions and types reusable without sacrificing type safety. Utility types transform existing types-essential for API layers and form handling.&lt;/p&gt;&#xA;&lt;h2 id=&#34;generic-functions&#34;&gt;Generic Functions&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;function&lt;/span&gt; first&amp;lt;&lt;span style=&#34;color:#268bd2&#34;&gt;T&lt;/span&gt;&amp;gt;(arr: &lt;span style=&#34;color:#dc322f&#34;&gt;T&lt;/span&gt;[])&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; T &lt;span style=&#34;color:#719e07&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#cb4b16&#34;&gt;undefined&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;return&lt;/span&gt; arr[&lt;span style=&#34;color:#2aa198&#34;&gt;0&lt;/span&gt;];&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; n &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; first([&lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#2aa198&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#2aa198&#34;&gt;3&lt;/span&gt;]);      &lt;span style=&#34;color:#586e75&#34;&gt;// number | undefined&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; s &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; first([&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;]);     &lt;span style=&#34;color:#586e75&#34;&gt;// string | undefined&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;constrained-generics&#34;&gt;Constrained Generics&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;function&lt;/span&gt; getProperty&amp;lt;&lt;span style=&#34;color:#268bd2&#34;&gt;T&lt;/span&gt;, K extends keyof T&amp;gt;(obj: &lt;span style=&#34;color:#dc322f&#34;&gt;T&lt;/span&gt;, key: &lt;span style=&#34;color:#dc322f&#34;&gt;K&lt;/span&gt;)&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; T[K] {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;return&lt;/span&gt; obj[key];&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;utility-types&#34;&gt;Utility Types&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt; - all properties optional&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Pick&amp;lt;T, K&amp;gt;&lt;/code&gt; - subset of keys&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Omit&amp;lt;T, K&amp;gt;&lt;/code&gt; - exclude keys&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Record&amp;lt;K, V&amp;gt;&lt;/code&gt; - keyed object type&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt; UpdateUserDto &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Partial&amp;lt;&lt;span style=&#34;color:#268bd2&#34;&gt;Pick&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#268bd2&#34;&gt;User&lt;/span&gt;, &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt; | &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;email&amp;#39;&lt;/span&gt;&amp;gt;&amp;gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;Master generics and utilities before reaching for complex conditional types. They keep DTOs, reducers, and hook return types DRY and accurate.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Testing React Components with Jest and RTL</title>
      <link>https://www.davidlang.tech/posts/testing-react-components-with-jest-and-rtl/</link>
      <pubDate>Thu, 15 Jul 2021 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/testing-react-components-with-jest-and-rtl/</guid>
      <description>&lt;p&gt;React Testing Library (RTL) encourages tests that resemble how users interact with your UI-queries by role, label, and text instead of implementation details.&lt;/p&gt;&#xA;&lt;h2 id=&#34;a-simple-component-test&#34;&gt;A Simple Component Test&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-jsx&#34; data-lang=&#34;jsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;import&lt;/span&gt; { render, screen, fireEvent } from &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;@testing-library/react&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;import&lt;/span&gt; Counter from &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;./Counter&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test(&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;increments count on click&amp;#39;&lt;/span&gt;, () =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  render(&amp;lt;&lt;span style=&#34;color:#268bd2&#34;&gt;Counter&lt;/span&gt; /&amp;gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fireEvent.click(screen.getByRole(&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;button&amp;#39;&lt;/span&gt;, { name&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#dc322f&#34;&gt;/increment/i&lt;/span&gt; }));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  expect(screen.getByText(&lt;span style=&#34;color:#dc322f&#34;&gt;/count: 1/i&lt;/span&gt;)).toBeInTheDocument();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;what-to-test&#34;&gt;What to Test&lt;/h2&gt;&#xA;&lt;p&gt;Focus on user-visible behavior: forms submit, errors display, loading states appear. Mock network with MSW (Mock Service Worker) instead of mocking fetch in every test.&lt;/p&gt;</description>
    </item>
    <item>
      <title>WebSockets with Node.js: Real-Time Applications</title>
      <link>https://www.davidlang.tech/posts/websockets-with-nodejs-real-time-applications/</link>
      <pubDate>Wed, 30 Jun 2021 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/websockets-with-nodejs-real-time-applications/</guid>
      <description>&lt;p&gt;WebSockets provide full-duplex communication over a single TCP connection-ideal for chat, live dashboards, and collaborative editing.&lt;/p&gt;&#xA;&lt;h2 id=&#34;socketio-setup&#34;&gt;Socket.io Setup&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; { Server } &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; require(&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;socket.io&amp;#39;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; io &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;new&lt;/span&gt; Server(httpServer, { cors&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; { origin&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; process.env.CLIENT_URL } });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;io.on(&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;connection&amp;#39;&lt;/span&gt;, (socket) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  socket.on(&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;join-room&amp;#39;&lt;/span&gt;, (roomId) =&amp;gt; socket.join(roomId));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  socket.on(&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;message&amp;#39;&lt;/span&gt;, (payload) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    io.to(payload.roomId).emit(&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;message&amp;#39;&lt;/span&gt;, payload);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;scaling-considerations&#34;&gt;Scaling Considerations&lt;/h2&gt;&#xA;&lt;p&gt;Use Redis adapter for Socket.io when running multiple server instances. Sticky sessions or shared pub/sub keep room state consistent.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Building Microservices with Node.js</title>
      <link>https://www.davidlang.tech/posts/building-microservices-with-nodejs/</link>
      <pubDate>Sat, 22 May 2021 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/building-microservices-with-nodejs/</guid>
      <description>&lt;p&gt;Microservices split a system into independently deployable services. Node.js is a common choice for I/O-bound services, BFF layers, and event-driven workers.&lt;/p&gt;&#xA;&lt;h2 id=&#34;service-boundaries&#34;&gt;Service Boundaries&lt;/h2&gt;&#xA;&lt;p&gt;Split by business capability-not by technical layer. A &lt;code&gt;orders&lt;/code&gt; service owns order data; a &lt;code&gt;notifications&lt;/code&gt; service sends email. Communicate via REST, gRPC, or message queues (RabbitMQ, Kafka).&lt;/p&gt;&#xA;&lt;h2 id=&#34;resilience-patterns&#34;&gt;Resilience Patterns&lt;/h2&gt;&#xA;&lt;p&gt;Implement timeouts, retries with exponential backoff, and circuit breakers. Use correlation IDs across services for distributed tracing (OpenTelemetry).&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kubernetes Fundamentals for Developers</title>
      <link>https://www.davidlang.tech/posts/kubernetes-fundamentals-for-developers/</link>
      <pubDate>Sun, 18 Apr 2021 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/kubernetes-fundamentals-for-developers/</guid>
      <description>&lt;p&gt;Kubernetes orchestrates containers at scale. Full stack developers do not need to be cluster admins, but understanding Pods, Deployments, and Services helps you debug production issues.&lt;/p&gt;&#xA;&lt;h2 id=&#34;core-objects&#34;&gt;Core Objects&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Pod&lt;/strong&gt;: One or more containers that share networking and storage.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Deployment&lt;/strong&gt;: Declarative updates for Pods (replicas, rolling updates).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Service&lt;/strong&gt;: Stable network endpoint to reach Pods (ClusterIP, LoadBalancer).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;a-minimal-deployment&#34;&gt;A Minimal Deployment&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;apiVersion&lt;/span&gt;: apps/v1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;kind&lt;/span&gt;: Deployment&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;metadata&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;name&lt;/span&gt;: api&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;spec&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;replicas&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;selector&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#268bd2&#34;&gt;matchLabels&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#268bd2&#34;&gt;app&lt;/span&gt;: api&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;template&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#268bd2&#34;&gt;metadata&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#268bd2&#34;&gt;labels&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#268bd2&#34;&gt;app&lt;/span&gt;: api&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#268bd2&#34;&gt;spec&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#268bd2&#34;&gt;containers&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#268bd2&#34;&gt;name&lt;/span&gt;: api&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;image&lt;/span&gt;: myregistry/api:1.2.0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;ports&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#268bd2&#34;&gt;containerPort&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;3000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;local-development&#34;&gt;Local Development&lt;/h2&gt;&#xA;&lt;p&gt;Use &lt;code&gt;minikube&lt;/code&gt; or &lt;code&gt;kind&lt;/code&gt; to run clusters locally. Skaffold and Tilt sync code into running Pods for faster iteration.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Next.js: The Ultimate Guide to Server-Side Rendering</title>
      <link>https://www.davidlang.tech/posts/nextjs-the-ultimate-guide-to-server-side-rendering/</link>
      <pubDate>Wed, 20 Jan 2021 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/nextjs-the-ultimate-guide-to-server-side-rendering/</guid>
      <description>&lt;p&gt;Next.js extends React with file-based routing, SSR, SSG, and API routes. Understanding when each rendering mode applies is essential for performance and SEO.&lt;/p&gt;&#xA;&lt;h2 id=&#34;rendering-modes&#34;&gt;Rendering Modes&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;Static Generation (SSG)&lt;/strong&gt; pre-renders at build time-ideal for marketing pages and blogs. &lt;strong&gt;Server-Side Rendering (SSR)&lt;/strong&gt; renders on each request-best for personalized or frequently changing data. &lt;strong&gt;Client-Side Rendering (CSR)&lt;/strong&gt; hydrates in the browser for highly interactive dashboards.&lt;/p&gt;&#xA;&lt;h2 id=&#34;getserversideprops-example&#34;&gt;getServerSideProps Example&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;function&lt;/span&gt; getServerSideProps({ params }) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; res &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;await&lt;/span&gt; fetch(&lt;span style=&#34;color:#586e75&#34;&gt;`https://api.example.com/posts/&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;${&lt;/span&gt;params.id&lt;span style=&#34;color:#2aa198&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;`&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; post &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;await&lt;/span&gt; res.json();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;return&lt;/span&gt; { props&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; { post } };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;app-router-preview&#34;&gt;App Router (Preview)&lt;/h2&gt;&#xA;&lt;p&gt;Next.js 13+ introduces the App Router with React Server Components. Pages Router patterns remain widely used-know both as you maintain legacy and greenfield apps.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Setting Up CI/CD Pipelines with GitHub Actions</title>
      <link>https://www.davidlang.tech/posts/setting-up-cicd-pipelines-with-github-actions/</link>
      <pubDate>Mon, 19 Oct 2020 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/setting-up-cicd-pipelines-with-github-actions/</guid>
      <description>&lt;p&gt;GitHub Actions integrates CI/CD directly into your repository. For full stack teams, automating test, build, and deploy on every pull request catches regressions early.&lt;/p&gt;&#xA;&lt;h2 id=&#34;a-basic-nodejs-workflow&#34;&gt;A Basic Node.js Workflow&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;name&lt;/span&gt;: CI&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;on&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;push&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#268bd2&#34;&gt;branches&lt;/span&gt;: [main]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;pull_request&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#268bd2&#34;&gt;branches&lt;/span&gt;: [main]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;jobs&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;test&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#268bd2&#34;&gt;runs-on&lt;/span&gt;: ubuntu-latest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#268bd2&#34;&gt;steps&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#268bd2&#34;&gt;uses&lt;/span&gt;: actions/checkout@v4&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#268bd2&#34;&gt;uses&lt;/span&gt;: actions/setup-node@v4&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#268bd2&#34;&gt;with&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;node-version&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;20&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;cache&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;npm&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#268bd2&#34;&gt;run&lt;/span&gt;: npm ci&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#268bd2&#34;&gt;run&lt;/span&gt;: npm test&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#268bd2&#34;&gt;run&lt;/span&gt;: npm run build&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;deploying-to-production&#34;&gt;Deploying to Production&lt;/h2&gt;&#xA;&lt;p&gt;Add a deploy job that runs only on &lt;code&gt;main&lt;/code&gt; after tests pass. Use environment secrets for API keys. Deploy to Vercel, AWS, or Docker registries with official actions.&lt;/p&gt;</description>
    </item>
    <item>
      <title>PostgreSQL vs MySQL: Choosing the Right Database</title>
      <link>https://www.davidlang.tech/posts/postgresql-vs-mysql-choosing-the-right-database/</link>
      <pubDate>Mon, 10 Aug 2020 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/postgresql-vs-mysql-choosing-the-right-database/</guid>
      <description>&lt;p&gt;Relational databases remain the backbone of most full stack applications. PostgreSQL and MySQL are the two most common choices-each excels in different scenarios.&lt;/p&gt;&#xA;&lt;h2 id=&#34;postgresql-strengths&#34;&gt;PostgreSQL Strengths&lt;/h2&gt;&#xA;&lt;p&gt;PostgreSQL offers advanced types (JSONB, arrays), full-text search, robust concurrency (MVCC), and extensions like PostGIS. It is the default choice for complex queries, analytics-heavy apps, and strict data integrity.&lt;/p&gt;&#xA;&lt;h2 id=&#34;mysql-strengths&#34;&gt;MySQL Strengths&lt;/h2&gt;&#xA;&lt;p&gt;MySQL (and MariaDB) are widely hosted, familiar to many teams, and perform well for read-heavy web workloads. Managed offerings are plentiful and often slightly cheaper at small scale.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Introduction to GraphQL: Why It Matters</title>
      <link>https://www.davidlang.tech/posts/introduction-to-graphql-why-it-matters/</link>
      <pubDate>Sat, 25 Jul 2020 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/introduction-to-graphql-why-it-matters/</guid>
      <description>&lt;p&gt;GraphQL is a query language for APIs that lets clients request exactly the fields they need. Unlike REST, you avoid over-fetching and under-fetching by design.&lt;/p&gt;&#xA;&lt;h2 id=&#34;schema-first-design&#34;&gt;Schema-First Design&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-graphql&#34; data-lang=&#34;graphql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;Query&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  user(id: &lt;span style=&#34;color:#268bd2&#34;&gt;ID&lt;/span&gt;!): &lt;span style=&#34;color:#268bd2&#34;&gt;User&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  posts(limit: &lt;span style=&#34;color:#268bd2&#34;&gt;Int&lt;/span&gt; = 10): [&lt;span style=&#34;color:#268bd2&#34;&gt;Post&lt;/span&gt;!]!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;User&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  id: &lt;span style=&#34;color:#268bd2&#34;&gt;ID&lt;/span&gt;!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  name: &lt;span style=&#34;color:#268bd2&#34;&gt;String&lt;/span&gt;!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  posts: [&lt;span style=&#34;color:#268bd2&#34;&gt;Post&lt;/span&gt;!]!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Clients send queries that mirror the shape of the response:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-graphql&#34; data-lang=&#34;graphql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;query&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;user&lt;/span&gt;(id: &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#268bd2&#34;&gt;name&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    posts(limit: &lt;span style=&#34;color:#268bd2&#34;&gt;5&lt;/span&gt;) { title createdAt }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;server-implementation&#34;&gt;Server Implementation&lt;/h2&gt;&#xA;&lt;p&gt;Apollo Server and GraphQL Yoga are popular in Node.js. Resolvers map fields to databases or microservices. Use DataLoader to batch N+1 queries.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Docker for Developers: Containerizing Your Node.js App</title>
      <link>https://www.davidlang.tech/posts/docker-for-developers-containerizing-your-nodejs-app/</link>
      <pubDate>Sat, 30 May 2020 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/docker-for-developers-containerizing-your-nodejs-app/</guid>
      <description>&lt;p&gt;Docker packages your application and its dependencies into a portable image. For Node.js APIs and React frontends, containers ensure dev, CI, and production environments behave the same way.&lt;/p&gt;&#xA;&lt;h2 id=&#34;a-production-ready-dockerfile&#34;&gt;A Production-Ready Dockerfile&lt;/h2&gt;&#xA;&lt;p&gt;Multi-stage builds keep images small:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-dockerfile&#34; data-lang=&#34;dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;node:20-alpine&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;AS&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;build&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;WORKDIR&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;/app&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;COPY&lt;/span&gt; package*.json ./&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;RUN&lt;/span&gt; npm ci&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;COPY&lt;/span&gt; . .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;RUN&lt;/span&gt; npm run build&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;node:20-alpine&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;WORKDIR&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;/app&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;COPY&lt;/span&gt; --from&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;build /app/dist ./dist&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;COPY&lt;/span&gt; --from&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;build /app/node_modules ./node_modules&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;ENV&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;NODE_ENV&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;production&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;EXPOSE&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;3000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;CMD&lt;/span&gt; [&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;node&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;dist/server.js&amp;#34;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;docker-compose-for-local-dev&#34;&gt;docker-compose for Local Dev&lt;/h2&gt;&#xA;&lt;p&gt;Pair your API with PostgreSQL or Redis:&lt;/p&gt;</description>
    </item>
    <item>
      <title>TypeScript for JavaScript Developers: Getting Started</title>
      <link>https://www.davidlang.tech/posts/typescript-for-javascript-developers-getting-started/</link>
      <pubDate>Sat, 18 Apr 2020 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/typescript-for-javascript-developers-getting-started/</guid>
      <description>&lt;p&gt;TypeScript adds static types to JavaScript, catching bugs at compile time and improving editor autocomplete. For full stack developers moving between frontend and backend, it is one of the highest-leverage skills to adopt.&lt;/p&gt;&#xA;&lt;h2 id=&#34;installing-and-configuring&#34;&gt;Installing and Configuring&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npm install -D typescript @types/node&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npx tsc --init&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A sensible &lt;code&gt;tsconfig.json&lt;/code&gt; for Node or React projects enables &lt;code&gt;strict&lt;/code&gt;, &lt;code&gt;esModuleInterop&lt;/code&gt;, and &lt;code&gt;skipLibCheck&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;core-concepts&#34;&gt;Core Concepts&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;Interfaces&lt;/strong&gt; describe object shapes. &lt;strong&gt;Generics&lt;/strong&gt; make reusable components type-safe. &lt;strong&gt;Union types&lt;/strong&gt; (&lt;code&gt;string | number&lt;/code&gt;) model values that can be one of several types.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Building REST APIs with Node.js and Express</title>
      <link>https://www.davidlang.tech/posts/building-rest-apis-with-nodejs-and-express/</link>
      <pubDate>Sun, 22 Mar 2020 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/building-rest-apis-with-nodejs-and-express/</guid>
      <description>&lt;p&gt;Express remains the most popular framework for building REST APIs in Node.js. It is minimal, unopinionated, and pairs well with middleware for auth, validation, and logging.&lt;/p&gt;&#xA;&lt;h2 id=&#34;project-setup&#34;&gt;Project Setup&lt;/h2&gt;&#xA;&lt;p&gt;Initialize a project and install Express:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npm init -y&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npm install express&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Create a basic server with JSON body parsing:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; express &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; require(&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;express&amp;#39;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; app &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; express();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app.use(express.json());&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; items &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; [];&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app.get(&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;/api/items&amp;#39;&lt;/span&gt;, (req, res) =&amp;gt; res.json(items));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app.post(&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;/api/items&amp;#39;&lt;/span&gt;, (req, res) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;const&lt;/span&gt; item &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; { id&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#b58900&#34;&gt;Date&lt;/span&gt;.now(), ...req.body };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  items.push(item);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  res.status(&lt;span style=&#34;color:#2aa198&#34;&gt;201&lt;/span&gt;).json(item);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app.listen(&lt;span style=&#34;color:#2aa198&#34;&gt;3000&lt;/span&gt;, () =&amp;gt; console.log(&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;API running on :3000&amp;#39;&lt;/span&gt;));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;structure-for-production&#34;&gt;Structure for Production&lt;/h2&gt;&#xA;&lt;p&gt;Organize routes by resource (&lt;code&gt;/users&lt;/code&gt;, &lt;code&gt;/orders&lt;/code&gt;), use a router per domain, and separate controllers from route definitions. Add &lt;code&gt;helmet&lt;/code&gt; for security headers, &lt;code&gt;cors&lt;/code&gt; for cross-origin access, and a centralized error handler that returns consistent JSON error shapes.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Getting Started with React Hooks: A Complete Guide</title>
      <link>https://www.davidlang.tech/posts/getting-started-with-react-hooks-a-complete-guide/</link>
      <pubDate>Sat, 15 Feb 2020 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/getting-started-with-react-hooks-a-complete-guide/</guid>
      <description>&lt;p&gt;React Hooks arrived in React 16.8 and changed how we write components. Instead of class components for state and lifecycle logic, you can use functions with &lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useEffect&lt;/code&gt;, and more.&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-hooks-matter&#34;&gt;Why Hooks Matter&lt;/h2&gt;&#xA;&lt;p&gt;Hooks let you reuse stateful logic without higher-order components or render props. They keep related logic together-fetching data, subscribing to events, and updating the DOM live in one place instead of spread across lifecycle methods.&lt;/p&gt;&#xA;&lt;h2 id=&#34;usestate-and-useeffect&#34;&gt;useState and useEffect&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;useState&lt;/code&gt; declares local state in a function component. &lt;code&gt;useEffect&lt;/code&gt; runs side effects after render-API calls, subscriptions, or DOM updates.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
