<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Michael Uzukwu</title>
    <description>The latest articles on DEV Community by Michael Uzukwu (@uzukwu_michael_91a95b823b).</description>
    <link>https://dev.to/uzukwu_michael_91a95b823b</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3331596%2F5b201d56-edd7-4dfc-9dfd-13cf5fd436c6.jpg</url>
      <title>DEV Community: Michael Uzukwu</title>
      <link>https://dev.to/uzukwu_michael_91a95b823b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/uzukwu_michael_91a95b823b"/>
    <language>en</language>
    <item>
      <title>Why Early Request Header Modification Matters in API Gateways</title>
      <dc:creator>Michael Uzukwu</dc:creator>
      <pubDate>Wed, 21 Jan 2026 13:42:53 +0000</pubDate>
      <link>https://dev.to/uzukwu_michael_91a95b823b/why-early-request-header-modification-matters-in-api-gateways-4gle</link>
      <guid>https://dev.to/uzukwu_michael_91a95b823b/why-early-request-header-modification-matters-in-api-gateways-4gle</guid>
      <description>&lt;p&gt;When people think about API gateway security, they often focus on authentication, rate limiting, or Transport Layer Security (TLS). Headers are usually treated as minor details, often like metadata attached to a request.&lt;/p&gt;

&lt;p&gt;But in practice, headers are often the inputs that drive routing, identity, and policy decisions.&lt;/p&gt;

&lt;p&gt;During my recent documentation work on the kgateway project, I spent time documenting and understanding the &lt;strong&gt;early request header modification&lt;/strong&gt; feature. The more I worked and documented, the clearer it became that this isn’t just a “nice-to-have” feature, but  a foundational pattern for building secure and predictable API gateways.&lt;/p&gt;

&lt;p&gt;This article is based on that real contribution, and it’s written for developers and platform engineers working in cloud-native systems who want to apply the same idea, whether they use kgateway or not.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Problem: Trusting Client-Supplied Headers
&lt;/h2&gt;

&lt;p&gt;Let’s start with a realistic scenario. A client sends a request like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/orders&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api.example.com&lt;/span&gt;
&lt;span class="na"&gt;x-user-id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;12345&lt;/span&gt;
&lt;span class="na"&gt;x-tenant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;premium&lt;/span&gt;
&lt;span class="na"&gt;x-auth-source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;internal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your gateway or downstream services rely on headers like &lt;code&gt;x-user-id&lt;/code&gt;, &lt;code&gt;x-tenant&lt;/code&gt;, or &lt;code&gt;x-auth-source&lt;/code&gt;, you already have a problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clients can &lt;strong&gt;forge headers&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Routing logic may make decisions based on &lt;strong&gt;untrusted input&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Authorization policies may be evaluated with &lt;strong&gt;faked identity data&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many API gateways allow header modification but often &lt;strong&gt;only after route selection&lt;/strong&gt;.&lt;br&gt;
By then, the request may already have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Matched the wrong route&lt;/li&gt;
&lt;li&gt;Triggered the wrong policy&lt;/li&gt;
&lt;li&gt;Been forwarded to the wrong backend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;That’s too late.&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Why “Early” Header Modification Exists
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Early request header modification&lt;/strong&gt; means sanitizing headers &lt;strong&gt;before&lt;/strong&gt; routing and policy evaluation happen.&lt;/p&gt;

&lt;p&gt;Conceptually, the flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client Request
  (untrusted headers)
        ↓
Early Header Modification
  - Remove unsafe headers
  - Inject trusted metadata
        ↓
Route Selection
        ↓
Policy Evaluation
        ↓
Upstream Services
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This guarantees that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Routing logic only sees clean, trusted headers&lt;/li&gt;
&lt;li&gt; Policies behave consistently&lt;/li&gt;
&lt;li&gt; Downstream services don’t need to guess what’s safe to trust&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Think of it like security screening at an airport: you don’t wait until someone boards the plane to remove dangerous items.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Real-World Example
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Goal
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Prevent clients from spoofing identity headers&lt;/li&gt;
&lt;li&gt;Ensure routing and policies rely only on gateway-controlled metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Early Header Modification (Conceptual)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;earlyHeaderModifier&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;x-user-id&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;x-tenant&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;x-auth-source&lt;/span&gt;
  &lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;x-auth-source&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gateway&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this achieves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client-supplied identity headers are stripped immediately&lt;/li&gt;
