diff --git a/.grok/skills/generate-blog-cover/SKILL.md b/.grok/skills/generate-blog-cover/SKILL.md new file mode 100644 index 000000000..42952442b --- /dev/null +++ b/.grok/skills/generate-blog-cover/SKILL.md @@ -0,0 +1,95 @@ +--- +name: generate-blog-cover +description: > + Generate consistent ultra-simple hand-drawn line art cover images for new agentgateway blog posts, using the exact same basic clean sketch style (one single large symbolic element, simple black ink outlines, almost no shading, flat or no colors, very basic icons, generous whitespace, 16:9). + Trigger when user says "generate blog cover", "new blog image", "create cover for [title]", "blog cover in same style", "hand drawn blog image", or when adding a new post to content/blog/. + Also use for /generate-blog-cover or when editing a new .md in content/blog/. +--- +# Generate Blog Cover Image + +This skill ensures every new blog post gets a cover image in the **exact same ultra-simple hand-drawn line art style** (basic black ink outlines, one main symbolic element, very minimal, clean and sparse like a quick sketch) as the other covers in `static/img/blog/covers/`. + +## When to use this skill +- User is creating a new blog post (new .md in content/blog/) +- User asks to generate / create / make a cover image for a blog +- User says "same style as the others", "hand drawn blog cover", "more simple", "ultra simple", "basic line art cover", "make the images more simple" +- After writing the frontmatter/title/description of a new post + +## Step-by-step process + +1. **Identify the blog post** + - If the user mentions a specific file or title, read the Markdown file from `content/blog/`. + - Extract: + - `title` + - `description` (or first paragraph of content for summary) + - `category` + - The filename slug (e.g. `2026-06-04-my-new-post` from `2026-06-04-my-new-post.md`) + - If no file exists yet, ask the user for the title + short description + desired category (Release, Tutorial, Announcement, etc.) and proposed filename slug (use `date-slug` format). + +2. **Craft the Central Element** + - Analyze the title and description. + - Come up with **one or two very simple symbolic elements** that represent the post (keep it extremely minimal — no people, no busy scenes, no small text/icons). + - Examples of good simple elements (study existing covers for consistency): + - Release / version: "a simple gateway arch" + - Tutorial / how-to: "a simple path or arrow icon" + - Security / auth: "a simple lock icon" + - Migration: "a simple arrow" + - Integration / observability: "a simple line or wave" + - Multi / federation: "a simple gateway with small icons" + - Architecture / kill switch: "a simple arch with a power symbol" + - Anniversary / milestone: "a simple '1' badge" + - Make the description short and iconic. + +3. **Build the full image_gen prompt** + Use this **exact base prompt** every time (do not deviate from the style): + + ``` + Ultra simple hand-drawn line art illustration for a professional developer blog cover. Very clean black ink outlines, almost no shading or hatching, extremely basic iconic symbols only (no people or characters). Light off-white background. Extremely minimalist composition with one single bold symbolic element. Warm orange, deep purple, blue accents if needed. Lots of negative space, calm, clean and professional. Deliberately basic and hand-drawn like a simple sketch, not detailed or cartoonish. 16:9 wide. Central element: [YOUR TAILORED SIMPLE ELEMENT HERE] + ``` + +4. **Generate the image** + - Call the `image_gen` tool with: + - `prompt`: the full prompt from step 3 + - `aspect_ratio`: "16:9" + - Note the output path (it will be something like `.../images/XX.jpg` in the current session). + +5. **Place the image correctly** + - Copy the generated image to: + ``` + static/img/blog/covers/.jpg + ``` + (Replace `` with the exact base name of the .md file, e.g. `2026-06-04-my-post`). + - Use `cp` or equivalent via terminal. Overwrite if needed. + - Confirm the file now exists at that location. + +6. **Verify and suggest next steps** + - Tell the user the image was created. + - Optionally run a quick Hugo build check or just remind them to refresh localhost:1313/blog/ + - If the post doesn't have `coverImage` in frontmatter, suggest they don't need it (the lp-list shortcode auto-falls back to `/img/blog/covers/.jpg`). + - Offer to generate a new one with tweaks if the central element wasn't perfect. + +## Style rules (never break these) +- Always exactly 1 main element (or 2 at absolute most) — keep it extremely basic and iconic. +- Very clean black ink outlines, almost zero shading or hatching. +- Extremely basic symbolic icons only — no people, no characters, no details. +- Light off-white background. +- Brand palette: warm orange, deep purple, blue accents (used sparingly). +- Lots of negative space — calm, clean, professional and very sparse. +- No text in the image. +- No photorealism, no cartoonish features, no AI polish, no heavy details — deliberately ultra-simple hand-drawn line sketch style. +- 16:9 (aspect-video) for the 3-column grid. + +## Existing examples for reference (read these if needed for inspiration on composition and central elements — they are now in the ultra-simple line art style) +- `static/img/blog/covers/2026-06-04-agentgateway-joins-aaif.jpg` +- `static/img/blog/covers/2026-05-11-agentgateway-v1.2.0.jpg` +- `static/img/blog/covers/2026-02-21-kill-switch.jpg` +- Any other in `static/img/blog/covers/` + +Note: All covers have been (or will be) regenerated in the new ultra-simple hand-drawn line art style while keeping the same central symbolic ideas for consistency. + +## Helper commands (use via run_terminal_command when needed) +- List existing covers: `ls static/img/blog/covers/*.jpg | sort` +- Get slug from a new file: `basename content/blog/NEW-FILE.md .md` +- Copy after generation: `cp /path/to/generated/XX.jpg static/img/blog/covers/.jpg` + +This skill guarantees visual consistency across all blog covers. diff --git a/assets/css/custom.css b/assets/css/custom.css index 410b1be85..1ed235207 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -395,3 +395,77 @@ h6 { /* Avoid breaking inside short blocks; don't force headings to next page */ blockquote, figure, img { break-inside: avoid; } } + +/* ===== Landing page hero background (for consistency on blog too) ===== */ +:root { + --hp-accent: #8A3FFC; + --hp-accent-soft: rgba(138,63,252,0.12); + --hp-accent-glow: rgba(138,63,252,0.35); + --hp-accent-deep: #6E29E0; + --hp-text-1: #0B0E18; + --hp-text-2: #151927; + --hp-text-3: #4A5068; + --hp-text-4: #5A6078; + --hp-text-5: #9AA0B5; + --hp-bg-0: #FFFFFF; + --hp-bg-1: #F6F7FB; + --hp-bg-2: #EDEEF7; + --hp-border: rgba(15,19,35,0.08); + --hp-border-2: rgba(15,19,35,0.14); + --hp-font-h: 'Figtree', system-ui, sans-serif; + --hp-font-b: 'DM Sans', system-ui, sans-serif; + --hp-font-m: 'DM Mono', ui-monospace, monospace; +} + +.dark { + --hp-accent: #A06EFF; + --hp-accent-soft: rgba(160,110,255,0.14); + --hp-accent-glow: rgba(160,110,255,0.40); + --hp-accent-deep: #B48CFF; + --hp-text-1: #F0F1F5; + --hp-text-2: #E4E5EB; + --hp-text-3: #B0B4C4; + --hp-text-4: #8A8FA5; + --hp-text-5: #5E6378; + --hp-bg-0: #0B0E18; + --hp-bg-1: #111422; + --hp-bg-2: #181C2E; + --hp-border: rgba(255,255,255,0.08); + --hp-border-2: rgba(255,255,255,0.14); +} + +.hp-hero-bg { + position: absolute; inset: 0; z-index: -1; + background: linear-gradient(180deg, var(--hp-bg-0) 0%, var(--hp-bg-1) 60%, var(--hp-bg-2) 100%); +} + +.hp-hero-grid-pattern { + position: absolute; inset: 0; + background-image: linear-gradient(rgba(15,19,35,0.04) 1px, transparent 1px), + linear-gradient(90deg, rgba(15,19,35,0.04) 1px, transparent 1px); + background-size: 56px 56px; + mask-image: radial-gradient(ellipse 100% 90% at 50% 30%, black 30%, transparent 75%); + -webkit-mask-image: radial-gradient(ellipse 100% 90% at 50% 30%, black 30%, transparent 75%); +} + +.hp-hero-blob { + position: absolute; border-radius: 50%; opacity: 0.5; pointer-events: none; +} + +.hp-hero-blob-1 { + width: 600px; height: 600px; top: -200px; right: -120px; + background: radial-gradient(circle, rgba(138,63,252,0.28), transparent 65%); +} + +.hp-hero-blob-2 { + width: 480px; height: 480px; top: 40%; left: -160px; + background: radial-gradient(circle, rgba(32,183,243,0.18), transparent 65%); +} + +.dark .hp-hero-grid-pattern { + background-image: linear-gradient(rgba(255,255,255,0.04) 1px, transparent 1px), + linear-gradient(90deg, rgba(255,255,255,0.04) 1px, transparent 1px); +} + +.dark .hp-hero-blob-1 { opacity: 0.3; } +.dark .hp-hero-blob-2 { opacity: 0.15; } diff --git a/content/blog/2025-07-14-a2a-mcp-gateway-api-0-6-release.md b/content/blog/2025-07-14-a2a-mcp-gateway-api-0-6-release.md index e321fb66b..72f8829d7 100644 --- a/content/blog/2025-07-14-a2a-mcp-gateway-api-0-6-release.md +++ b/content/blog/2025-07-14-a2a-mcp-gateway-api-0-6-release.md @@ -3,6 +3,8 @@ title: Announcing A2A, MCP, and Kubernetes Gateway API support toc: false publishDate: 2025-07-14T00:00:00-00:00 author: Christian Posta, John Howard +category: "Release" +description: "agentgateway adds deep native support for A2A and MCP, full Kubernetes Gateway API (all core routes + policies), advanced rate limiting/auth, OpenTelemetry, and unified LLM routing in a Rust-based AI-native gateway." --- > Today, we're excited to share the next major milestone: agentgateway is now a full-featured, AI-native gateway that combines deep MCP and A2A protocol awareness, robust traffic policy controls, inference gateway support, Kubernetes Gateway API support, and unified access to major LLMs, all purpose-built with Rust for real-world agentic systems. diff --git a/content/blog/2025-08-12-mcp-authorization-following-the-spec.md b/content/blog/2025-08-12-mcp-authorization-following-the-spec.md index 8df92f22d..4192438be 100644 --- a/content/blog/2025-08-12-mcp-authorization-following-the-spec.md +++ b/content/blog/2025-08-12-mcp-authorization-following-the-spec.md @@ -3,6 +3,8 @@ title: MCP Authorization the Easy Way toc: false publishDate: 2025-08-12T00:00:00-00:00 author: Christian Posta, Rinor Maloku +category: "Security" +description: "Handle the updated MCP Authorization spec (OAuth, Protected Resource Metadata, WWW-Authenticate) at the gateway so your MCP servers don't have to. agentgateway makes spec-compliant auth simple via config." --- diff --git a/content/blog/2025-08-25-solo-contributes-agentgateway-to-lf.md b/content/blog/2025-08-25-solo-contributes-agentgateway-to-lf.md index e280b7347..19ec0eba2 100644 --- a/content/blog/2025-08-25-solo-contributes-agentgateway-to-lf.md +++ b/content/blog/2025-08-25-solo-contributes-agentgateway-to-lf.md @@ -3,6 +3,8 @@ title: Solo.io Contributes agentgateway to Linux Foundation to Make AI Agents Mo toc: false publishDate: 2025-08-25T00:00:00-00:00 author: Lin Sun +category: "Announcement" +description: "Solo.io contributes agentgateway to the Linux Foundation. A purpose-built, Rust-based AI-native gateway for A2A, MCP, LLM, and API traffic — delivering security, observability, and governance for the agentic era." --- Today at Open Source Summit Europe, the [Linux Foundation accepted **agentgateway**](https://www.linuxfoundation.org/press/linux-foundation-welcomes-agentgateway-project-to-accelerate-ai-agent-adoption-while-maintaining-security-observability-and-governance), a new open source AI-native project created by [Solo.io](https://www.solo.io/). [Agentgateway](https://agentgateway.dev/) provides drop-in security, observability, and governance for agent-to-agent and agent-to-tool communication and supports leading interoperable protocols, including [Agent2Agent (A2A)](https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/) and [Model Context Protocol (MCP)](https://modelcontextprotocol.io/docs/getting-started/intro). diff --git a/content/blog/2025-11-02-rate-limit-quota-llm.md b/content/blog/2025-11-02-rate-limit-quota-llm.md index 2b976dd57..c9e0d76a8 100644 --- a/content/blog/2025-11-02-rate-limit-quota-llm.md +++ b/content/blog/2025-11-02-rate-limit-quota-llm.md @@ -3,6 +3,8 @@ title: Provider Rate Limiting is Not Enough for Enterprise LLM Usage toc: false publishDate: 2025-11-02T00:00:00-00:00 author: Christian Posta, Michael Levan +category: "LLM" +description: "LLM providers offer only coarse RPM/TPM limits at org/project level. Enterprises need fine-grained, configurable quotas, cost controls, and per-consumer rate limiting — which agentgateway delivers at the gateway layer." --- Hosted LLM providers like OpenAI and Anthropic have [rate limiting capabilities](https://platform.openai.com/docs/guides/rate-limits) centered around requests per minute (RPM) and tokens per minute (TPM). These are specified at the "organization" level and "project" level. API keys are associated with an organization or project, and each call is subject to token or rate limit restrictions. The actual limits are set by the provider, not you. They will depend on what tier you pay for, but generally not directly configurable. For example: diff --git a/content/blog/2026-01-26-enterprise-mcp-sso.md b/content/blog/2026-01-26-enterprise-mcp-sso.md index 5646e9385..543b1b5a7 100644 --- a/content/blog/2026-01-26-enterprise-mcp-sso.md +++ b/content/blog/2026-01-26-enterprise-mcp-sso.md @@ -3,6 +3,8 @@ title: Enterprise MCP SSO With Microsoft Entra and Agentgateway toc: false publishDate: 2026-01-26T00:00:00-00:00 author: Christian Posta +category: "Tutorial" +description: "Secure internal MCP servers and clients with enterprise SSO using Microsoft Entra ID (OIDC) through agentgateway. Apply identity, policy, and access controls consistently for AI agents and desktop MCP clients without browser flows." --- diff --git a/content/blog/2026-01-30-adds-nginx-migration-support.md b/content/blog/2026-01-30-adds-nginx-migration-support.md index ea7b791e3..4e1141a79 100644 --- a/content/blog/2026-01-30-adds-nginx-migration-support.md +++ b/content/blog/2026-01-30-adds-nginx-migration-support.md @@ -3,6 +3,8 @@ title: agentgateway adds support for migrating from ingress-nginx toc: false publishDate: 2026-01-30T00:00:00-00:00 author: Eitan Suez +category: "Release" +description: "With ingress-nginx retiring, easily migrate your Ingress resources to Kubernetes Gateway API + agentgateway using the updated ingress2gateway tool. Get production-grade AI-aware traffic management without rewriting routes." --- ## ingress-nginx retirement diff --git a/content/blog/2026-02-09-getting-started-agentgateway-llm-routing.md b/content/blog/2026-02-09-getting-started-agentgateway-llm-routing.md index d42677838..70e01b4a8 100644 --- a/content/blog/2026-02-09-getting-started-agentgateway-llm-routing.md +++ b/content/blog/2026-02-09-getting-started-agentgateway-llm-routing.md @@ -2,7 +2,9 @@ title: Getting started with Multi-LLM provider routing toc: false publishDate: 2026-02-09 -author: Sebastian +author: "Sebastian Maniak" +category: "Tutorial" +description: "Route to multiple LLM providers (OpenAI, Anthropic, xAI, etc) through one agentgateway using Kubernetes Gateway API. Step-by-step on Kind with HTTPRoutes and AgentgatewayBackend for unified, observable LLM access." --- # How to: Building Agentgateway to support Multi-LLM providers. diff --git a/content/blog/2026-02-11-your-first-AI-route.md b/content/blog/2026-02-11-your-first-AI-route.md index dd06dbca3..684a808d1 100644 --- a/content/blog/2026-02-11-your-first-AI-route.md +++ b/content/blog/2026-02-11-your-first-AI-route.md @@ -2,6 +2,7 @@ title: "Your First AI Route: Connecting to OpenAI with AgentGateway" publishDate: 2026-02-11 author: "Sebastian Maniak" +category: "Tutorial" description: "Step-by-step guide to connecting open source AgentGateway to OpenAI API with cost tracking, monitoring, security best practices, and production-ready configurations." --- diff --git a/content/blog/2026-02-13-Happy-V-Day.md b/content/blog/2026-02-13-Happy-V-Day.md index 35506140c..ad8a1886f 100644 --- a/content/blog/2026-02-13-Happy-V-Day.md +++ b/content/blog/2026-02-13-Happy-V-Day.md @@ -2,6 +2,7 @@ title: "Explore Gateway API and Agentgateway with ExtAuth Match 💕 Game" publishDate: 2026-02-13 author: "Lin Sun & Yuval Kohavi" +category: "Community" description: "Let’s have some fun and share love while learning Kubernetes Gateway API and agentgateway with the ExtAuth Match game." --- {{< reuse-image src="img/blog/happy-v-day/V-card.png" width="600px" >}} diff --git a/content/blog/2026-02-17-agentgateway-langfuse-integration.md b/content/blog/2026-02-17-agentgateway-langfuse-integration.md index bc5c6c09a..f9a07f713 100644 --- a/content/blog/2026-02-17-agentgateway-langfuse-integration.md +++ b/content/blog/2026-02-17-agentgateway-langfuse-integration.md @@ -2,6 +2,7 @@ title: "Open Source LLM Observability: Tracing AI Calls with AgentGateway and Langfuse" publishDate: 2026-02-18 author: "Sebastian Maniak" +category: "Tutorial" description: "How to automatically capture, monitor, and debug every LLM API call flowing through Solo AgentGateway using Langfuse — with zero application code changes." --- diff --git a/content/blog/2026-02-19-connect-any-ide-githhub-mcp-agentgateway.md b/content/blog/2026-02-19-connect-any-ide-githhub-mcp-agentgateway.md index acd3dbaee..36f19281e 100644 --- a/content/blog/2026-02-19-connect-any-ide-githhub-mcp-agentgateway.md +++ b/content/blog/2026-02-19-connect-any-ide-githhub-mcp-agentgateway.md @@ -2,6 +2,7 @@ title: "Connect Any IDE to GitHub MCP Server Through AgentGateway" publishDate: 2026-02-19 author: "Sebastian Maniak" +category: "Tutorial" description: "Route MCP traffic from Cursor, VS Code, Windsurf, Claude Code, and OpenCode to GitHub's remote MCP server through Solo AgentGateway — with config examples for every IDE." --- diff --git a/content/blog/2026-02-20-mcp-multiplexing-tool-access-agentgateway.md b/content/blog/2026-02-20-mcp-multiplexing-tool-access-agentgateway.md index 290331e58..917dd6b13 100644 --- a/content/blog/2026-02-20-mcp-multiplexing-tool-access-agentgateway.md +++ b/content/blog/2026-02-20-mcp-multiplexing-tool-access-agentgateway.md @@ -2,6 +2,7 @@ title: "MCP Multiplexing with AgentGateway" publishDate: 2026-02-20 author: "Sebastian Maniak" +category: "Tutorial" description: "Federate multiple MCP servers behind a single endpoint with AgentGateway OSS so clients connect once and see all available tools." --- diff --git a/content/blog/2026-02-21-kill-switch.md b/content/blog/2026-02-21-kill-switch.md index 901aac4c6..f7ad97bf6 100644 --- a/content/blog/2026-02-21-kill-switch.md +++ b/content/blog/2026-02-21-kill-switch.md @@ -2,6 +2,7 @@ title: "Multi-Agent OpenClaw Architecture with a Kill Switch: Why Every AI Agent Needs a Gateway" publishDate: 2026-02-21 author: "Sebastian Maniak" +category: "Architecture" description: "A multi-agent system where a coordinator routes tasks to specialist sub-agents — and every LLM call and MCP tool invocation passes through agentgateway running in Kubernetes for cost control, rate limiting, governance, and a kill switch." --- diff --git a/content/blog/2026-03-12-agentgateway-v1.0.md b/content/blog/2026-03-12-agentgateway-v1.0.md index 3e81c107e..f7ebce90b 100644 --- a/content/blog/2026-03-12-agentgateway-v1.0.md +++ b/content/blog/2026-03-12-agentgateway-v1.0.md @@ -2,6 +2,7 @@ title: "A Year In: agentgateway Hits v1.0.0 — and the Pieces Are Converging" publishDate: 2026-03-16 author: "Sebastian Maniak" +category: "Release" description: "A Year In: agentgateway Hits v1.0.0 — and the Pieces Are Converging" --- diff --git a/content/blog/2026-03-19-agentgateway-llm-d-gaie-inference-serving.md b/content/blog/2026-03-19-agentgateway-llm-d-gaie-inference-serving.md index 366a03055..2a3852b46 100644 --- a/content/blog/2026-03-19-agentgateway-llm-d-gaie-inference-serving.md +++ b/content/blog/2026-03-19-agentgateway-llm-d-gaie-inference-serving.md @@ -3,6 +3,7 @@ title: "Inference Serving with Superpowers" toc: false publishDate: 2026-03-23 author: "Daneyon Hansen" +category: "LLM" description: "Agentgateway, llm-d, and Gateway API Inference Extension combine gateway policy, smart inference scheduling, and Kubernetes-native standards for production quality inference serving." --- diff --git a/content/blog/2026-03-25-agentgateway-one-year-anniversary.md b/content/blog/2026-03-25-agentgateway-one-year-anniversary.md index d2e480a96..ca3742a9c 100644 --- a/content/blog/2026-03-25-agentgateway-one-year-anniversary.md +++ b/content/blog/2026-03-25-agentgateway-one-year-anniversary.md @@ -2,6 +2,7 @@ title: "Happy 1st birthday, agentgateway!" publishDate: 2026-03-25 author: "Lin Sun" +category: "Community" description: "Agentgateway celebrates 1 million pulls, 175+ contributors, and 2,000+ stars in 1 year" --- diff --git a/content/blog/2026-05-11-agentgateway-v1.2.0.md b/content/blog/2026-05-11-agentgateway-v1.2.0.md index 7056d52a4..75e813201 100644 --- a/content/blog/2026-05-11-agentgateway-v1.2.0.md +++ b/content/blog/2026-05-11-agentgateway-v1.2.0.md @@ -2,6 +2,7 @@ title: "Agentgateway v1.2.0: we're shipping like the agents are watching" publishDate: 2026-05-14 author: "Sebastian Maniak" +category: "Release" description: "Agentgateway v1.2.0 lands route delegation, backend external auth, conditional policies with CEL, the new agctl debugger, and a stack of LLM gateway upgrades." --- diff --git a/content/blog/2026-06-04-agentgateway-joins-aaif.md b/content/blog/2026-06-04-agentgateway-joins-aaif.md index 3d4b6add8..0512ba7a9 100644 --- a/content/blog/2026-06-04-agentgateway-joins-aaif.md +++ b/content/blog/2026-06-04-agentgateway-joins-aaif.md @@ -2,6 +2,7 @@ title: "agentgateway Joins AAIF as an Open Gateway for Agentic AI Infrastructure" publishDate: 2026-06-04 author: "Agentic AI Foundation" +category: "Announcement" description: "agentgateway joins the Agentic AI Foundation as the fourth hosted initiative under the Linux Foundation — an open, high-performance gateway for MCP, A2A, LLM inference, and conventional API traffic." toc: false --- diff --git a/content/blog/2026-06-04-designing-agentgateway-unified-gateway.md b/content/blog/2026-06-04-designing-agentgateway-unified-gateway.md index 04b2092f2..843a25758 100644 --- a/content/blog/2026-06-04-designing-agentgateway-unified-gateway.md +++ b/content/blog/2026-06-04-designing-agentgateway-unified-gateway.md @@ -2,6 +2,7 @@ title: "Designing agentgateway: A Unified High-Performance Gateway for AI and API Traffic" publishDate: 2026-06-04 author: "Lin Sun" +category: "Engineering" description: "Why we built agentgateway as a unified control plane and data plane for HTTP, gRPC, MCP, A2A, and LLM traffic — the design decisions, the choice of Rust, the performance numbers, and the road to AAIF." toc: false --- diff --git a/content/blog/_index.md b/content/blog/_index.md index 7ebb8beb7..cc1d456d2 100644 --- a/content/blog/_index.md +++ b/content/blog/_index.md @@ -4,11 +4,20 @@ toc: false description: "" --- -
-
-

