<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Posts on David Lang</title>
    <link>https://www.davidlang.tech/posts/</link>
    <description>Recent content in Posts 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/posts/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>Evaluating LLM Outputs: RAGAS, DeepEval, and Custom Metrics</title>
      <link>https://www.davidlang.tech/posts/evaluating-llm-outputs-ragas-deepeval-and-custom-metrics/</link>
      <pubDate>Sat, 18 Oct 2025 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/evaluating-llm-outputs-ragas-deepeval-and-custom-metrics/</guid>
      <description>&lt;p&gt;Frameworks like RAGAS and DeepEval codify LLM evaluation metrics so you can regression-test prompts and pipelines in CI.&lt;/p&gt;&#xA;&lt;h2 id=&#34;ragas-rag-assessment&#34;&gt;RAGAS (RAG Assessment)&lt;/h2&gt;&#xA;&lt;p&gt;Measures context precision/recall, faithfulness, and answer relevance-ideal for retrieval pipelines.&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-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; ragas &lt;span style=&#34;color:#719e07&#34;&gt;import&lt;/span&gt; evaluate&#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; ragas.metrics &lt;span style=&#34;color:#719e07&#34;&gt;import&lt;/span&gt; faithfulness, answer_relevancy&#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;result &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; evaluate(dataset&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;eval_dataset, metrics&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;[faithfulness, answer_relevancy])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;deepeval&#34;&gt;DeepEval&lt;/h2&gt;&#xA;&lt;p&gt;Offers pytest-style LLM tests, G-Eval, and hallucination metrics with CI integration.&lt;/p&gt;&#xA;&lt;h2 id=&#34;custom-metrics&#34;&gt;Custom Metrics&lt;/h2&gt;&#xA;&lt;p&gt;Domain-specific checks often outperform generic scores-JSON schema match, SQL execution success, unit test pass rate for codegen.&lt;/p&gt;</description>
    </item>
    <item>
      <title>FastAPI &#43; LangChain: Building Production-Ready AI APIs</title>
      <link>https://www.davidlang.tech/posts/fastapi-langchain-building-production-ready-ai-apis/</link>
      <pubDate>Fri, 05 Sep 2025 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/fastapi-langchain-building-production-ready-ai-apis/</guid>
      <description>&lt;p&gt;FastAPI&amp;rsquo;s async support and automatic OpenAPI docs pair naturally with LangChain for production AI backends.&lt;/p&gt;&#xA;&lt;h2 id=&#34;project-structure&#34;&gt;Project 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;  main.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  routers/chat.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  services/rag.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  models/schemas.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;async-endpoint&#34;&gt;Async Endpoint&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; fastapi &lt;span style=&#34;color:#719e07&#34;&gt;import&lt;/span&gt; FastAPI&#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; pydantic &lt;span style=&#34;color:#719e07&#34;&gt;import&lt;/span&gt; BaseModel&#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 &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; FastAPI()&#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;class&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;ChatRequest&lt;/span&gt;(BaseModel):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    message: &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;&#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.post&lt;/span&gt;(&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;/chat&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:#719e07&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;chat&lt;/span&gt;(req: ChatRequest):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    result &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;await&lt;/span&gt; rag_chain&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;ainvoke({&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;input&amp;#34;&lt;/span&gt;: req&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;message})&#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:#2aa198&#34;&gt;&amp;#34;answer&amp;#34;&lt;/span&gt;: result[&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;answer&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;production-checklist&#34;&gt;Production Checklist&lt;/h2&gt;&#xA;&lt;p&gt;Rate limiting, API keys, structured logging, health checks, timeout on LLM calls, background tasks for long ingest jobs.&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>Claude Code: Agentic AI Coding from the Terminal</title>
      <link>https://www.davidlang.tech/posts/claude-code-agentic-ai-coding-from-the-terminal/</link>
      <pubDate>Mon, 30 Jun 2025 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/claude-code-agentic-ai-coding-from-the-terminal/</guid>
      <description>&lt;p&gt;Claude Code brings agentic coding to the terminal-read files, edit code, run tests, and commit changes through natural language, powered by Anthropic&amp;rsquo;s models.&lt;/p&gt;&#xA;&lt;h2 id=&#34;workflow&#34;&gt;Workflow&lt;/h2&gt;&#xA;&lt;p&gt;Run from your repository root. Ask for features or fixes in plain language. Claude Code explores the tree, proposes edits, and executes commands with your approval.&lt;/p&gt;&#xA;&lt;h2 id=&#34;strengths&#34;&gt;Strengths&lt;/h2&gt;&#xA;&lt;p&gt;Strong on refactors spanning many files, understanding build errors from test output, and following git history. Terminal-native fits backend and DevOps workflows.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Building Multi-Agent AI Systems</title>
      <link>https://www.davidlang.tech/posts/building-multi-agent-ai-systems/</link>
      <pubDate>Tue, 20 May 2025 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/building-multi-agent-ai-systems/</guid>
      <description>&lt;p&gt;Multi-agent systems divide work among specialized agents-a researcher, coder, critic-coordinated by a supervisor or message bus.&lt;/p&gt;&#xA;&lt;h2 id=&#34;patterns&#34;&gt;Patterns&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;Supervisor&lt;/strong&gt; - One model delegates subtasks and aggregates results.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Peer-to-peer&lt;/strong&gt; - Agents message each other until consensus or max rounds.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Pipeline&lt;/strong&gt; - Fixed stages (plan → implement → test).&lt;/p&gt;&#xA;&lt;h2 id=&#34;implementation-tips&#34;&gt;Implementation Tips&lt;/h2&gt;&#xA;&lt;p&gt;Give each agent a narrow system prompt and tool set. Pass structured state (JSON) between agents, not raw chat logs.&lt;/p&gt;&#xA;&lt;h2 id=&#34;failure-modes&#34;&gt;Failure Modes&lt;/h2&gt;&#xA;&lt;p&gt;Infinite loops, duplicated work, conflicting edits. Enforce step limits, idempotent tools, and single-writer rules for shared files.&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>Cursor vs GitHub Copilot vs Claude Code: The AI Coding Assistant Showdown</title>
      <link>https://www.davidlang.tech/posts/cursor-vs-github-copilot-vs-claude-code-the-ai-coding-assistant-showdown/</link>
      <pubDate>Fri, 10 Jan 2025 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/cursor-vs-github-copilot-vs-claude-code-the-ai-coding-assistant-showdown/</guid>
      <description>&lt;p&gt;AI coding assistants evolved from inline completions to agentic editors. Cursor, GitHub Copilot, and Claude Code represent three philosophies-knowing the differences helps you pick the right tool per task.&lt;/p&gt;&#xA;&lt;h2 id=&#34;github-copilot&#34;&gt;GitHub Copilot&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;Strengths:&lt;/strong&gt; Deep IDE integration (VS Code, JetBrains), inline Tab completion, Copilot Chat, enterprise policies, broad language support.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Day-to-day completion inside your existing editor, teams already on GitHub, minimal workflow change.&lt;/p&gt;&#xA;&lt;h2 id=&#34;cursor&#34;&gt;Cursor&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;Strengths:&lt;/strong&gt; AI-native editor (VS Code fork), multi-file edits, Composer agent, codebase indexing, rules and &lt;code&gt;.cursorrules&lt;/code&gt; for project context, integrated terminal agent.&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>Claude API vs OpenAI API: Choosing the Right LLM</title>
      <link>https://www.davidlang.tech/posts/claude-api-vs-openai-api-choosing-the-right-llm/</link>
      <pubDate>Wed, 14 Aug 2024 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/claude-api-vs-openai-api-choosing-the-right-llm/</guid>
      <description>&lt;p&gt;Anthropic&amp;rsquo;s Claude and OpenAI&amp;rsquo;s GPT families both offer strong APIs. Choosing between them depends on task, context length, cost, and compliance-not benchmark hype alone.&lt;/p&gt;&#xA;&lt;h2 id=&#34;strengths-at-a-glance&#34;&gt;Strengths at a Glance&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;Claude&lt;/strong&gt; - Long context windows, careful refusals, strong long-document analysis and coding reviews.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;OpenAI&lt;/strong&gt; - Broad ecosystem, function calling maturity, image and audio modalities, largest third-party integration surface.&lt;/p&gt;&#xA;&lt;h2 id=&#34;integration-pattern&#34;&gt;Integration Pattern&lt;/h2&gt;&#xA;&lt;p&gt;Abstract the provider behind an interface:&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-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;interface&lt;/span&gt; LLMProvider {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  chat(messages: &lt;span style=&#34;color:#dc322f&#34;&gt;Message&lt;/span&gt;[])&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; Promise&amp;lt;&lt;span style=&#34;color:#268bd2&#34;&gt;string&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Swap implementations per route (cheap model for classification, premium for generation).&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>Fine-Tuning LLMs: When and How to Customize AI Models</title>
      <link>https://www.davidlang.tech/posts/fine-tuning-llms-when-and-how-to-customize-ai-models/</link>
      <pubDate>Wed, 15 May 2024 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/fine-tuning-llms-when-and-how-to-customize-ai-models/</guid>
      <description>&lt;p&gt;Fine-tuning adapts a base model to your domain with labeled examples. Use it when prompting and RAG cannot achieve consistent style, format, or task-specific behavior.&lt;/p&gt;&#xA;&lt;h2 id=&#34;when-to-fine-tune&#34;&gt;When to Fine-Tune&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Fixed output schema (legal clauses, medical codes)&lt;/li&gt;&#xA;&lt;li&gt;Brand voice across thousands of responses&lt;/li&gt;&#xA;&lt;li&gt;Specialized terminology poorly covered by general models&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;when-not-to-fine-tune&#34;&gt;When Not to Fine-Tune&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Facts that change frequently (use RAG)&lt;/li&gt;&#xA;&lt;li&gt;One-off tasks (use prompting)&lt;/li&gt;&#xA;&lt;li&gt;Small datasets without validation (risk overfitting)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;openai-fine-tuning-flow&#34;&gt;OpenAI Fine-Tuning Flow&lt;/h2&gt;&#xA;&lt;p&gt;Prepare JSONL with &lt;code&gt;messages&lt;/code&gt; arrays. Upload, create job, evaluate on a holdout set. Monitor loss and human ratings before promoting to production.&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>GitHub Copilot in Practice: AI-Assisted Development</title>
      <link>https://www.davidlang.tech/posts/github-copilot-in-practice-ai-assisted-development/</link>
      <pubDate>Sun, 25 Feb 2024 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/github-copilot-in-practice-ai-assisted-development/</guid>
      <description>&lt;p&gt;GitHub Copilot suggests code inline and in chat, trained on public repositories. Used well, it accelerates boilerplate; used blindly, it introduces subtle bugs.&lt;/p&gt;&#xA;&lt;h2 id=&#34;effective-workflows&#34;&gt;Effective Workflows&lt;/h2&gt;&#xA;&lt;p&gt;Write descriptive function names and docstrings-Copilot uses them as prompts. Accept suggestions in tests and CRUD handlers; scrutinize auth, crypto, and SQL.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tab-vs-chat&#34;&gt;Tab vs Chat&lt;/h2&gt;&#xA;&lt;p&gt;Inline completions excel for repetitive patterns. Copilot Chat handles explanations, refactors, and multi-file questions inside VS Code and JetBrains.&lt;/p&gt;&#xA;&lt;h2 id=&#34;team-policies&#34;&gt;Team Policies&lt;/h2&gt;&#xA;&lt;p&gt;Define what code can be sent to cloud models. Some organizations restrict Copilot on regulated codebases. Review license implications for generated code.&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>Using dynamic SQL query in Redshift database</title>
      <link>https://www.davidlang.tech/posts/using-sql-dynamic-queries-in-redshift-database/</link>
      <pubDate>Thu, 16 Nov 2023 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/using-sql-dynamic-queries-in-redshift-database/</guid>
      <description>&lt;p&gt;While working with a client, we had a requirement to perform bulk insert/update using &lt;strong&gt;&lt;a href=&#34;https://docs.retool.com/docs/working-with-tables&#34;&gt;Retool table&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href=&#34;https://aws.amazon.com/redshift/&#34;&gt;Redshift database&lt;/a&gt;&lt;/strong&gt;. For this situation, We had to loop through the table records and execute a dynamic SQL query in Redshift.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Redshift database&lt;/strong&gt; supports execution of &lt;strong&gt;dynamic SQL&lt;/strong&gt; with the help of &lt;strong&gt;Prepared Statements&lt;/strong&gt; or &lt;strong&gt;Stored Procedures&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;prepared-statements&#34;&gt;Prepared Statements&lt;/h2&gt;&#xA;&lt;p&gt;We use prepared statements when we want to execute dynamic SQL queries directly without a stored procedure. When a prepared statement is executed, the SQL statement is parsed, rewritten, and planned. We then &lt;strong&gt;EXECUTE&lt;/strong&gt; the prepared statement.&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>Passing AWS Solutions Architect Associate 2020 Exam</title>
      <link>https://www.davidlang.tech/posts/tips-and-resources-passing-cloud-aws-solutions-architect-associate-2020-exam/</link>
      <pubDate>Sun, 03 Sep 2023 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/tips-and-resources-passing-cloud-aws-solutions-architect-associate-2020-exam/</guid>
      <description>&lt;p&gt;Last week I finally took a plunge and decided to take the &lt;strong&gt;&lt;a href=&#34;https://aws.amazon.com/certification/certified-solutions-architect-associate/&#34;&gt;AWS Solutions Architect 2020 - Associate&lt;/a&gt;&lt;/strong&gt; exam. I passed the exam with a score of &lt;strong&gt;&lt;a href=&#34;https://www.certmetrics.com/amazon/public/badge.aspx?i=1&amp;amp;t=c&amp;amp;d=2020-03-14&amp;amp;ci=AWS01122340&#34;&gt;926 / 1000&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I have been working in the cloud space for more than 5 years, but never got the interest in taking the exam. While having a chat with a friend, he told me that he cleared 4 to 5 AWS certifications including AWS Solutions Architect - Professional. That piqued my interest and decided to start with AWS Solutions Architect - Associate.&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>TypeScript Arrays: 25 Essential Functions and Examples</title>
      <link>https://www.davidlang.tech/posts/typescript-arrays-25-essential-functions-and-examples/</link>
      <pubDate>Thu, 22 Jun 2023 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/typescript-arrays-25-essential-functions-and-examples/</guid>
      <description>&lt;h3 id=&#34;introduction&#34;&gt;Introduction:&lt;/h3&gt;&#xA;&lt;p&gt;Arrays are a fundamental data structure in TypeScript, allowing us to store and manipulate collections of elements. TypeScript provides a rich set of array functions that simplify common tasks and enhance the functionality of arrays. In this article, we will explore 25 essential functions of TypeScript arrays and provide practical examples to help you harness their power in your projects.&lt;/p&gt;&#xA;&lt;h4 id=&#34;1-push&#34;&gt;1. push():&lt;/h4&gt;&#xA;&lt;p&gt;Adds one or more elements to the end of an array.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Store additional user information in firebase using react and javascript</title>
      <link>https://www.davidlang.tech/posts/store-additional-user-information-in-firebase-using-react-and-javascript/</link>
      <pubDate>Sun, 28 May 2023 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/store-additional-user-information-in-firebase-using-react-and-javascript/</guid>
      <description>&lt;p&gt;To store additional information for a user in &lt;code&gt;Firebase&lt;/code&gt; using React and JavaScript, you typically use Firestore or the Realtime Database, as Firebase Authentication does not allow for arbitrary additional data to be stored directly in user profiles. Here’s a step-by-step guide on how to achieve this using Firestore.&lt;/p&gt;&#xA;&lt;h2 id=&#34;step-1-set-up-firebase-in-your-react-app&#34;&gt;Step 1: Set Up Firebase in Your React App&lt;/h2&gt;&#xA;&lt;p&gt;First, ensure that you have Firebase set up in your React application. You need to install Firebase and initialize it in your project.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Simple Notes app using React, TypeScript, Node.js, GraphQL and MongoDB</title>
      <link>https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/</link>
      <pubDate>Mon, 17 Apr 2023 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/</guid>
      <description>&lt;p&gt;In the series of the blog post, I am going to walk through step by step process of building a &lt;a href=&#34;https://github.com/rasikjain/SimpleNotes&#34;&gt;Simple Notes&lt;/a&gt; App using &lt;a href=&#34;https://reactjs.org/&#34;&gt;React&lt;/a&gt;, &lt;a href=&#34;https://www.typescriptlang.org/&#34;&gt;TypeScript&lt;/a&gt;, &lt;a href=&#34;https://nodejs.org/en/&#34;&gt;Node.js&lt;/a&gt;, &lt;a href=&#34;https://graphql.org/&#34;&gt;GraphQL &lt;/a&gt;, and &lt;a href=&#34;https://www.mongodb.com/&#34;&gt;MongoDB&lt;/a&gt;. During the process of our development, we are going to use some useful npm packages like &lt;a href=&#34;https://expressjs.com/&#34;&gt;Express&lt;/a&gt;, &lt;a href=&#34;https://www.apollographql.com/docs/apollo-server&#34;&gt;Apollo-Server&lt;/a&gt;, &lt;a href=&#34;https://github.com/typegoose/typegoose&#34;&gt;Typegoose&lt;/a&gt;, &lt;a href=&#34;https://mongoosejs.com/&#34;&gt;Mongoose&lt;/a&gt;, &lt;a href=&#34;https://typegraphql.com/&#34;&gt;TypeGraphQL &lt;/a&gt;, and &lt;a href=&#34;https://getbootstrap.com/&#34;&gt;Bootstrap&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Here is the Github &lt;a href=&#34;https://github.com/rasikjain/SimpleNotes&#34;&gt;Source Code&lt;/a&gt; to run the application.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Table of Content&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/#dev-environment-setup&#34;&gt;Dev Environment Setup&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/#graphql-server-backend&#34;&gt;GraphQL Server Backend&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/#folder-structure&#34;&gt;Folder Structure&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/#creating-nodejs-project&#34;&gt;Creating Node.js project&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/#configuring-typescript&#34;&gt;Configuring TypeScript&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/#installing-dependency-packages&#34;&gt;Installing Dependency Packages&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/#mongoose-schema-and-graphql-schema&#34;&gt;Mongoose Schema and GraphQL Schema&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/#graphql-resolvers&#34;&gt;GraphQL Resolvers&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/#mongo-database-setup&#34;&gt;Mongo Database Setup&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/#environment-configuration&#34;&gt;Environment Configuration&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/#nodejs-server-setup&#34;&gt;Node.js Server Setup&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/#config-files&#34;&gt;Config files&lt;/a&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/#packagejson&#34;&gt;package.json&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/#nodemonjson-configuration&#34;&gt;nodemon.json configuration&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.davidlang.tech/posts/simple-notes-app-using-react-typescript-nodejs-graphql-mongodb/#running-nodejs--server&#34;&gt;Running node.js / Server&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;dev-environment-setup&#34;&gt;Dev Environment Setup&lt;/h3&gt;&#xA;&lt;p&gt;We are going to set up our initial codebase and folder structure to get started. In this tutorial, I am going to use the Windows environment. The command structure is mostly the same and can be easily replicated to macOS.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Introduction to LangChain: Building AI-Powered Apps</title>
      <link>https://www.davidlang.tech/posts/introduction-to-langchain-building-ai-powered-apps/</link>
      <pubDate>Wed, 08 Mar 2023 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/introduction-to-langchain-building-ai-powered-apps/</guid>
      <description>&lt;p&gt;LangChain composes LLM calls with prompts, memory, tools, and retrieval. It standardizes patterns that every AI app eventually needs.&lt;/p&gt;&#xA;&lt;h2 id=&#34;chains-and-prompts&#34;&gt;Chains and Prompts&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_openai &lt;span style=&#34;color:#719e07&#34;&gt;import&lt;/span&gt; ChatOpenAI&#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; langchain_core.prompts &lt;span style=&#34;color:#719e07&#34;&gt;import&lt;/span&gt; ChatPromptTemplate&#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;llm &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; ChatOpenAI(model&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;gpt-4&amp;#34;&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; ChatPromptTemplate&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;from_messages([&#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;system&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Answer as a senior engineer.&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:#2aa198&#34;&gt;&amp;#34;user&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;{question}&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;chain &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; prompt &lt;span style=&#34;color:#719e07&#34;&gt;|&lt;/span&gt; llm&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;response &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; chain&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;invoke({&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;question&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;What is RAG?&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;retrieval&#34;&gt;Retrieval&lt;/h2&gt;&#xA;&lt;p&gt;Load documents, chunk text, embed with OpenAI or open models, store in a vector DB, and retrieve relevant chunks at query time-foundation for RAG systems.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Security - Authentication Workflows</title>
      <link>https://www.davidlang.tech/posts/security-application-authentication-workflows/</link>
      <pubDate>Sun, 05 Feb 2023 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/security-application-authentication-workflows/</guid>
      <description>&lt;p&gt;Here are three scenarios for implementing authentication workflows.&lt;/p&gt;&#xA;&lt;h2 id=&#34;internet-applications-public-facing&#34;&gt;Internet Applications (Public facing)&lt;/h2&gt;&#xA;&lt;p&gt;For internet web applications and APIs, Session based (SessionID cookie) and Token Based (JWT) Authentication can be implemented.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Session Based:&lt;/strong&gt; Implemented for a majority of traditional and stateful web applications. Once the user is authenticated, A Session state is created and stored in an external State server or SQL database. The Session state is identified by a unique SessionID. This SessionID is returned to the client and set as a cookie using &lt;code&gt;Set-Cookie: sessionid=38askse24d56dh43hrs7a8; HttpOnly; Path=/&lt;/code&gt;.&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>Mastering Chart.js in React: A Comprehensive Guide with Examples</title>
      <link>https://www.davidlang.tech/posts/mastering-chartjs-in-react-a-comprehensive-guide-with-examples/</link>
      <pubDate>Thu, 24 Nov 2022 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/mastering-chartjs-in-react-a-comprehensive-guide-with-examples/</guid>
      <description>&lt;h3 id=&#34;introduction&#34;&gt;Introduction:&lt;/h3&gt;&#xA;&lt;p&gt;In the world of web development, data visualization plays a crucial role in conveying information effectively. Chart.js, a popular JavaScript library, provides an elegant and flexible way to create interactive and visually appealing charts. In this blog post, we will explore how to integrate Chart.js into a React application and leverage its powerful features to create stunning charts. We&amp;rsquo;ll cover the installation process, basic usage, and provide practical examples to help you get started.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Differences between getServerSideProps and getStaticProps in Next.js</title>
      <link>https://www.davidlang.tech/posts/differences-between-getserversideprops-and-getstaticprops-in-next.js/</link>
      <pubDate>Tue, 11 Oct 2022 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/differences-between-getserversideprops-and-getstaticprops-in-next.js/</guid>
      <description>&lt;h3 id=&#34;introduction&#34;&gt;Introduction:&lt;/h3&gt;&#xA;&lt;p&gt;&lt;code&gt;Next.js&lt;/code&gt; is a popular &lt;code&gt;React framework&lt;/code&gt; that enables developers to create server-side rendered applications with ease. Two essential functions in Next.js are &lt;code&gt;getServerSideProps&lt;/code&gt; and &lt;code&gt;getStaticProps&lt;/code&gt;, which help developers pre-render pages and optimize performance. Although they share similarities, they have significant differences in terms of functionality and usage. In this blog, we will explore the differences between getServerSideProps and getStaticProps and provide real-world examples to help you understand their use cases.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Boosting Performance with useEffect: Best Use Cases and Examples</title>
      <link>https://www.davidlang.tech/posts/boosting-performance-with-useeffect-best-use-cases-and-examples/</link>
      <pubDate>Wed, 14 Sep 2022 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/boosting-performance-with-useeffect-best-use-cases-and-examples/</guid>
      <description>&lt;h3 id=&#34;introduction&#34;&gt;Introduction:&lt;/h3&gt;&#xA;&lt;p&gt;As a React developer, you&amp;rsquo;re likely familiar with the &lt;code&gt;useEffect&lt;/code&gt; hook. It&amp;rsquo;s a powerful tool that allows you to manage side effects in functional components. While its primary role is to handle tasks like data fetching, DOM manipulation, and subscriptions, &lt;code&gt;useEffect&lt;/code&gt; can also be a game-changer when it comes to optimizing your application&amp;rsquo;s performance. In this blog post, we&amp;rsquo;ll explore some of the best use cases of &lt;code&gt;useEffect&lt;/code&gt; in improving performance, complete with sample code to help you get started.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Simplifying State Management with React&#39;s useContext Feature</title>
      <link>https://www.davidlang.tech/posts/simplifying-state-management-with-react-usecontext-feature/</link>
      <pubDate>Tue, 19 Jul 2022 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/simplifying-state-management-with-react-usecontext-feature/</guid>
      <description>&lt;h3 id=&#34;introduction&#34;&gt;Introduction:&lt;/h3&gt;&#xA;&lt;p&gt;React, being a popular JavaScript library for building user interfaces, provides various tools and features to handle state management. One such feature is &lt;code&gt;useContext&lt;/code&gt;, which allows developers to share state across different components without prop drilling. In this blog post, we will explore the &lt;code&gt;useContext&lt;/code&gt; feature in React and demonstrate its usage with a TypeScript example.&lt;/p&gt;&#xA;&lt;h3 id=&#34;understanding-usecontext&#34;&gt;Understanding useContext:&lt;/h3&gt;&#xA;&lt;p&gt;The &lt;code&gt;useContext&lt;/code&gt; hook is part of the React library and allows components to consume values from a provided context. It provides a simple and efficient way to share state between multiple components in a React application. By utilizing &lt;code&gt;useContext&lt;/code&gt;, we can avoid passing props through intermediate components, thereby reducing the complexity of the codebase.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Efficient Data Flow in React: Unveiling the Power of Prop Drilling</title>
      <link>https://www.davidlang.tech/posts/efficient-data-flow-in-react-unveiling-the-power-of-prop-drilling/</link>
      <pubDate>Wed, 08 Jun 2022 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/efficient-data-flow-in-react-unveiling-the-power-of-prop-drilling/</guid>
      <description>&lt;h3 id=&#34;introduction&#34;&gt;Introduction:&lt;/h3&gt;&#xA;&lt;p&gt;React, the popular JavaScript library for building user interfaces, offers several powerful features that make it a developer-friendly choice. One such feature is prop drilling, a technique used for passing data from a top-level component to a deeply nested component. In this blog post, we will explore the concept of prop drilling, understand its benefits and limitations, and provide an example using TypeScript to demonstrate its usage.&lt;/p&gt;&#xA;&lt;h3 id=&#34;what-is-prop-drilling&#34;&gt;What is Prop Drilling?&lt;/h3&gt;&#xA;&lt;p&gt;Prop drilling refers to the process of passing data through multiple layers of components in order to make it accessible to a deeply nested component that needs it. In React, components are organized in a hierarchical structure, where data typically flows from parent components to their children. However, when a component deeply nested in the component tree requires data from a top-level component, prop drilling comes into play.&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>Enhancing Web Performance with React&#39;s Lazy Loading Feature</title>
      <link>https://www.davidlang.tech/posts/enhancing-web-performance-with-react-lazy-loading-feature/</link>
      <pubDate>Fri, 22 Apr 2022 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/enhancing-web-performance-with-react-lazy-loading-feature/</guid>
      <description>&lt;h3 id=&#34;introduction&#34;&gt;Introduction:&lt;/h3&gt;&#xA;&lt;p&gt;In today&amp;rsquo;s fast-paced digital world, website performance plays a vital role in providing a seamless user experience. As web applications become increasingly complex, it&amp;rsquo;s crucial to optimize the loading time of our applications. One powerful technique to achieve this is lazy loading. In this blog post, we&amp;rsquo;ll explore how React&amp;rsquo;s lazy loading feature can significantly improve web performance by deferring the loading of non-critical components until they are actually needed.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Using React Hooks - useState and useEffect</title>
      <link>https://www.davidlang.tech/posts/using-reactjs-hooks-introduction-usestate-useeffect/</link>
      <pubDate>Tue, 15 Mar 2022 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/using-reactjs-hooks-introduction-usestate-useeffect/</guid>
      <description>&lt;p&gt;With the release of &lt;a href=&#34;https://reactjs.org/docs/hooks-intro.html&#34; title=&#34;React Hooks&#34;&gt;Hooks&lt;/a&gt; in React 16.8, it is now possible to store &lt;strong&gt;state&lt;/strong&gt; in a &lt;strong&gt;function&lt;/strong&gt;. We can add react features like useState and useEffect into the function directly without needing to create &lt;strong&gt;class&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;usestate&#34;&gt;useState&lt;/h2&gt;&#xA;&lt;p&gt;The &lt;strong&gt;useState&lt;/strong&gt; hook adds state to the functional components. useState hook allows you to declare one state variable at a time.&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-react&#34; data-lang=&#34;react&#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; React, { useState } from &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;react&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;function&lt;/span&gt; Counter() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;//Declare the &amp;#34;counter&amp;#34; state variable&#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; [counter, setCounter] &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; useState(&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;  &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;div&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;p&lt;/span&gt;&amp;gt;Clicked {counter} times&amp;lt;/&lt;span style=&#34;color:#268bd2&#34;&gt;p&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;        &lt;span style=&#34;color:#586e75&#34;&gt;//increment the counter by 1 on every click&#xA;&lt;/span&gt;&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;button&lt;/span&gt; onClick&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;{() =&amp;gt; setCounter(counter &lt;span style=&#34;color:#719e07&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt;)}&amp;gt;Click here&amp;lt;/&lt;span style=&#34;color:#268bd2&#34;&gt;button&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;div&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;h2 id=&#34;useeffect&#34;&gt;useEffect&lt;/h2&gt;&#xA;&lt;p&gt;The &lt;strong&gt;useEffect&lt;/strong&gt; allows to manage side effects in a functional component. Some of the examples are fetching external data using api, manipulating DOM in react. It is similar to componentDidMount and componentDidUpdate from class component.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Vite vs Webpack: Why Developers Are Switching</title>
      <link>https://www.davidlang.tech/posts/vite-vs-webpack-why-developers-are-switching/</link>
      <pubDate>Tue, 08 Feb 2022 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/vite-vs-webpack-why-developers-are-switching/</guid>
      <description>&lt;p&gt;Vite uses native ES modules in development for near-instant cold starts. Webpack remains ubiquitous in enterprise codebases-but Vite won the greenfield race by 2022.&lt;/p&gt;&#xA;&lt;h2 id=&#34;development-experience&#34;&gt;Development Experience&lt;/h2&gt;&#xA;&lt;p&gt;Vite serves source files directly; the browser requests modules on demand. Webpack bundles the entire graph before serving-slower as projects grow.&lt;/p&gt;&#xA;&lt;h2 id=&#34;production-builds&#34;&gt;Production Builds&lt;/h2&gt;&#xA;&lt;p&gt;Vite uses Rollup for optimized production bundles. Tree-shaking, code splitting, and asset handling are comparable to Webpack 5.&lt;/p&gt;&#xA;&lt;h2 id=&#34;migration-tips&#34;&gt;Migration Tips&lt;/h2&gt;&#xA;&lt;p&gt;Replace &lt;code&gt;webpack.config.js&lt;/code&gt; with &lt;code&gt;vite.config.ts&lt;/code&gt;. Use &lt;code&gt;import.meta.env&lt;/code&gt; instead of &lt;code&gt;process.env&lt;/code&gt; for env variables. Check plugins-most popular React libraries ship Vite templates.&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>Tailwind CSS: Rapid UI Development</title>
      <link>https://www.davidlang.tech/posts/tailwind-css-rapid-ui-development/</link>
      <pubDate>Fri, 05 Mar 2021 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/tailwind-css-rapid-ui-development/</guid>
      <description>&lt;p&gt;Tailwind CSS is a utility-first framework-you compose designs from small classes in markup instead of writing custom CSS files for every component.&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-teams-adopt-tailwind&#34;&gt;Why Teams Adopt Tailwind&lt;/h2&gt;&#xA;&lt;p&gt;Development speed increases when you do not context-switch between JSX and separate stylesheets. Design tokens (spacing, colors, typography) stay consistent through configuration. PurgeCSS removes unused classes in production builds.&lt;/p&gt;&#xA;&lt;h2 id=&#34;example-component&#34;&gt;Example Component&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;function&lt;/span&gt; Card({ title, children }) {&#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;div&lt;/span&gt; className&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;rounded-lg border border-gray-200 bg-white p-6 shadow-sm hover:shadow-md transition-shadow&amp;#34;&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;h2&lt;/span&gt; className&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;text-lg font-semibold text-gray-900&amp;#34;&lt;/span&gt;&amp;gt;{title}&amp;lt;/&lt;span style=&#34;color:#268bd2&#34;&gt;h2&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;div&lt;/span&gt; className&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;mt-2 text-gray-600&amp;#34;&lt;/span&gt;&amp;gt;{children}&amp;lt;/&lt;span style=&#34;color:#268bd2&#34;&gt;div&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;div&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;h2 id=&#34;customizing-the-theme&#34;&gt;Customizing the Theme&lt;/h2&gt;&#xA;&lt;p&gt;Extend &lt;code&gt;tailwind.config.js&lt;/code&gt; with brand colors and fonts. Use &lt;code&gt;@apply&lt;/code&gt; sparingly in CSS modules for repeated patterns.&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>Modern JavaScript ES2020: Top Features You Should Know</title>
      <link>https://www.davidlang.tech/posts/modern-javascript-es2020-top-features-you-should-know/</link>
      <pubDate>Sat, 28 Nov 2020 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/modern-javascript-es2020-top-features-you-should-know/</guid>
      <description>&lt;p&gt;ECMAScript 2020 added practical features that reduce boilerplate and improve null-safety. If you are still avoiding optional chaining, now is the time to adopt it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;optional-chaining-and-nullish-coalescing&#34;&gt;Optional Chaining and Nullish Coalescing&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; city &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; user&lt;span style=&#34;color:#719e07&#34;&gt;?&lt;/span&gt;.address&lt;span style=&#34;color:#719e07&#34;&gt;?&lt;/span&gt;.city &lt;span style=&#34;color:#719e07&#34;&gt;??&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;Unknown&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;?.&lt;/code&gt; short-circuits on &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;. &lt;code&gt;??&lt;/code&gt; returns the right side only when the left is &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;-unlike &lt;code&gt;||&lt;/code&gt;, it preserves &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;&#39;&#39;&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;bigint-and-globalthis&#34;&gt;BigInt and globalThis&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;BigInt&lt;/code&gt; handles integers beyond &lt;code&gt;Number.MAX_SAFE_INTEGER&lt;/code&gt;. &lt;code&gt;globalThis&lt;/code&gt; provides a standard way to access the global object in browsers and Node.&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>JWT Authentication: Securing Your REST API</title>
      <link>https://www.davidlang.tech/posts/jwt-authentication-securing-your-rest-api/</link>
      <pubDate>Sat, 05 Sep 2020 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/jwt-authentication-securing-your-rest-api/</guid>
      <description>&lt;p&gt;JSON Web Tokens (JWT) are a compact way to represent claims between parties. For stateless REST APIs and SPAs, JWT-based auth is a standard pattern-when implemented correctly.&lt;/p&gt;&#xA;&lt;h2 id=&#34;token-structure&#34;&gt;Token Structure&lt;/h2&gt;&#xA;&lt;p&gt;A JWT has three Base64-encoded parts: header, payload, and signature. The server signs the token with a secret (HS256) or private key (RS256). Clients send &lt;code&gt;Authorization: Bearer &amp;lt;token&amp;gt;&lt;/code&gt; on each request.&lt;/p&gt;&#xA;&lt;h2 id=&#34;issuing-tokens-in-nodejs&#34;&gt;Issuing Tokens in Node.js&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; jwt &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; require(&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;jsonwebtoken&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;function&lt;/span&gt; login(req, res) {&#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; user &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; validateCredentials(req.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;if&lt;/span&gt; (&lt;span style=&#34;color:#719e07&#34;&gt;!&lt;/span&gt;user) &lt;span style=&#34;color:#719e07&#34;&gt;return&lt;/span&gt; res.status(&lt;span style=&#34;color:#2aa198&#34;&gt;401&lt;/span&gt;).json({ error&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;Invalid credentials&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; token &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; jwt.sign(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    { sub&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; user.id, role&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; user.role },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    process.env.JWT_SECRET,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    { expiresIn&lt;span style=&#34;color:#719e07&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;1h&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;  res.json({ token });&#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;middleware-verification&#34;&gt;Middleware Verification&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;function&lt;/span&gt; authMiddleware(req, res, next) {&#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; header &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; req.headers.authorization;&#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; (&lt;span style=&#34;color:#719e07&#34;&gt;!&lt;/span&gt;header&lt;span style=&#34;color:#719e07&#34;&gt;?&lt;/span&gt;.startsWith(&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#39;Bearer &amp;#39;&lt;/span&gt;)) &lt;span style=&#34;color:#719e07&#34;&gt;return&lt;/span&gt; res.sendStatus(&lt;span style=&#34;color:#2aa198&#34;&gt;401&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;try&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    req.user &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; jwt.verify(header.slice(&lt;span style=&#34;color:#2aa198&#34;&gt;7&lt;/span&gt;), process.env.JWT_SECRET);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    next();&#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;catch&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    res.sendStatus(&lt;span style=&#34;color:#2aa198&#34;&gt;401&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;security-checklist&#34;&gt;Security Checklist&lt;/h2&gt;&#xA;&lt;p&gt;Keep secrets out of source control. Use short expiration and refresh tokens for long sessions. Never store sensitive data in the payload-it is readable. Prefer HTTPS everywhere.&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>CSS Grid Layout: Building Responsive Designs</title>
      <link>https://www.davidlang.tech/posts/css-grid-layout-building-responsive-designs/</link>
      <pubDate>Sun, 14 Jun 2020 00:00:00 +0000</pubDate>
      <guid>https://www.davidlang.tech/posts/css-grid-layout-building-responsive-designs/</guid>
      <description>&lt;p&gt;CSS Grid is a two-dimensional layout system-rows and columns together-making it ideal for page layouts, dashboards, and card grids that Flexbox alone struggles with.&lt;/p&gt;&#xA;&lt;h2 id=&#34;defining-a-grid&#34;&gt;Defining a Grid&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-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&lt;span style=&#34;color:#268bd2&#34;&gt;page&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;display&lt;/span&gt;: &lt;span style=&#34;color:#719e07&#34;&gt;grid&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;grid-template-columns&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;240&lt;/span&gt;&lt;span style=&#34;color:#dc322f&#34;&gt;px&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt;fr;&#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;grid-template-rows&lt;/span&gt;: &lt;span style=&#34;color:#cb4b16&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt;fr &lt;span style=&#34;color:#cb4b16&#34;&gt;auto&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;min-height&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;color:#dc322f&#34;&gt;vh&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;gap&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#dc322f&#34;&gt;rem&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;sidebar&lt;/span&gt; { &lt;span style=&#34;color:#719e07&#34;&gt;grid-column&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt;; &lt;span style=&#34;color:#719e07&#34;&gt;grid-row&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;2&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;main&lt;/span&gt;    { &lt;span style=&#34;color:#719e07&#34;&gt;grid-column&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;2&lt;/span&gt;; &lt;span style=&#34;color:#719e07&#34;&gt;grid-row&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;2&lt;/span&gt;; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;responsive-patterns&#34;&gt;Responsive Patterns&lt;/h2&gt;&#xA;&lt;p&gt;Use &lt;code&gt;repeat(auto-fit, minmax(280px, 1fr))&lt;/code&gt; for card layouts that reflow without media queries. Named grid areas improve readability:&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-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&lt;span style=&#34;color:#268bd2&#34;&gt;layout&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;display&lt;/span&gt;: &lt;span style=&#34;color:#719e07&#34;&gt;grid&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;grid-template-areas&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;header header&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:#2aa198&#34;&gt;&amp;#34;nav    main&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:#2aa198&#34;&gt;&amp;#34;footer footer&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;grid-vs-flexbox&#34;&gt;Grid vs Flexbox&lt;/h2&gt;&#xA;&lt;p&gt;Use Grid for page-level structure; use Flexbox for aligning items inside a component (nav links, button groups). They complement each other.&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>