&lt;li&gt;A trusted header is injected by the gateway&lt;/li&gt;
&lt;li&gt;All routing and policies downstream see predictable input&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Downstream services can now safely assume:&lt;br&gt;&lt;br&gt;
&lt;em&gt;“If this header exists, it came from the gateway — not the client.”&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Timing Is the Critical Detail
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Modification Type&lt;/th&gt;
&lt;th&gt;When It Runs&lt;/th&gt;
&lt;th&gt;Risk&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Standard header modification&lt;/td&gt;
&lt;td&gt;After route selection&lt;/td&gt;
&lt;td&gt;Client headers may already influence routing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Early header modification&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Before route selection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Only trusted headers affect routing &amp;amp; policies&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This timing difference is subtle, but it’s the difference between:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Defensive design&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;And &lt;strong&gt;accidental trust in user input&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  How This Is Implemented in kgateway
&lt;/h2&gt;

&lt;p&gt;In kgateway, early request header modification is implemented using the &lt;strong&gt;HTTPListenerPolicy API&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This allows header sanitization to occur &lt;em&gt;before&lt;/em&gt; routing, which is especially important for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-tenant routing&lt;/li&gt;
&lt;li&gt;Policy-driven architectures&lt;/li&gt;
&lt;li&gt;Zero-trust gateway setups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I recently documented this behavior as part of a contribution to the kgateway docs, including:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When the feature runs&lt;/li&gt;
&lt;li&gt;How it differs from standard header modifiers&lt;/li&gt;
&lt;li&gt;How to configure it safely&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;📘 Official Guide&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://kgateway.dev/docs/envoy/main/traffic-management/header-control/early-request-header-modifier/" rel="noopener noreferrer"&gt;Early Request Header Modification (kgateway)&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Applying the Pattern Beyond kgateway
&lt;/h2&gt;

&lt;p&gt;Even if you’re not using kgateway, the pattern applies broadly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Never trust&lt;/strong&gt; client-supplied headers&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Sanitize before routing&lt;/strong&gt;, not after&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Inject trusted metadata&lt;/strong&gt; at the gateway boundary&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Make policies deterministic&lt;/strong&gt; by design&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach works whether you’re using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Envoy-based gateways&lt;/li&gt;
&lt;li&gt;Kubernetes ingress controllers&lt;/li&gt;
&lt;li&gt;Service mesh edge proxies&lt;/li&gt;
&lt;li&gt;Custom gateway layers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea is universal, only the configuration syntax changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Documentation Matters Here
&lt;/h2&gt;

&lt;p&gt;This is one of those features that’s easy to misuse if it’s not documented clearly.Without good documentation, users may:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modify headers too late&lt;/li&gt;
&lt;li&gt;Assume headers are safe when they’re not&lt;/li&gt;
&lt;li&gt;Miss the feature entirely&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clear docs help users understand not just &lt;strong&gt;how&lt;/strong&gt; to configure something, but &lt;strong&gt;why&lt;/strong&gt; it exists in the first place. That’s what motivated my contribution and this article.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;API gateway security isn’t only about auth tokens and firewalls.&lt;/p&gt;

&lt;p&gt;Sometimes, it’s the &lt;strong&gt;small architectural details&lt;/strong&gt; - like &lt;strong&gt;when&lt;/strong&gt; a header is modified that determines whether your system is safe or fragile.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Early request header modification prevents problems before they happen.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If you design, operate, or document cloud-native systems, it’s a pattern worth understanding deeply.&lt;/p&gt;

</description>
      <category>apigateway</category>
      <category>cloudnative</category>
      <category>security</category>
      <category>documentation</category>
    </item>
    <item>
      <title>How I Added Glossary Tooltip Hover to Kgateway Docs (Using Hugo Shortcodes)</title>
      <dc:creator>Michael Uzukwu</dc:creator>
      <pubDate>Thu, 11 Dec 2025 13:12:08 +0000</pubDate>
      <link>https://dev.to/uzukwu_michael_91a95b823b/how-i-added-glossary-tooltip-hover-to-kgateway-docs-using-hugo-shortcodes-1e6o</link>
      <guid>https://dev.to/uzukwu_michael_91a95b823b/how-i-added-glossary-tooltip-hover-to-kgateway-docs-using-hugo-shortcodes-1e6o</guid>
      <description>&lt;p&gt;When I joined the &lt;strong&gt;Kgateway documentation team as a Technical Writer and contributor&lt;/strong&gt;, one pattern kept repeating during reviews and user feedback:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Readers were constantly getting stuck on core terms.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kgateway touches so many different domains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes
&lt;/li&gt;
&lt;li&gt;Envoy
&lt;/li&gt;
&lt;li&gt;Service Mesh
&lt;/li&gt;
&lt;li&gt;AI / Agentic patterns
&lt;/li&gt;
&lt;li&gt;Kgateway-specific architecture
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So concepts like &lt;strong&gt;Clusters (Envoy)&lt;/strong&gt;, &lt;strong&gt;Backends&lt;/strong&gt;, &lt;strong&gt;A2A&lt;/strong&gt;, &lt;strong&gt;Ambient Mesh&lt;/strong&gt;, or &lt;strong&gt;Data Plane&lt;/strong&gt; appear everywhere.&lt;br&gt;&lt;br&gt;
But new readers often had to leave the page just to understand what these terms meant.&lt;/p&gt;

&lt;p&gt;Not good for learning flow.&lt;/p&gt;

&lt;p&gt;So I decided to solve it the way modern docs teams do (think Stripe, Datadog, GitHub):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;I implemented a reusable glossary tooltip hover system using Hugo shortcodes.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It ended up improving clarity, reducing confusion, and making the docs feel far more polished.&lt;/p&gt;

&lt;p&gt;In this article, I’ll walk through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why this feature matters
&lt;/li&gt;
&lt;li&gt;Where to place (and &lt;em&gt;not&lt;/em&gt; place) tooltips
&lt;/li&gt;
&lt;li&gt;The exact files I built (&lt;code&gt;gloss.html&lt;/code&gt;, YAML store, and CSS)
&lt;/li&gt;
&lt;li&gt;Screenshots
&lt;/li&gt;
&lt;li&gt;Lessons learned as a documentation contributor
&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Why Glossary Tooltips Matter (Especially in Technical Documentation)
&lt;/h2&gt;

&lt;p&gt;Tooltips look like a small UI detail, but they significantly improve the &lt;em&gt;reading experience&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here’s why:&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;1. Faster learning, fewer context switches&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Readers shouldn’t need to open three tabs just to understand a sentence.&lt;br&gt;&lt;br&gt;
A simple hover = instant definition.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;2. Helps unify mixed terminology&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Kgateway mixes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes CRDs
&lt;/li&gt;
&lt;li&gt;Envoy concepts
&lt;/li&gt;
&lt;li&gt;Agentic AI terms
&lt;/li&gt;
&lt;li&gt;Mesh networking terminology
&lt;/li&gt;
&lt;li&gt;Kgateway-specific keywords
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A central glossary helps create consistency.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;3. Cleaner, more readable pages&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Instead of repeating definitions everywhere, a tooltip keeps things neat.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;4. One source of truth (via YAML)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Whenever a definition changes, update it once → it updates everywhere.&lt;/p&gt;


&lt;h2&gt;
  
  
  But There’s a Catch: Don’t Overuse Tooltips
&lt;/h2&gt;

&lt;p&gt;While building this feature, the docs maintainer and I agreed on one rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Do NOT apply tooltips on every instance of a term.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Too many hover effects distract readers, especially on dense technical pages.&lt;/p&gt;

&lt;p&gt;So we adopted a &lt;strong&gt;strategic placement model&lt;/strong&gt;👇&lt;/p&gt;


&lt;h2&gt;
  
  
  Where to Place Tooltips (and Where Not To)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Use tooltips in these places:&lt;/strong&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Location&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Where a term is first introduced&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Helps readers build initial understanding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Overview or conceptual pages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;These pages often introduce many new ideas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pages discussing a concept heavily&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Add tooltips once or twice only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Glossary page&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Optional, but helpful&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Avoid tooltips in:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Every repeated occurrence