- Agentgateway Blog +
+ +
+
+
+
+ +
+

+ Blog

+

+ Latest updates, deep dives, and announcements from the agentgateway community. +

diff --git a/layouts/_partials/blog-avatar.html b/layouts/_partials/blog-avatar.html new file mode 100644 index 000000000..873972047 --- /dev/null +++ b/layouts/_partials/blog-avatar.html @@ -0,0 +1,29 @@ +{{- /* + Partial: blog-avatar + Renders a round author avatar. Uses a real photo from + /img/blog/authors/.(png|jpg) when present, otherwise a colored + initials circle. For multi-author bylines, the first author is used. + + Params (dict): + name - author string (required), e.g. "Lin Sun" or "Christian Posta, John Howard" + size - Tailwind size classes (optional), default "h-9 w-9 text-xs" +*/ -}} +{{- $name := .name | default "" -}} +{{- $size := .size | default "h-9 w-9 text-xs" -}} +{{- $primary := trim (index (split (replaceRE "&" "," $name) ",") 0) " " -}} +{{- $slug := anchorize $primary -}} +{{- $png := printf "/img/blog/authors/%s.png" $slug -}} +{{- $jpg := printf "/img/blog/authors/%s.jpg" $slug -}} +{{- $photo := "" -}} +{{- if fileExists (printf "static%s" $png) }}{{ $photo = $png }}{{ end -}} +{{- if and (not $photo) (fileExists (printf "static%s" $jpg)) }}{{ $photo = $jpg }}{{ end -}} +{{- if $photo -}} + {{ $primary }} +{{- else -}} + {{- $words := split $primary " " -}} + {{- $initials := "" -}} + {{- range first 2 $words }}{{ $initials = printf "%s%s" $initials (substr . 0 1) }}{{ end -}} + {{- $palette := slice "bg-indigo-500" "bg-orange-500" "bg-emerald-500" "bg-rose-500" "bg-sky-500" "bg-violet-500" "bg-amber-500" "bg-teal-500" -}} + {{- $color := index $palette (mod (len $primary) (len $palette)) -}} + {{ $initials }} +{{- end -}} diff --git a/layouts/_partials/blog-category.html b/layouts/_partials/blog-category.html new file mode 100644 index 000000000..42cab60f3 --- /dev/null +++ b/layouts/_partials/blog-category.html @@ -0,0 +1,57 @@ +{{- /* + Partial: blog-category + Renders a small colored category pill. + + Usage: + {{ partial "blog-category.html" .Params.category }} → auto (respects global dark mode) + {{ partial "blog-category.html" (dict "category" .Params.category "variant" "light") }} → always light colors (for light illustration areas) + {{ partial "blog-category.html" (dict "category" . "variant" "dark") }} → always dark/subtle colors (for dark hero areas) + + The "light" variant is used on blog listing cards because the image area is intentionally light cream/beige + even in dark mode. "dark" or "auto" is used in the post hero. +*/ -}} +{{- $cat := .category | default . | default "Blog" -}} +{{- $variant := .variant | default "auto" -}} + +{{- $lightColors := dict + "Release" "bg-orange-200 text-orange-800" + "Tutorial" "bg-indigo-200 text-indigo-800" + "Announcement" "bg-violet-200 text-violet-800" + "Community" "bg-emerald-200 text-emerald-800" + "Engineering" "bg-sky-200 text-sky-800" + "Security" "bg-rose-200 text-rose-800" + "LLM" "bg-amber-200 text-amber-800" + "Architecture" "bg-teal-200 text-teal-800" +-}} + +{{- $darkColors := dict + "Release" "bg-orange-500/15 text-orange-300" + "Tutorial" "bg-indigo-500/15 text-indigo-300" + "Announcement" "bg-violet-500/15 text-violet-300" + "Community" "bg-emerald-500/15 text-emerald-300" + "Engineering" "bg-sky-500/15 text-sky-300" + "Security" "bg-rose-500/15 text-rose-300" + "LLM" "bg-amber-500/15 text-amber-300" + "Architecture" "bg-teal-500/15 text-teal-300" +-}} + +{{- $cls := "" -}} +{{- if eq $variant "light" -}} + {{- $cls = index $lightColors $cat | default "bg-gray-100 text-gray-700" -}} +{{- else if eq $variant "dark" -}} + {{- $cls = index $darkColors $cat | default "bg-gray-700/30 text-gray-300" -}} +{{- else -}} + {{- /* auto: original behavior with dark: variants for global theme */ -}} + {{- $cls = index (dict + "Release" "bg-orange-100 text-orange-700 dark:bg-orange-500/15 dark:text-orange-300" + "Tutorial" "bg-indigo-100 text-indigo-700 dark:bg-indigo-500/15 dark:text-indigo-300" + "Announcement" "bg-violet-100 text-violet-700 dark:bg-violet-500/15 dark:text-violet-300" + "Community" "bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300" + "Engineering" "bg-sky-100 text-sky-700 dark:bg-sky-500/15 dark:text-sky-300" + "Security" "bg-rose-100 text-rose-700 dark:bg-rose-500/15 dark:text-rose-300" + "LLM" "bg-amber-100 text-amber-700 dark:bg-amber-500/15 dark:text-amber-300" + "Architecture" "bg-teal-100 text-teal-700 dark:bg-teal-500/15 dark:text-teal-300" + ) $cat | default "bg-gray-100 text-gray-700 dark:bg-gray-700/30 dark:text-gray-300" -}} +{{- end -}} + +{{ $cat }} diff --git a/layouts/_shortcodes/lp-list.html b/layouts/_shortcodes/lp-list.html index c4f11800e..ed5cb6620 100644 --- a/layouts/_shortcodes/lp-list.html +++ b/layouts/_shortcodes/lp-list.html @@ -1,46 +1,61 @@ {{- /* Shortcode: lp-list - Renders a list of child pages as styled article cards showing the date, author, title, summary, and a "Read full article" link. + Responsive 3-column card grid for the blog listing. + Cards with cover images, category pill overlaid, title, excerpt, and meta. + Uses simpler minimalist covers. Tailwind utilities; dark mode supported. - Parameters: - (none -- iterates over child pages of the current page) + Prefers .Params.description for excerpt (good for listing), falls back to .Summary. + Cover image: uses the page's `coverImage` param when set, otherwise falls + back to /img/blog/covers/.jpg (or .png). Example: {{< lp-list >}} */ -}} -
-
- {{ range $.Page.Pages }} -
- - -
- - - {{ .Params.Author }} +{{ $pages := $.Page.Pages }} +
+ +
+ {{ range $pages }} + {{ $cover := .Params.coverImage }} + {{ if not $cover }} + {{ $base := .File.ContentBaseName }} + {{ $pngPath := printf "/img/blog/covers/%s.png" $base }} + {{ $jpgPath := printf "/img/blog/covers/%s.jpg" $base }} + {{ if fileExists (printf "static%s" $jpgPath) }} + {{ $cover = $jpgPath }} + {{ else if fileExists (printf "static%s" $pngPath) }} + {{ $cover = $pngPath }} + {{ else }} + {{ $cover = $pngPath }} + {{ end }} + {{ end }} + {{ $excerpt := .Params.description | default .Summary | plainify | truncate 140 "…" }} + +
+ Cover illustration for {{ .LinkTitle }} +
{{ partial "blog-category.html" (dict "category" .Params.category "variant" "light") }}
- - -

- + +
+

{{ .LinkTitle }} - -

- - -
- {{ .Summary }} +

+

{{ $excerpt }}

+ +
+ {{ partial "blog-avatar.html" (dict "name" .Params.Author "size" "h-6 w-6 text-[10px]") }} + {{ .Params.Author }} + · + + · + {{ .ReadingTime }} min +
- - - - Read full article - - - - -
+ {{ end }}
diff --git a/layouts/blog/list.html b/layouts/blog/list.html index 679ed006c..58e8ee267 100644 --- a/layouts/blog/list.html +++ b/layouts/blog/list.html @@ -1,4 +1,7 @@ {{ define "main" }} +
+{{ partial "announcement.html" .}} +
{{ partial "sidebar.html" (dict "context" . "disableSidebar" true) }}
diff --git a/layouts/blog/single.html b/layouts/blog/single.html index 8f4d8ec51..a7beab115 100644 --- a/layouts/blog/single.html +++ b/layouts/blog/single.html @@ -1,25 +1,38 @@ {{ define "main" }} +
+{{ partial "announcement.html" .}} +
{{ partial "sidebar.html" (dict "context" . "disableSidebar" true) }}
{{ partial "nav.html" . }} -
-
-

+
+ +
+
+
+
+ +
+ {{ with $.Page.Params.category }} +
{{ partial "blog-category.html" (dict "category" . "variant" "auto") }}
+ {{ end }} +