&lt;/li&gt;
&lt;li&gt;Tables with long text
&lt;/li&gt;
&lt;li&gt;Code blocks
&lt;/li&gt;
&lt;li&gt;Headings (breaks formatting)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This keeps the UI clean and professional.&lt;/p&gt;


&lt;h2&gt;
  
  
  How I Implemented Glossary Tooltips (Hugo Shortcodes + YAML + CSS)
&lt;/h2&gt;

&lt;p&gt;This is the entire structure I added to the Kgateway docs.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;1. YAML Glossary Data Store&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;/data/glossary.yaml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;A2A&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;short&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent-to-Agent&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Protocol&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;—&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secure,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;policy-driven&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;communication&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;between&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sidecarless&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;agents."&lt;/span&gt;

&lt;span class="na"&gt;Agentgateway&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;short&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;open-source&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;plane&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;optimized&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;agentic&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;AI&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;connectivity."&lt;/span&gt;

&lt;span class="na"&gt;Cluster (Envoy)&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;short&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Envoy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'cluster'&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;—&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;logical&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;grouping&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;upstream&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;endpoints&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;used&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;load&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;balancing."&lt;/span&gt;

&lt;span class="na"&gt;Backends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;short&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Destination&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;services&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;or&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;endpoints&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Kgateway&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;routes&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;traffic&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(Kubernetes&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;services,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Lambdas,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;external&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;hosts)."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This acts like a central mini-database for terms. We ended up storing 30+ key concepts.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Hugo Tooltip Shortcode
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File&lt;/strong&gt;: &lt;code&gt;layouts/shortcodes/gloss.html&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;glossary&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;

&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"glossary-term"&lt;/span&gt; &lt;span class="n"&gt;tabindex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;glossary&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"{{ $key }}"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Inner&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"tooltip-content"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;strong&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;strong&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;short&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"{{ $entry.link }}"&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"tooltip-link"&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="n"&gt;Learn&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Inner&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage in Markdown&lt;/strong&gt;:&lt;br&gt;
The translation cycle starts by defining {{&amp;lt; gloss "Cluster (Envoy)" &amp;gt;}}Envoy clusters{{&amp;lt; /gloss &amp;gt;}}...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6irkv9kzk9owrcl2g10h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6irkv9kzk9owrcl2g10h.png" alt="Hover definition for “Control Plane" width="800" height="464"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Fig 1&lt;/strong&gt;: &lt;em&gt;Tooltip Hover Definition for 'Control Plane' in the Concept Architecture page&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Tooltip Styling (CSS)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File&lt;/strong&gt;: static/css/glossary.css&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.glossary-term&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;help&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;dotted&lt;/span&gt; &lt;span class="m"&gt;#666&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.glossary-term&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;visibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;280px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;125%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="m"&gt;12px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.15&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;opacity&lt;/span&gt; &lt;span class="m"&gt;.3s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.glossary-term&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.glossary-term&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;visibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Accessible, responsive, and subtle.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The Glossary Page
&lt;/h3&gt;

&lt;p&gt;We also created a full &lt;code&gt;glossary.md&lt;/code&gt; page, which:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;improves SEO&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;collects all terms in one place&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;creates a complete reference index&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Glossary hover tooltips may look small, but they make your docs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;easier to read&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;friendlier to beginners&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;more consistent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;more modern&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And in my experience contributing to Kgateway docs, this little feature created a big difference in user experience.&lt;/p&gt;

&lt;p&gt;If you're building technical documentation on Hugo or not, I highly recommend adding it.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;br&gt;
Feel free to ask if you want a reusable template or module version. Meanwhile here's a link my merged Pull Request for this task: &lt;a href="https://github.com/kgateway-dev/kgateway.dev/pull/484#event-21146577386" rel="noopener noreferrer"&gt;Tooltip Hover feature&lt;/a&gt;&lt;/p&gt;