{{ $.Page.Params.Title }}

{{ with $.Page.Params.Description }} -

{{ . }}

+

{{ . }}

{{ end }} -
- {{ $.Page.Params.Author }} - - - {{ with $.Page.ReadingTime }} - - {{ . }} min read - {{ end }} +
+ {{ partial "blog-avatar.html" (dict "name" $.Page.Params.Author "size" "h-10 w-10 text-sm") }} +
+ {{ $.Page.Params.Author }} + + + {{ with $.Page.ReadingTime }} {{ . }} min read{{ end }} + +
@@ -27,6 +40,26 @@

Back to blog + {{ $cover := .Params.coverImage }} + {{ if not $cover }} + {{ $base := .File.ContentBaseName }} + {{ $pngPath := printf "/img/blog/covers/%s.png" $base }} + {{ $jpgPath := printf "/img/blog/covers/%s.jpg" $base }} + {{ if fileExists (printf "static%s" $jpgPath) }} + {{ $cover = $jpgPath }} + {{ else if fileExists (printf "static%s" $pngPath) }} + {{ $cover = $pngPath }} + {{ else }} + {{ $cover = $pngPath }} + {{ end }} + {{ end }} + {{ if fileExists (printf "static%s" $cover) }} + Cover illustration for {{ .Params.Title }} + {{ end }}
- ✨ agentgateway has joined the Agentic AI Foundation (AAIF) — Learn more + ✨ agentgateway has joined the Agentic AI Foundation (AAIF) — Learn more · @agentgateway
diff --git a/layouts/partials/homepage-content.html b/layouts/partials/homepage-content.html index 9cb783794..87cdcdf19 100644 --- a/layouts/partials/homepage-content.html +++ b/layouts/partials/homepage-content.html @@ -1041,7 +1041,6 @@