</description>
      <category>documentation</category>
      <category>hugo</category>
      <category>frontend</category>
      <category>opensource</category>
    </item>
    <item>
      <title>A Beginner-Friendly Guide to Docs as Code &amp; CI/CD Pipelines</title>
      <dc:creator>Michael Uzukwu</dc:creator>
      <pubDate>Fri, 08 Aug 2025 22:17:22 +0000</pubDate>
      <link>https://dev.to/uzukwu_michael_91a95b823b/a-beginner-friendly-guide-to-docs-as-code-cicd-pipelines-470l</link>
      <guid>https://dev.to/uzukwu_michael_91a95b823b/a-beginner-friendly-guide-to-docs-as-code-cicd-pipelines-470l</guid>
      <description>&lt;p&gt;In today's software world, documentation is no longer a side task—it’s a core part of the development lifecycle. If you've heard terms like &lt;strong&gt;“Docs as Code”&lt;/strong&gt; and &lt;strong&gt;“CI/CD pipelines”&lt;/strong&gt;, but they sound intimidating or too advanced, this guide is for you.&lt;/p&gt;

&lt;p&gt;Whether you’re a technical writer, developer, or contributor to an open-source project, you'll learn how to automate documentation deployment using a static site generator and GitHub Actions. No complex DevOps background needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is “Docs as Code”?
&lt;/h2&gt;

&lt;p&gt;Docs as Code is a modern approach that treats documentation just like source code. Instead of writing docs in Google Docs or Word, you write them in &lt;strong&gt;Markdown&lt;/strong&gt;, version them in &lt;strong&gt;Git&lt;/strong&gt;, and manage them in the same repository as the project.&lt;/p&gt;

&lt;p&gt;This approach allows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Team collaboration through version control (like Git)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Code reviews and pull requests for documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automated building and deployment (CI/CD)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reuse of developer tools for docs workflows&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CI/CD Pipeline
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CI/CD&lt;/strong&gt; stands for &lt;strong&gt;Continuous Integration and Continuous Deployment&lt;/strong&gt;. It means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CI&lt;/strong&gt;: Automatically checking your code or docs when you push changes (e.g., spellcheck, linting, tests).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CD&lt;/strong&gt;: Automatically building and deploying your site to the web without manual steps.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, we’ll use GitHub’s &lt;strong&gt;Actions&lt;/strong&gt; feature to run our CI/CD pipeline whenever we push to the &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Guide Matters
&lt;/h2&gt;

&lt;p&gt;While some static site generators (SSGs) like &lt;strong&gt;Astro Starlight&lt;/strong&gt; or &lt;strong&gt;Next.js&lt;/strong&gt; do offer native/auto-deployment especially on platforms like &lt;strong&gt;Vercel&lt;/strong&gt;, &lt;strong&gt;Netlify&lt;/strong&gt;, etc, others like &lt;strong&gt;MkDocs&lt;/strong&gt;, &lt;strong&gt;Hugo&lt;/strong&gt;, and &lt;strong&gt;Docusaurus&lt;/strong&gt; don't—especially when using &lt;strong&gt;GitHub Pages&lt;/strong&gt; for hosting.&lt;/p&gt;