Getting started

- @@ -1051,26 +1050,15 @@

Getting started

# Install the agentgateway binary
$ curl -sL https://agentgateway.dev/install | bash
 
-
# Run with a config file
+
# Download sample config
+
$ curl -sL https://raw.githubusercontent.com/agentgateway/agentgateway/main/examples/basic/config.yaml -o config.yaml
+
 
+
# Run with the config
$ agentgateway -f config.yaml
 
# INFO agentgateway: Listening on 0.0.0.0:3000
# INFO agentgateway: Admin UI at http://localhost:15000/ui/
-
-
# yaml-language-server: $schema=https://agentgateway.dev/schema/config
-
binds:
-
- port: 3000
-
listeners:
-
- routes:
-
- policies:
-
cors:
-
allowOrigins: ["*"]
-
allowHeaders: [content-type, cache-control]
-
a2a: {}
-
backends:
-
- host: localhost:9999
-
# Install Gateway API CRDs
$ kubectl apply --server-side --force-conflicts \
@@ -1080,14 +1068,14 @@

Getting started

$ helm upgrade -i agentgateway-crds \
oci://cr.agentgateway.dev/charts/agentgateway-crds \
--create-namespace --namespace agentgateway-system \
-
--version v1.1.0 \
+
--version v1.2.1 \
--set controller.image.pullPolicy=Always
 