&lt;p&gt;To solve this gap, we’ll create our own automated workflow using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;MkDocs (a Python-based static site generator)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GitHub Actions (for automation)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GitHub Pages (for free hosting)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end, you’ll have a workflow where your documentation deploys automatically each time you push changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of This Setup
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zero cost&lt;/strong&gt;: Everything uses free GitHub features.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automation&lt;/strong&gt;: No need to deploy manually.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Versioned and traceable&lt;/strong&gt;: Every change is recorded in Git.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lightweight&lt;/strong&gt;: Minimal setup needed for personal or team docs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting, you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A GitHub&lt;/strong&gt; account and repository set up&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Basic knowledge of Markdown and Git&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python&lt;/strong&gt; installed locally&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MkDocs installed (&lt;code&gt;pip install mkdocs mkdocs-material&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Project Recap: What We Deployed
&lt;/h2&gt;

&lt;p&gt;For this demo, we built and deployed a simple &lt;strong&gt;Vue.js&lt;/strong&gt; documentation site using &lt;strong&gt;MkDocs&lt;/strong&gt; and hosted it at:&lt;br&gt;
👉 &lt;a href="https://mike-4-prog.github.io/vue.js-mkdocs-demo/" rel="noopener noreferrer"&gt;demo site&lt;/a&gt;&lt;br&gt;
It currently includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A custom homepage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduction page&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Quick Start guide&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step-by-Step: Set Up CI/CD for MkDocs with GitHub Pages
&lt;/h2&gt;

&lt;p&gt;Here’s how we set up the pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Understand the Flow&lt;/strong&gt;
When you push changes to your main branch, GitHub Actions will:&lt;/li&gt;
&lt;li&gt;Detect the change (triggered by the on: push event in deploy.yml).&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Checkout your repo code into the workflow environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set up Python (since MkDocs is Python-based).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install MkDocs and the Material theme.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build the documentation into static HTML.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deploy it to the gh-pages branch, which GitHub Pages serves as your live site.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Project Folder Structure&lt;/strong&gt;
Your folder should look like this:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vue.js-mkdocs-demo/
├── docs/
│   ├── index.md
│   ├── introduction.md
│   └── quick-start.md
├── mkdocs.yml
├── .github/
│   └── workflows/
│       └── deploy.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create a &lt;code&gt;deploy.yml&lt;/code&gt; Workflow File&lt;/strong&gt;
Inside &lt;code&gt;.github/workflows/&lt;/code&gt;, create a file named &lt;code&gt;deploy.yml&lt;/code&gt; and include your script similar to this:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy MkDocs Site&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;  &lt;span class="c1"&gt;# deploy when pushing to main&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;  &lt;span class="c1"&gt;# needed to push to gh-pages branch&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repo&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Python&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v5&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.10'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;python -m pip install --upgrade pip&lt;/span&gt;
          &lt;span class="s"&gt;pip install mkdocs mkdocs-material&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and deploy&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mkdocs gh-deploy --force --remote-name origin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwtn0hjlbs391oedttdxp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwtn0hjlbs391oedttdxp.png" alt=" deploy.yml file in VS Code" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Fig1&lt;/strong&gt;: &lt;em&gt;Code syntax showing the 'deploy.yml' file setup for the CI/CD Pipeline&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Runs when you push to the main branch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Installs Python and MkDocs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Builds your docs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deploys them to GitHub Pages&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Push and Watch the Pipeline Run&lt;/strong&gt;
Once you’ve created the file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add .github/workflows/deploy.yml
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add MkDocs deployment workflow"&lt;/span&gt;
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Go to the Actions tab in your GitHub repo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should see the “Deploy MkDocs Site” workflow running.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click into it to watch each step (checkout, setup, install, build, deploy).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All steps should turn green ✅ when successful.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdi2tppho196g44mbq2tk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdi2tppho196g44mbq2tk.png" alt="Github pages setup" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Fig2&lt;/strong&gt;: &lt;em&gt;Set up Configurations for Github Pages&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdzot9aobib0munw4i27r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdzot9aobib0munw4i27r.png" alt="Successful Github Actions Flow" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Fig4&lt;/strong&gt;: &lt;em&gt;Github Actions Flow Showing Successful deployment&lt;/em&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;View Your Live Documentation&lt;/strong&gt;
Once the workflow finishes, your site will be live at:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://&amp;lt;your-username&amp;gt;.github.io/&amp;lt;repo-name&amp;gt;/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frb3gvn73nqmspv6s3u78.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frb3gvn73nqmspv6s3u78.png" alt="Live Mkdocs site homepage hosted on Github pages" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Fig5&lt;/strong&gt;: &lt;em&gt;Live Site of deployed Vue.js docs built with Mkdocs&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;This guide proves that documentation automation isn’t just for large dev teams—it’s beginner-friendly and accessible. By using Docs as Code practices with GitHub Actions and MkDocs, you ensure your docs stay live, versioned, and up-to-date with zero manual deployment effort.&lt;/p&gt;

&lt;p&gt;Treating docs like code saves time, builds consistency, and improves collaboration. If you're new to CI/CD or static site generators, this hands-on tutorial is a solid start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Live Site]&lt;/strong&gt;(&lt;a href="https://mike-4-prog.github.io/vue.js-mkdocs-demo/" rel="noopener noreferrer"&gt;https://mike-4-prog.github.io/vue.js-mkdocs-demo/&lt;/a&gt;)&lt;br&gt;
&lt;strong&gt;[Github Repo]&lt;/strong&gt;(&lt;a href="https://github.com/Mike-4-prog/vue.js-mkdocs-demo" rel="noopener noreferrer"&gt;https://github.com/Mike-4-prog/vue.js-mkdocs-demo&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>documentation</category>
      <category>cicd</category>
      <category>githubactions</category>
      <category>opensource</category>
    </item>
    <item>
      <title>From Code to Live in Minutes: Deploying My Astro Starlight Static Site on Vercel.</title>
      <dc:creator>Michael Uzukwu</dc:creator>
      <pubDate>Tue, 08 Jul 2025 21:53:49 +0000</pubDate>
      <link>https://dev.to/uzukwu_michael_91a95b823b/from-code-to-live-in-minutes-deploying-my-astro-starlight-static-site-on-vercel-49ca</link>
      <guid>https://dev.to/uzukwu_michael_91a95b823b/from-code-to-live-in-minutes-deploying-my-astro-starlight-static-site-on-vercel-49ca</guid>
      <description>&lt;p&gt;When I set out to recreate the Vue.js documentation using Astro Starlight a month ago, I had two main goals — keep it static, and make it accessible online with minimal setup.&lt;/p&gt;

&lt;p&gt;At first, I figured &lt;strong&gt;GitHub Pages&lt;/strong&gt; would do the trick — but I ran into a few headaches pretty quickly. Then I made the switch to &lt;strong&gt;Vercel&lt;/strong&gt;, and it turned out to be one of the best decisions for this project.&lt;/p&gt;

&lt;p&gt;In this post, I’ll walk you through how I deployed my Astro-powered documentation site using Vercel, and why it’s now my preferred tool for static site hosting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Vercel for Static Sites?
&lt;/h2&gt;

&lt;p&gt;So, what made me go with Vercel? Here’s what really convinced me before I even got to the setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;Instant GitHub integration&lt;/strong&gt; – Deploy right from your repository with no CLI fuss.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Global CDN out of the box&lt;/strong&gt; – Blazing-fast performance for static assets.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Custom domain support&lt;/strong&gt; – Easy setup and automatic HTTPS&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Automatic deploy previews&lt;/strong&gt; – See what each branch or PR looks like live.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Zero-config setup&lt;/strong&gt; – Frameworks like Astro are detected automatically.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Free tier available&lt;/strong&gt; – Ideal for personal projects and experimentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Project Context: Rebuilding Vue.js Docs with Astro Starlight
&lt;/h2&gt;

&lt;p&gt;As part of &lt;strong&gt;Product Documentation Cohort-1&lt;/strong&gt; of the &lt;strong&gt;Technical Writing Mentorship Program (TWMP)&lt;/strong&gt;, I recreated the Vue.js documentation using &lt;strong&gt;Astro Starlight&lt;/strong&gt; — a lightweight static site generator that focuses on performance, markdown-based content, and great developer experience.&lt;/p&gt;

&lt;p&gt;The idea was to restructure and improve the official Vue.js docs — but powered by Astro.&lt;/p&gt;

&lt;p&gt;Since the content was static, with no backend or dynamic data, this made it perfect for static deployment — no server needed, just HTML, CSS, and JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-Step: Deploying an Astro Site on Vercel
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;GitHub account&lt;/strong&gt; with your static site code pushed to a repo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fze1z0y6dn8rswxa994li.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fze1z0y6dn8rswxa994li.png" alt="Vue.js GitHub repository ready for deployment" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Figure 1&lt;/strong&gt;: &lt;em&gt;Ensure your static site code (like this Vue.js repo) is pushed to GitHub before importing it into Vercel.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;Vercel account&lt;/strong&gt; (you can sign up with GitHub for seamless integration).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  1. Import Your Project into Vercel
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa04p3u4ilpsyi6hfiexj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa04p3u4ilpsyi6hfiexj.png" alt="Vercel detecting Astro framework during project set up" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 2&lt;/strong&gt;: &lt;em&gt;Vercel automatically detects Astro as the framework and applies default build and output settings.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;a href="https://vercel.com/dashboard" rel="noopener noreferrer"&gt;vercel.com/dashboard&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;“Add New Project”&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select your GitHub repository (Vercel may ask for GitHub access the first time).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vercel will auto-detect &lt;strong&gt;Astro&lt;/strong&gt; as the framework and pre-fill the build command (&lt;code&gt;astro build&lt;/code&gt;) and output directory (&lt;code&gt;dist&lt;/code&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Configure the Settings
&lt;/h3&gt;

&lt;p&gt;You can usually go with the defaults:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Framework: Astro  
Build &lt;span class="nb"&gt;command&lt;/span&gt;: astro build  
Output directory: dist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Deploy
&lt;/h3&gt;

&lt;p&gt;Click the &lt;strong&gt;“Deploy”&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;Vercel will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clone your repo&lt;/li&gt;
&lt;li&gt;Install dependencies&lt;/li&gt;
&lt;li&gt;Build the project&lt;/li&gt;
&lt;li&gt;Host the &lt;code&gt;dist/&lt;/code&gt; output on its CDN&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After a minute or so, you’ll get a unique &lt;code&gt;.vercel.app&lt;/code&gt; URL to view your live site.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqpa0fou94udng7m9m6sk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqpa0fou94udng7m9m6sk.png" alt="Vercel deployment status showing life page" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 3&lt;/strong&gt;: &lt;em&gt;Vercel deployment success screen. Once the build completes, your site is live on a unique &lt;code&gt;.vercel.app&lt;/code&gt; URL.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up a Custom Domain (Optional but Awesome)
&lt;/h2&gt;

&lt;p&gt;If you want a branded URL:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the project dashboard, go to the &lt;strong&gt;Domains&lt;/strong&gt; tab&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;“Add”&lt;/strong&gt; to connect your custom domain&lt;/li&gt;
&lt;li&gt;Update your domain’s DNS to point to Vercel’s servers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HTTPS is auto-enabled with &lt;strong&gt;Let’s Encrypt&lt;/strong&gt; — no extra setup needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0b7qormcoha2i22g40t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0b7qormcoha2i22g40t.png" alt="Choosing a custom domain on Vercel" width="800" height="693"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 4&lt;/strong&gt;: &lt;em&gt;A quick look at the domain setup screen on Vercel.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Switched from GitHub Pages to Vercel
&lt;/h2&gt;

&lt;p&gt;GitHub Pages is great for simple projects, but I ran into issues like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Having to manually build and push the &lt;code&gt;dist/&lt;/code&gt; folder to a &lt;code&gt;gh-pages&lt;/code&gt; branch&lt;/li&gt;
&lt;li&gt;Problems with routing (e.g., missing &lt;code&gt;_redirects&lt;/code&gt; support)&lt;/li&gt;
&lt;li&gt;Extra configuration for Astro and Starlight projects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With &lt;strong&gt;Vercel&lt;/strong&gt;, all that friction disappeared.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips &amp;amp; Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;.vercel/&lt;/code&gt; to your &lt;code&gt;.gitignore&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use Vercel’s dashboard to securely manage environment variables&lt;/li&gt;
&lt;li&gt;Enable analytics (available on paid plans)&lt;/li&gt;
&lt;li&gt;👥 Working in a team? Preview deployments make collaboration smooth and safe.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Deploying with Vercel made the process incredibly smooth. From GitHub integration to instant deployment and live previews, it handled everything I needed for a modern static site — no DevOps headaches.&lt;/p&gt;

&lt;p&gt;Whether you’re building documentation, blogs, or full sites using &lt;strong&gt;Astro&lt;/strong&gt;, &lt;strong&gt;Next.js&lt;/strong&gt;, or even plain &lt;strong&gt;HTML&lt;/strong&gt; — &lt;strong&gt;Vercel&lt;/strong&gt; is a solid choice.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Want to see the live site?&lt;/strong&gt; Check it out here: &lt;a href="https://vue-js-nine-rouge.vercel.app/" rel="noopener noreferrer"&gt;https://vue-js-nine-rouge.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💻 &lt;strong&gt;Project repository:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/Mike-4-prog/vue.js" rel="noopener noreferrer"&gt;https://github.com/Mike-4-prog/vue.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Note: The documentation is still a work in progress, with more pages and improvements coming soon!)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have you tried deploying with Vercel? Got stuck with GitHub Pages too?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;💬 Feel free to drop your questions or share your experience in the comments!&lt;/p&gt;

</description>
      <category>vercel</category>
      <category>astro</category>
      <category>webdev</category>
      <category>deployment</category>
    </item>
  </channel>
</rss>