# Install agentgateway via Helm
$ helm upgrade -i agentgateway \
oci://cr.agentgateway.dev/charts/agentgateway \
--namespace agentgateway-system \
-
--version v1.1.0 \
+
--version v1.2.1 \
--set controller.image.pullPolicy=Always \
--set controller.extraEnv.KGW_ENABLE_GATEWAY_API_EXPERIMENTAL_FEATURES=true \
--wait
diff --git a/layouts/partials/nav.html b/layouts/partials/nav.html index aeb3503cc..fbbf1cf67 100644 --- a/layouts/partials/nav.html +++ b/layouts/partials/nav.html @@ -278,7 +278,7 @@ {{- /* Determine if we're on the landing page or docs */ -}} -{{- $isLandingPage := eq .RelPermalink "/" -}} +{{- $isLandingPage := or (eq .RelPermalink "/") (hasPrefix .RelPermalink "/blog") -}} {{- $isDocsPage := false -}} {{- if .RelPermalink -}} {{- $path := .RelPermalink -}} diff --git a/scripts/add_blog_categories.py b/scripts/add_blog_categories.py new file mode 100644 index 000000000..df41beaeb --- /dev/null +++ b/scripts/add_blog_categories.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +"""One-off: add a `category` field to blog post frontmatter (idempotent).""" +import re +from pathlib import Path + +ROOT = Path(__file__).resolve().parent.parent +BLOG = ROOT / "content" / "blog" + +CATEGORY = { + "2025-07-14-a2a-mcp-gateway-api-0-6-release": "Release", + "2025-08-12-mcp-authorization-following-the-spec": "Security", + "2025-08-25-solo-contributes-agentgateway-to-lf": "Announcement", + "2025-11-02-rate-limit-quota-llm": "LLM", + "2026-01-26-enterprise-mcp-sso": "Tutorial", + "2026-01-30-adds-nginx-migration-support": "Release", + "2026-02-09-getting-started-agentgateway-llm-routing": "Tutorial", + "2026-02-11-your-first-AI-route": "Tutorial", + "2026-02-13-Happy-V-Day": "Community", + "2026-02-17-agentgateway-langfuse-integration": "Tutorial", + "2026-02-19-connect-any-ide-githhub-mcp-agentgateway": "Tutorial", + "2026-02-20-mcp-multiplexing-tool-access-agentgateway": "Tutorial", + "2026-02-21-kill-switch": "Architecture", + "2026-03-12-agentgateway-v1.0": "Release", + "2026-03-19-agentgateway-llm-d-gaie-inference-serving": "LLM", + "2026-03-25-agentgateway-one-year-anniversary": "Community", + "2026-05-11-agentgateway-v1.2.0": "Release", + "2026-06-04-agentgateway-joins-aaif": "Announcement", + "2026-06-04-designing-agentgateway-unified-gateway": "Engineering", +} + + +def main(): + changed = 0 + for slug, cat in CATEGORY.items(): + path = BLOG / f"{slug}.md" + if not path.exists(): + print(f" missing: {slug}") + continue + text = path.read_text(encoding="utf-8") + if not text.startswith("---"): + print(f" no frontmatter: {slug}") + continue + end = text.find("\n---", 3) + block = text[3:end] + if re.search(r'^category:', block, re.M): + print(f" skip (has category): {slug}") + continue + # insert category right after the author line, else at top of block + lines = block.splitlines() + out, inserted = [], False + for line in lines: + out.append(line) + if not inserted and line.startswith("author:"): + out.append(f'category: "{cat}"') + inserted = True + if not inserted: + out.insert(1, f'category: "{cat}"') + new_block = "\n".join(out) + path.write_text("---" + new_block + text[end:], encoding="utf-8") + print(f" + {slug}: {cat}") + changed += 1 + print(f"\nUpdated {changed} post(s).") + + +if __name__ == "__main__": + main() diff --git a/scripts/gen_blog_covers.py b/scripts/gen_blog_covers.py new file mode 100644 index 000000000..f89690b20 --- /dev/null +++ b/scripts/gen_blog_covers.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python3 +""" +Generate comic-book style cover images for blog posts using OpenAI gpt-image-1. + +For each post in content/blog/*.md it builds a prompt from the title + +description + a snippet of the body, then calls the OpenAI images "edits" +endpoint passing the agentgateway logo as a reference image so the real brand +mark is rendered into the scene. Output PNGs land in +static/img/blog/covers/.png. + +Usage: + OPENAI_API_KEY=... python3 scripts/gen_blog_covers.py # all posts, skip existing + python3 scripts/gen_blog_covers.py --force # regenerate everything + python3 scripts/gen_blog_covers.py [ ...] # only these posts + python3 scripts/gen_blog_covers.py --limit 1 # validate on one post + +No third-party deps beyond `requests` (stdlib + requests only). +""" +import argparse +import base64 +import os +import re +import sys +from pathlib import Path + +import requests + +ROOT = Path(__file__).resolve().parent.parent +BLOG_DIR = ROOT / "content" / "blog" +OUT_DIR = ROOT / "static" / "img" / "blog" / "covers" +LOGO_PNG = ROOT / "assets" / "img" / "logo-agentgateway-transparent.png" + +API_URL = "https://api.openai.com/v1/images/edits" +MODEL = "gpt-image-1" +SIZE = "1024x1024" +QUALITY = "medium" + +# Normalize inconsistent author frontmatter -> canonical display name. +AUTHOR_CANON = { + "sebastian": "Sebastian Maniak", + "sebastian maniak": "Sebastian Maniak", + "lin sun": "Lin Sun", + "christian posta": "Christian Posta", + "daneyon hansen": "Daneyon Hansen", + "eitan suez": "Eitan Suez", + "agentic ai foundation": "Agentic AI Foundation", +} + + +def canon_author(raw: str) -> str: + """Return the primary, canonicalized author name.""" + primary = re.split(r"[,&]", raw)[0].strip() + return AUTHOR_CANON.get(primary.lower(), primary) + + +def parse_frontmatter(text: str): + """Return (frontmatter_dict, body) for a Hugo markdown file.""" + fm = {} + body = text + if text.startswith("---"): + end = text.find("\n---", 3) + if end != -1: + block = text[3:end] + body = text[end + 4:] + for line in block.splitlines(): + m = re.match(r'^(\w+):\s*(.*)$', line) + if m: + key, val = m.group(1), m.group(2).strip() + val = val.strip('"').strip("'") + fm[key] = val + return fm, body + + +def body_snippet(body: str, limit: int = 600) -> str: + """First few sentences of prose, stripped of markdown noise.""" + lines = [] + for line in body.splitlines(): + s = line.strip() + if not s or s.startswith(("#", ">", "-", "*", "|", "```", "{{", "<")): + continue + lines.append(s) + if sum(len(x) for x in lines) > limit: + break + snippet = " ".join(lines) + snippet = re.sub(r"\[([^\]]+)\]\([^)]+\)", r"\1", snippet) # md links -> text + snippet = re.sub(r"[*_`]", "", snippet) + return snippet[:limit] + + +def build_prompt(title: str, desc: str, author: str, body: str) -> str: + topic = desc or body_snippet(body) + return f"""A modern flat editorial comic-book illustration for a tech blog cover, square format. + +STYLE: clean bold vector line art, limited brand palette of vivid orange (#E9622E), +deep indigo/purple (#4F46E5) and slate gray on a light off-white background with +a subtle halftone-dot texture. Confident comic-book ink outlines, friendly and +energetic, professional tech-editorial look (similar to a developer-platform +illustration). Flat shading, no photorealism. + +SCENE: visually represent this article in a metaphorical, conceptual way - +title: "{title}" +about: {topic} +Show a clean technical metaphor (gateways, routing arrows, connected services, +cloud/Kubernetes, AI agents and tools as friendly characters) that fits the topic. +Include a friendly professional engineer character as the focal figure. + +BRANDING: integrate the agentgateway logo shown in the provided reference image +as a small, crisp brand mark in one corner. Keep the logo's real shape and colors. + +TEXT: do NOT add paragraphs of text or captions; at most the single word +"agentgateway" near the logo. Avoid gibberish text. Keep it clean. +""" + + +def collect_posts(only_slugs): + posts = [] + for path in sorted(BLOG_DIR.glob("*.md")): + slug = path.stem + if slug == "_index": + continue + if only_slugs and slug not in only_slugs: + continue + text = path.read_text(encoding="utf-8") + fm, body = parse_frontmatter(text) + title = fm.get("title", slug) + if not title or title == "Blog": + continue + posts.append({ + "slug": slug, + "path": path, + "title": title, + "desc": fm.get("description", ""), + "author": canon_author(fm.get("author", "")), + "body": body, + "has_cover": "coverImage" in fm, + }) + return posts + + +def generate(post, api_key) -> bool: + prompt = build_prompt(post["title"], post["desc"], post["author"], post["body"]) + out_path = OUT_DIR / f"{post['slug']}.png" + print(f" -> generating {post['slug']} (author: {post['author']})") + with open(LOGO_PNG, "rb") as logo_f: + resp = requests.post( + API_URL, + headers={"Authorization": f"Bearer {api_key}"}, + data={"model": MODEL, "size": SIZE, "quality": QUALITY, "prompt": prompt}, + files={"image[]": ("logo.png", logo_f, "image/png")}, + timeout=300, + ) + if resp.status_code != 200: + print(f" !! API error {resp.status_code}: {resp.text[:500]}", file=sys.stderr) + return False + data = resp.json() + b64 = data["data"][0]["b64_json"] + out_path.write_bytes(base64.b64decode(b64)) + print(f" ok {out_path.relative_to(ROOT)}") + return True + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("slugs", nargs="*", help="only generate these post slugs") + ap.add_argument("--force", action="store_true", help="regenerate even if PNG exists") + ap.add_argument("--limit", type=int, default=0, help="stop after N images") + args = ap.parse_args() + + api_key = os.environ.get("OPENAI_API_KEY") + if not api_key: + sys.exit("OPENAI_API_KEY is not set") + if not LOGO_PNG.exists(): + sys.exit(f"logo not found: {LOGO_PNG}") + OUT_DIR.mkdir(parents=True, exist_ok=True) + + posts = collect_posts(set(args.slugs)) + done = 0 + for post in posts: + out_path = OUT_DIR / f"{post['slug']}.png" + if out_path.exists() and not args.force: + print(f" skip {post['slug']} (cover exists)") + continue + if generate(post, api_key): + done += 1 + if args.limit and done >= args.limit: + break + print(f"\nGenerated {done} cover(s) into {OUT_DIR.relative_to(ROOT)}") + + +if __name__ == "__main__": + main() diff --git a/static/img/blog/covers/2025-07-14-a2a-mcp-gateway-api-0-6-release.jpg b/static/img/blog/covers/2025-07-14-a2a-mcp-gateway-api-0-6-release.jpg new file mode 100644 index 000000000..c238916b2 Binary files /dev/null and b/static/img/blog/covers/2025-07-14-a2a-mcp-gateway-api-0-6-release.jpg differ diff --git a/static/img/blog/covers/2025-07-14-a2a-mcp-gateway-api-0-6-release.png b/static/img/blog/covers/2025-07-14-a2a-mcp-gateway-api-0-6-release.png new file mode 100644 index 000000000..a7321bf1f Binary files /dev/null and b/static/img/blog/covers/2025-07-14-a2a-mcp-gateway-api-0-6-release.png differ diff --git a/static/img/blog/covers/2025-08-12-mcp-authorization-following-the-spec.jpg b/static/img/blog/covers/2025-08-12-mcp-authorization-following-the-spec.jpg new file mode 100644 index 000000000..1d6fa5437 Binary files /dev/null and b/static/img/blog/covers/2025-08-12-mcp-authorization-following-the-spec.jpg differ diff --git a/static/img/blog/covers/2025-08-12-mcp-authorization-following-the-spec.png b/static/img/blog/covers/2025-08-12-mcp-authorization-following-the-spec.png new file mode 100644 index 000000000..4625e4319 Binary files /dev/null and b/static/img/blog/covers/2025-08-12-mcp-authorization-following-the-spec.png differ diff --git a/static/img/blog/covers/2025-08-25-solo-contributes-agentgateway-to-lf.jpg b/static/img/blog/covers/2025-08-25-solo-contributes-agentgateway-to-lf.jpg new file mode 100644 index 000000000..07db75150 Binary files /dev/null and b/static/img/blog/covers/2025-08-25-solo-contributes-agentgateway-to-lf.jpg differ diff --git a/static/img/blog/covers/2025-08-25-solo-contributes-agentgateway-to-lf.png b/static/img/blog/covers/2025-08-25-solo-contributes-agentgateway-to-lf.png new file mode 100644 index 000000000..4d24791d2 Binary files /dev/null and b/static/img/blog/covers/2025-08-25-solo-contributes-agentgateway-to-lf.png differ diff --git a/static/img/blog/covers/2025-11-02-rate-limit-quota-llm.jpg b/static/img/blog/covers/2025-11-02-rate-limit-quota-llm.jpg new file mode 100644 index 000000000..fba1cc6af Binary files /dev/null and b/static/img/blog/covers/2025-11-02-rate-limit-quota-llm.jpg differ diff --git a/static/img/blog/covers/2025-11-02-rate-limit-quota-llm.png b/static/img/blog/covers/2025-11-02-rate-limit-quota-llm.png new file mode 100644 index 000000000..6e2cf5854 Binary files /dev/null and b/static/img/blog/covers/2025-11-02-rate-limit-quota-llm.png differ diff --git a/static/img/blog/covers/2026-01-26-enterprise-mcp-sso.jpg b/static/img/blog/covers/2026-01-26-enterprise-mcp-sso.jpg new file mode 100644 index 000000000..9889a1bd9 Binary files /dev/null and b/static/img/blog/covers/2026-01-26-enterprise-mcp-sso.jpg differ diff --git a/static/img/blog/covers/2026-01-26-enterprise-mcp-sso.png b/static/img/blog/covers/2026-01-26-enterprise-mcp-sso.png new file mode 100644 index 000000000..9187d3916 Binary files /dev/null and b/static/img/blog/covers/2026-01-26-enterprise-mcp-sso.png differ diff --git a/static/img/blog/covers/2026-01-30-adds-nginx-migration-support.jpg b/static/img/blog/covers/2026-01-30-adds-nginx-migration-support.jpg new file mode 100644 index 000000000..3e4cf3939 Binary files /dev/null and b/static/img/blog/covers/2026-01-30-adds-nginx-migration-support.jpg differ diff --git a/static/img/blog/covers/2026-01-30-adds-nginx-migration-support.png b/static/img/blog/covers/2026-01-30-adds-nginx-migration-support.png new file mode 100644 index 000000000..9b4595125 Binary files /dev/null and b/static/img/blog/covers/2026-01-30-adds-nginx-migration-support.png differ diff --git a/static/img/blog/covers/2026-02-09-getting-started-agentgateway-llm-routing.jpg b/static/img/blog/covers/2026-02-09-getting-started-agentgateway-llm-routing.jpg new file mode 100644 index 000000000..a960145a5 Binary files /dev/null and b/static/img/blog/covers/2026-02-09-getting-started-agentgateway-llm-routing.jpg differ diff --git a/static/img/blog/covers/2026-02-09-getting-started-agentgateway-llm-routing.png b/static/img/blog/covers/2026-02-09-getting-started-agentgateway-llm-routing.png new file mode 100644 index 000000000..3f42bf743 Binary files /dev/null and b/static/img/blog/covers/2026-02-09-getting-started-agentgateway-llm-routing.png differ diff --git a/static/img/blog/covers/2026-02-11-your-first-AI-route.jpg b/static/img/blog/covers/2026-02-11-your-first-AI-route.jpg new file mode 100644 index 000000000..4197dd3c6 Binary files /dev/null and b/static/img/blog/covers/2026-02-11-your-first-AI-route.jpg differ diff --git a/static/img/blog/covers/2026-02-11-your-first-AI-route.png b/static/img/blog/covers/2026-02-11-your-first-AI-route.png new file mode 100644 index 000000000..2d0a5e86d Binary files /dev/null and b/static/img/blog/covers/2026-02-11-your-first-AI-route.png differ diff --git a/static/img/blog/covers/2026-02-13-Happy-V-Day.jpg b/static/img/blog/covers/2026-02-13-Happy-V-Day.jpg new file mode 100644 index 000000000..ac780ae25 Binary files /dev/null and b/static/img/blog/covers/2026-02-13-Happy-V-Day.jpg differ diff --git a/static/img/blog/covers/2026-02-13-Happy-V-Day.png b/static/img/blog/covers/2026-02-13-Happy-V-Day.png new file mode 100644 index 000000000..dd2934c6e Binary files /dev/null and b/static/img/blog/covers/2026-02-13-Happy-V-Day.png differ diff --git a/static/img/blog/covers/2026-02-17-agentgateway-langfuse-integration.jpg b/static/img/blog/covers/2026-02-17-agentgateway-langfuse-integration.jpg new file mode 100644 index 000000000..dedcc76bf Binary files /dev/null and b/static/img/blog/covers/2026-02-17-agentgateway-langfuse-integration.jpg differ diff --git a/static/img/blog/covers/2026-02-17-agentgateway-langfuse-integration.png b/static/img/blog/covers/2026-02-17-agentgateway-langfuse-integration.png new file mode 100644 index 000000000..6b3bd2819 Binary files /dev/null and b/static/img/blog/covers/2026-02-17-agentgateway-langfuse-integration.png differ diff --git a/static/img/blog/covers/2026-02-19-connect-any-ide-githhub-mcp-agentgateway.jpg b/static/img/blog/covers/2026-02-19-connect-any-ide-githhub-mcp-agentgateway.jpg new file mode 100644 index 000000000..b2c62bfaf Binary files /dev/null and b/static/img/blog/covers/2026-02-19-connect-any-ide-githhub-mcp-agentgateway.jpg differ diff --git a/static/img/blog/covers/2026-02-19-connect-any-ide-githhub-mcp-agentgateway.png b/static/img/blog/covers/2026-02-19-connect-any-ide-githhub-mcp-agentgateway.png new file mode 100644 index 000000000..353cc84d1 Binary files /dev/null and b/static/img/blog/covers/2026-02-19-connect-any-ide-githhub-mcp-agentgateway.png differ diff --git a/static/img/blog/covers/2026-02-20-mcp-multiplexing-tool-access-agentgateway.jpg b/static/img/blog/covers/2026-02-20-mcp-multiplexing-tool-access-agentgateway.jpg new file mode 100644 index 000000000..e5c056319 Binary files /dev/null and b/static/img/blog/covers/2026-02-20-mcp-multiplexing-tool-access-agentgateway.jpg differ diff --git a/static/img/blog/covers/2026-02-20-mcp-multiplexing-tool-access-agentgateway.png b/static/img/blog/covers/2026-02-20-mcp-multiplexing-tool-access-agentgateway.png new file mode 100644 index 000000000..397edba08 Binary files /dev/null and b/static/img/blog/covers/2026-02-20-mcp-multiplexing-tool-access-agentgateway.png differ diff --git a/static/img/blog/covers/2026-02-21-kill-switch.jpg b/static/img/blog/covers/2026-02-21-kill-switch.jpg new file mode 100644 index 000000000..03767f56a Binary files /dev/null and b/static/img/blog/covers/2026-02-21-kill-switch.jpg differ diff --git a/static/img/blog/covers/2026-02-21-kill-switch.png b/static/img/blog/covers/2026-02-21-kill-switch.png new file mode 100644 index 000000000..97e0fe9f1 Binary files /dev/null and b/static/img/blog/covers/2026-02-21-kill-switch.png differ diff --git a/static/img/blog/covers/2026-03-12-agentgateway-v1.0.jpg b/static/img/blog/covers/2026-03-12-agentgateway-v1.0.jpg new file mode 100644 index 000000000..df4ec5714 Binary files /dev/null and b/static/img/blog/covers/2026-03-12-agentgateway-v1.0.jpg differ diff --git a/static/img/blog/covers/2026-03-12-agentgateway-v1.0.png b/static/img/blog/covers/2026-03-12-agentgateway-v1.0.png new file mode 100644 index 000000000..f11532522 Binary files /dev/null and b/static/img/blog/covers/2026-03-12-agentgateway-v1.0.png differ diff --git a/static/img/blog/covers/2026-03-19-agentgateway-llm-d-gaie-inference-serving.jpg b/static/img/blog/covers/2026-03-19-agentgateway-llm-d-gaie-inference-serving.jpg new file mode 100644 index 000000000..ef6438754 Binary files /dev/null and b/static/img/blog/covers/2026-03-19-agentgateway-llm-d-gaie-inference-serving.jpg differ diff --git a/static/img/blog/covers/2026-03-19-agentgateway-llm-d-gaie-inference-serving.png b/static/img/blog/covers/2026-03-19-agentgateway-llm-d-gaie-inference-serving.png new file mode 100644 index 000000000..29071c85e Binary files /dev/null and b/static/img/blog/covers/2026-03-19-agentgateway-llm-d-gaie-inference-serving.png differ diff --git a/static/img/blog/covers/2026-03-25-agentgateway-one-year-anniversary.jpg b/static/img/blog/covers/2026-03-25-agentgateway-one-year-anniversary.jpg new file mode 100644 index 000000000..589b67e65 Binary files /dev/null and b/static/img/blog/covers/2026-03-25-agentgateway-one-year-anniversary.jpg differ diff --git a/static/img/blog/covers/2026-03-25-agentgateway-one-year-anniversary.png b/static/img/blog/covers/2026-03-25-agentgateway-one-year-anniversary.png new file mode 100644 index 000000000..5956dfd09 Binary files /dev/null and b/static/img/blog/covers/2026-03-25-agentgateway-one-year-anniversary.png differ diff --git a/static/img/blog/covers/2026-05-11-agentgateway-v1.2.0.jpg b/static/img/blog/covers/2026-05-11-agentgateway-v1.2.0.jpg new file mode 100644 index 000000000..6572d95f6 Binary files /dev/null and b/static/img/blog/covers/2026-05-11-agentgateway-v1.2.0.jpg differ diff --git a/static/img/blog/covers/2026-05-11-agentgateway-v1.2.0.png b/static/img/blog/covers/2026-05-11-agentgateway-v1.2.0.png new file mode 100644 index 000000000..a96ba7e91 Binary files /dev/null and b/static/img/blog/covers/2026-05-11-agentgateway-v1.2.0.png differ diff --git a/static/img/blog/covers/2026-06-04-agentgateway-joins-aaif.jpg b/static/img/blog/covers/2026-06-04-agentgateway-joins-aaif.jpg new file mode 100644 index 000000000..270b2a5c3 Binary files /dev/null and b/static/img/blog/covers/2026-06-04-agentgateway-joins-aaif.jpg differ diff --git a/static/img/blog/covers/2026-06-04-agentgateway-joins-aaif.png b/static/img/blog/covers/2026-06-04-agentgateway-joins-aaif.png new file mode 100644 index 000000000..04b370f68 Binary files /dev/null and b/static/img/blog/covers/2026-06-04-agentgateway-joins-aaif.png differ diff --git a/static/img/blog/covers/2026-06-04-designing-agentgateway-unified-gateway.jpg b/static/img/blog/covers/2026-06-04-designing-agentgateway-unified-gateway.jpg new file mode 100644 index 000000000..01bd35af4 Binary files /dev/null and b/static/img/blog/covers/2026-06-04-designing-agentgateway-unified-gateway.jpg differ diff --git a/static/img/blog/covers/2026-06-04-designing-agentgateway-unified-gateway.png b/static/img/blog/covers/2026-06-04-designing-agentgateway-unified-gateway.png new file mode 100644 index 000000000..88b0d648a Binary files /dev/null and b/static/img/blog/covers/2026-06-04-designing-agentgateway-unified-gateway.png differ