diff --git a/documentation/blog/2025-12-28-goose-maintains-goose/index.md b/documentation/blog/2025-12-28-goose-maintains-goose/index.md index da14c9114f60..0831682a5ba2 100644 --- a/documentation/blog/2025-12-28-goose-maintains-goose/index.md +++ b/documentation/blog/2025-12-28-goose-maintains-goose/index.md @@ -4,6 +4,7 @@ description: Learn how an AI agent embedded in GitHub Actions helps maintainers authors: - rizel - tyler +image: /img/blog/goose-maintains-goose.png --- ![blog cover](goose-maintains-goose.png) diff --git a/documentation/blog/2026-01-04-how-i-taught-my-agent-my-design-taste/index.md b/documentation/blog/2026-01-04-how-i-taught-my-agent-my-design-taste/index.md index f4a023c1b315..02da8920415c 100644 --- a/documentation/blog/2026-01-04-how-i-taught-my-agent-my-design-taste/index.md +++ b/documentation/blog/2026-01-04-how-i-taught-my-agent-my-design-taste/index.md @@ -3,6 +3,7 @@ title: "How I Taught My Agent My Design Taste" description: "I used Agent Skills and recipes to automate execution so I could study taste, constraint design, feedback loops, and avoid AI smells." authors: - rizel +image: /img/blog/automate-taste.png --- ![blog cover](automate-taste.png) diff --git a/documentation/blog/2026-01-05-agentic-guardrails-and-controls/index.md b/documentation/blog/2026-01-05-agentic-guardrails-and-controls/index.md index 0c1b4e700ef9..5be8906d9f76 100644 --- a/documentation/blog/2026-01-05-agentic-guardrails-and-controls/index.md +++ b/documentation/blog/2026-01-05-agentic-guardrails-and-controls/index.md @@ -1,12 +1,13 @@ --- title: "Agent Guardrails and Controls: Applying the CORS Model to Agents" description: Applying the security model of CORS to Agentic technologies to address common attacks against tool calling. +image: /img/blog/agentic_guardrails_header.jpg authors: - clinton - alex --- -![blog cover](agentic_guardrails_header.jpg) +![blog cover](/img/blog/agentic_guardrails_header.jpg) In [our previous blog post](https://goose-docs.ai/blog/2025/03/31/securing-mcp/) we detailed the Model Context Protocol (MCP) system and discussed some security concerns and mitigations. As a brief recap, MCP provides agents with a means to accomplish tasks using defined tools; reducing the burden of using complex and varied APIs and integrations on the agent. diff --git a/documentation/blog/2026-01-06-mcp-apps/index.md b/documentation/blog/2026-01-06-mcp-apps/index.md index ed8e4fbd4356..526a06f85697 100644 --- a/documentation/blog/2026-01-06-mcp-apps/index.md +++ b/documentation/blog/2026-01-06-mcp-apps/index.md @@ -3,9 +3,10 @@ title: "goose Lands MCP Apps" description: "goose ships early support for the draft MCP Apps specification, aligning with the emerging standard for interactive UIs in MCP." authors: - aharvard +image: /img/blog/goose-lands-mcp-apps-header-image.png --- -![Retro 1980s hardware lab with three CRT monitors displaying "goose Lands MCP Apps" in glowing green text, with a small goose figurine on the desk](goose-lands-mcp-apps-header-image.png) +![Retro 1980s hardware lab with three CRT monitors displaying "goose Lands MCP Apps" in glowing green text, with a small goose figurine on the desk](/img/blog/goose-lands-mcp-apps-header-image.png) The MCP ecosystem is standardizing how servers deliver interactive UIs to hosts, and goose is an early adopter. Today we're shipping support for the draft MCP Apps specification ([SEP-1865](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx)), bringing goose in line with the emerging standard, as other hosts like Claude and ChatGPT move toward adoption. diff --git a/documentation/blog/2026-01-15-why-tool-descriptions-arent-enough/index.md b/documentation/blog/2026-01-15-why-tool-descriptions-arent-enough/index.md index 4961500ab70e..6bfcc8ce1ca7 100644 --- a/documentation/blog/2026-01-15-why-tool-descriptions-arent-enough/index.md +++ b/documentation/blog/2026-01-15-why-tool-descriptions-arent-enough/index.md @@ -1,10 +1,11 @@ --- title: "Why Tool Descriptions Aren’t Enough" description: "I thought better tool descriptions would solve everything. They didn’t. Here’s what finally made MCP sampling click for me." +image: /img/blog/tool-descriptions-banner.png authors: - ebony --- -![blog banner](blogbanner.png) +![blog banner](/img/blog/tool-descriptions-banner.png) The first question I had when I heard about MCP sampling was: diff --git a/documentation/blog/2026-01-20-goose-mobile-apps/index.md b/documentation/blog/2026-01-20-goose-mobile-apps/index.md index 699acc80f948..3b7c93ff9340 100644 --- a/documentation/blog/2026-01-20-goose-mobile-apps/index.md +++ b/documentation/blog/2026-01-20-goose-mobile-apps/index.md @@ -1,11 +1,12 @@ --- title: "goose mobile apps and agent clients" description: Consolidating agent apps for iOS and Android and ACP +image: /img/blog/goose-mobile-apps-banner.png authors: - mic --- -![goose mobile apps](goose-mobile-apps-banner.png) +![goose mobile apps](/img/blog/goose-mobile-apps-banner.png) In 2025 we did a fairly cutting edge take on whole device automation using Android (code name was gosling) which was an on-device agent that would take over your device (mic even used it to do some shopping - which he realized after some things arrived at his door that it had automatically purchased as the result of an email - hence the PoC/experimental label!) diff --git a/documentation/blog/2026-01-22-mcp-ui-to-mcp-apps/index.md b/documentation/blog/2026-01-22-mcp-ui-to-mcp-apps/index.md index 560e40c22a3a..d3069ac8b7f5 100644 --- a/documentation/blog/2026-01-22-mcp-ui-to-mcp-apps/index.md +++ b/documentation/blog/2026-01-22-mcp-ui-to-mcp-apps/index.md @@ -1,11 +1,12 @@ --- title: "From MCP-UI to MCP Apps: Evolving Interactive Agent UIs" description: "I migrated a real MCP-UI server to MCP Apps. Here’s what actually changed, what broke, and why this shift matters." +image: /img/blog/mcp-ui-to-apps-blogbanner.png authors: - ebony --- -![blog banner](blogbanner.png) +![blog banner](/img/blog/mcp-ui-to-apps-blogbanner.png) MCP-UI is fun. It’s scrappy. It’s early. And like I said in my last post, there’s something genuinely addictive about building this close to the edges of an ecosystem while everything is still taking shape. diff --git a/documentation/blog/2026-01-30-5-tips-building-mcp-apps/index.md b/documentation/blog/2026-01-30-5-tips-building-mcp-apps/index.md index 8512e91ac21d..00c0b87eeff0 100644 --- a/documentation/blog/2026-01-30-5-tips-building-mcp-apps/index.md +++ b/documentation/blog/2026-01-30-5-tips-building-mcp-apps/index.md @@ -1,12 +1,13 @@ --- title: "5 Tips for Building MCP Apps That Work" description: "5 expert tips on building better MCP Apps for your AI agents" +image: /img/blog/mcp-apps-tips-blogbanner.png authors: - rizel - matt --- -![Level Up Your MCP Apps - goose and MCP Jam](blogbanner.png) +![Level Up Your MCP Apps - goose and MCP Jam](/img/blog/mcp-apps-tips-blogbanner.png) [MCP Apps](https://modelcontextprotocol.io/docs/extensions/apps) allow you to render interactive UI directly inside any agent supporting the Model Context Protocol. Instead of a wall of text, your agent can now provide a functional chart, a checkout form, or a video player. This bridges the gap in agentic workflows: clicking a button is often clearer than describing the action you hope an agent executes. diff --git a/documentation/blog/2026-02-06-8-things-you-didnt-know-about-code-mode/index.md b/documentation/blog/2026-02-06-8-things-you-didnt-know-about-code-mode/index.md index ff4c91c7c85e..21e571a7c4bd 100644 --- a/documentation/blog/2026-02-06-8-things-you-didnt-know-about-code-mode/index.md +++ b/documentation/blog/2026-02-06-8-things-you-didnt-know-about-code-mode/index.md @@ -1,11 +1,12 @@ --- title: "8 Things You Didn't Know About Code Mode" description: Discover how Code mode reduces context rot and token usage in AI agents making them more efficient for long running sessions. +image: /img/blog/code-mode-header-image.png authors: - rizel --- -![blog cover](header-image.png) +![blog cover](/img/blog/code-mode-header-image.png) Agents fundamentally changed how we program. They enable developers to move faster by disintermediating the traditional development workflow. This means less time switching between specialized tools and fewer dependencies on other teams. Now that agents can execute complicated tasks, developers face a new challenge: using them effectively over long sessions. diff --git a/documentation/blog/2026-02-06-rp-why-skill/index.md b/documentation/blog/2026-02-06-rp-why-skill/index.md index 879448a20f8f..76cf3eb92779 100644 --- a/documentation/blog/2026-02-06-rp-why-skill/index.md +++ b/documentation/blog/2026-02-06-rp-why-skill/index.md @@ -2,11 +2,12 @@ title: "Level Up Your AI Game with rp-why" description: "A goose skill that measures the cognitive complexity of your AI collaboration using the Gas Town × DOK framework." date: 2026-02-06 +image: /img/blog/rp-why-banner.png authors: - dakota --- -![rp-why skill banner](rp-why-banner.png) +![rp-why skill banner](/img/blog/rp-why-banner.png) ## What is rp-why? diff --git a/documentation/blog/2026-02-06-rpi-openclaw-alternative/index.md b/documentation/blog/2026-02-06-rpi-openclaw-alternative/index.md index a8f36fe4bdd7..13cc7cbd258f 100644 --- a/documentation/blog/2026-02-06-rpi-openclaw-alternative/index.md +++ b/documentation/blog/2026-02-06-rpi-openclaw-alternative/index.md @@ -1,11 +1,12 @@ --- title: "How I Used RPI to Build an OpenClaw Alternative" description: "Learn how I built a minimal, personal AI agent using goose and the RPI method." +image: /img/blog/rpi-openclaw-blogbanner.png authors: - rizel --- -![How I Used RPI to Build an OpenClaw Alternative](blogbanner.png) +![How I Used RPI to Build an OpenClaw Alternative](/img/blog/rpi-openclaw-blogbanner.png) Everyone on Tech Twitter has been buying Mac Minis, so they could run a local agentic tool called [OpenClaw](https://openclaw.ai/). OpenClaw is a messaging-based AI assistant that connects to platforms such as Discord and Telegram allowing you to interact with an AI agent through DMs or @mentions. Under the hood, it uses an agent called Pi to execute tasks, browse the web, write code, and more. diff --git a/documentation/blog/2026-02-07-context-engineering/index.md b/documentation/blog/2026-02-07-context-engineering/index.md index 638823a19946..11e0bfe897a5 100644 --- a/documentation/blog/2026-02-07-context-engineering/index.md +++ b/documentation/blog/2026-02-07-context-engineering/index.md @@ -1,11 +1,12 @@ --- title: "One Shot Prompting is Dead" description: "Practical steps and mental models for building context engineered workflows instead of clever prompts." +image: /img/blog/context-engineering-blogbanner.png authors: - ebony --- -![One shot prompting is dead](blogbanner.png) +![One shot prompting is dead](/img/blog/context-engineering-blogbanner.png) I attended one shot prompting’s funeral. diff --git a/documentation/blog/2026-02-19-gastown-explained-goosetown/index.md b/documentation/blog/2026-02-19-gastown-explained-goosetown/index.md index 517e58a43356..cf5c1bc36b59 100644 --- a/documentation/blog/2026-02-19-gastown-explained-goosetown/index.md +++ b/documentation/blog/2026-02-19-gastown-explained-goosetown/index.md @@ -1,12 +1,13 @@ --- title: "Gas Town Explained: How to Use Goosetown for Parallel Agentic Engineering" description: "Learn how Gas Town and Goosetown lead the industrial coding revolution by teaching AI agents to work together in a team. This beginner guide explains the infrastructure we're using to move from talking to one AI to coordinating many agents at once." +image: /img/blog/goosetown.png authors: - rizel - tyler --- -![Goosetown](goosetown.png) +![Goosetown](/img/blog/goosetown.png) On New Year's Day 2026, while many were recovering from the night before, a different kind of hangover took hold of every AI-pilled, chronically online software engineer. Steve Yegge published a new blog post: "[Welcome to Gas Town](https://steve-yegge.medium.com/welcome-to-gas-town-4f25ee16dd04)." Some walked away inspired to finally use their agents optimally; others were just plain confused. If you're like me, you felt a bit of both. diff --git a/documentation/blog/2026-02-23-goose-v1-25-0/index.md b/documentation/blog/2026-02-23-goose-v1-25-0/index.md index 538eb0663b2f..f12f44ddd889 100644 --- a/documentation/blog/2026-02-23-goose-v1-25-0/index.md +++ b/documentation/blog/2026-02-23-goose-v1-25-0/index.md @@ -3,9 +3,10 @@ title: "goose v1.25.0: Sandboxed, Streamlined, and More Secure" description: "goose v1.25.0 brings macOS sandboxing, a unified summon extension, rich MCP app UIs, agentic CLI upgrades, and SLSA build provenance." authors: - debbie +image: /img/blog/goose-v1-25-0.png --- -![Banner image for the goose v1.25.0 release](banner.png) +![Banner image for the goose v1.25.0 release](/img/blog/goose-v1-25-0.png) goose v1.25.0 is here, and it's one of our most significant releases yet. This version brings macOS sandboxing for enhanced security, a major architectural simplification with the unified summon extension, rich UI rendering for MCP apps, and a wave of improvements to agentic CLI providers. Whether you're running goose Desktop or the CLI, there's something in this release for you. diff --git a/documentation/blog/2026-02-24-goose-grant-goose-in-a-pond/index.md b/documentation/blog/2026-02-24-goose-grant-goose-in-a-pond/index.md index 0b9194395f18..646e2389d7a2 100644 --- a/documentation/blog/2026-02-24-goose-grant-goose-in-a-pond/index.md +++ b/documentation/blog/2026-02-24-goose-grant-goose-in-a-pond/index.md @@ -3,9 +3,10 @@ title: "Grant Winner: Goose In A Pond" description: "Introducing a privacy-first, local AI home assistant powered by Goose on edge hardware." authors: - angie +image: /img/blog/goose-grant-goose-in-a-pond.png --- -![blog banner](banner.png) +![blog banner](/img/blog/goose-grant-goose-in-a-pond.png) We launched the [goose grant program](/grants/) awarding $100K grants for developers building the future of agentic AI. We're looking for ambitious, open source projects that push goose into new territory, and today, We're thrilled to introduce one of our grant recipients: **Goose In A Pond**, a project that's taking goose off the desktop and into your home. diff --git a/documentation/blog/2026-02-25-order-lunch-with-goose/index.md b/documentation/blog/2026-02-25-order-lunch-with-goose/index.md index 74bedc365c56..c66cf95cf6a6 100644 --- a/documentation/blog/2026-02-25-order-lunch-with-goose/index.md +++ b/documentation/blog/2026-02-25-order-lunch-with-goose/index.md @@ -3,9 +3,10 @@ title: "Order Lunch Without Leaving Your AI Agent" description: "Use the Neighborhood extension in goose to discover nearby restaurants, browse interactive menus, and place a takeout order, all from a simple chat prompt." authors: - debbie +image: /img/blog/lunch-with-goose.png --- -![Ba'al Falafel salads menu in goose showing Couscous Salad, Red Cabbage Salad, and Beets Apple Salad with photos and prices](banner.png) +![Ba'al Falafel salads menu in goose showing Couscous Salad, Red Cabbage Salad, and Beets Apple Salad with photos and prices](/img/blog/lunch-with-goose.png) If you're anything like me, deciding what to eat for lunch is harder than it should be. Now add dietary restrictions on top of that (I'm coeliac so have to eat gluten-free) and suddenly finding a restaurant becomes a whole research project. Searching menus, cross-referencing reviews, checking if that one sandwich actually has gluten in it... it's exhausting. diff --git a/documentation/blog/2026-03-17-webmcp-for-beginners/index.md b/documentation/blog/2026-03-17-webmcp-for-beginners/index.md index 7ff4ad26bf62..79b596354c48 100644 --- a/documentation/blog/2026-03-17-webmcp-for-beginners/index.md +++ b/documentation/blog/2026-03-17-webmcp-for-beginners/index.md @@ -3,9 +3,10 @@ title: "WebMCP for Beginners" description: "WebMCP lets websites expose structured actions that AI agents can call directly. This guide explains how it works, how it differs from MCP and browser automation, and how to build your own WebMCP-enabled site." authors: - rizel +image: /img/blog/webmcp-for-beginners.png --- -![blog cover](webmcp-for-beginners.png) +![blog cover](/img/blog/webmcp-for-beginners.png) Raise your hand if you thought WebMCP was just an MCP server. Guilty as charged. I did too. It turns out it's a W3C standard that uses similar concepts to MCP. Here's what it actually is. diff --git a/documentation/blog/2026-03-31-adversary-mode/index.md b/documentation/blog/2026-03-31-adversary-mode/index.md index ed43c73b16e7..2bb171be6c43 100644 --- a/documentation/blog/2026-03-31-adversary-mode/index.md +++ b/documentation/blog/2026-03-31-adversary-mode/index.md @@ -1,11 +1,12 @@ --- title: "Adversary Agent: using a hidden agent to keep the main agent safe" description: "Introducing adversary mode — an independent agent reviewer that silently watches the main agent to keep it away from danger." +image: /img/blog/adversary-mode.png authors: - mic --- -![blog cover](adversary-mode.png) +![blog cover](/img/blog/adversary-mode.png) One of the desires of goose (well for some of us) was to avoid the constant asking for permissions, delegating all the decisions to end users in an attempt to keep agent execution of tools safe. Sometimes that gets pretty noisy and annoying and ends up being less secure when you get tired of reading and approving. diff --git a/documentation/blog/2026-04-08-goose-acp-and-new-tui/index.md b/documentation/blog/2026-04-08-goose-acp-and-new-tui/index.md index 54a0a1fe04b8..ef0d54f313e7 100644 --- a/documentation/blog/2026-04-08-goose-acp-and-new-tui/index.md +++ b/documentation/blog/2026-04-08-goose-acp-and-new-tui/index.md @@ -3,11 +3,13 @@ title: "goose 2.0 beta - new architecture and clients" description: "We're shipping a new TUI, rewriting the desktop app in Tauri, and unifying everything under ACP." authors: - alexhancock +featured: true +image: /img/blog/goose-2-blog-cover.jpg --- # goose 2.0 beta - new architecture and clients -![blog cover](goose-2-blog-cover.jpg) +![blog cover](/img/blog/goose-2-blog-cover.jpg) goose started life in the terminal. The earliest versions were a Python CLI that ran the agent in-process — you typed a message, the model responded, tools executed, and everything happened in a single loop. That simplicity was a strength: it meant anyone with a terminal could start using goose immediately, no app to install, no server to run. diff --git a/documentation/blog/2026-04-08-how-to-break-up-with-your-agent/index.md b/documentation/blog/2026-04-08-how-to-break-up-with-your-agent/index.md index b892e74378af..0c42dc200514 100644 --- a/documentation/blog/2026-04-08-how-to-break-up-with-your-agent/index.md +++ b/documentation/blog/2026-04-08-how-to-break-up-with-your-agent/index.md @@ -3,9 +3,10 @@ title: "How to Break Up with Your Agent" description: "ACP lets you keep your favorite editor but swap the AI agent, or keep your agent but use it from any editor. Here's what actually works today in Goose." authors: - codefromthecrypt +image: /img/blog/how-to-break-up-with-your-agent.png --- -![Editors connect to Goose via ACP, and Goose connects to multiple agents](header.png) +![Editors connect to Goose via ACP, and Goose connects to multiple agents](/img/blog/how-to-break-up-with-your-agent.png) The biggest shift in developer tooling over the last year wasn't the rise of agents. It was the rise of agent subscriptions. We stopped choosing LLM platforms and counting tokens. We started choosing an agent CLI and paying a flat monthly fee. diff --git a/documentation/docusaurus.config.ts b/documentation/docusaurus.config.ts index 85492c4c1b2c..30590d0c0f00 100644 --- a/documentation/docusaurus.config.ts +++ b/documentation/docusaurus.config.ts @@ -75,6 +75,7 @@ const config: Config = { onInlineAuthors: "warn", onUntruncatedBlogPosts: "warn", blogSidebarCount: "ALL", + postsPerPage: 22, }, theme: { customCss: [ diff --git a/documentation/src/theme/BlogListPage/StructuredData/index.tsx b/documentation/src/theme/BlogListPage/StructuredData/index.tsx new file mode 100644 index 000000000000..6ae32bf4bee5 --- /dev/null +++ b/documentation/src/theme/BlogListPage/StructuredData/index.tsx @@ -0,0 +1,19 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import React from 'react'; +import Head from '@docusaurus/Head'; +import {useBlogListPageStructuredData} from '@docusaurus/plugin-content-blog/client'; +export default function BlogListPageStructuredData(props) { + const structuredData = useBlogListPageStructuredData(props); + return ( + + + + ); +} diff --git a/documentation/src/theme/BlogListPage/index.tsx b/documentation/src/theme/BlogListPage/index.tsx new file mode 100644 index 000000000000..bac24983f758 --- /dev/null +++ b/documentation/src/theme/BlogListPage/index.tsx @@ -0,0 +1,185 @@ +import React, {type ReactNode} from 'react'; +import clsx from 'clsx'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import useBaseUrl from '@docusaurus/useBaseUrl'; +import { + PageMetadata, + HtmlClassNameProvider, + ThemeClassNames, +} from '@docusaurus/theme-common'; +import BlogLayout from '@theme/BlogLayout'; +import BlogListPaginator from '@theme/BlogListPaginator'; +import SearchMetadata from '@theme/SearchMetadata'; +import type {Props} from '@theme/BlogListPage'; +import BlogListPageStructuredData from '@theme/BlogListPage/StructuredData'; +import styles from './styles.module.css'; + +function BlogListPageMetadata(props: Props): ReactNode { + const {metadata} = props; + const { + siteConfig: {title: siteTitle}, + } = useDocusaurusContext(); + const {blogDescription, blogTitle, permalink} = metadata; + const isBlogOnlyMode = permalink === '/'; + const title = isBlogOnlyMode ? siteTitle : blogTitle; + return ( + <> + + + + ); +} + +const getAuthorName = (author: any): string => + typeof author === 'string' ? author : (author.name || author.key || author); + +function AuthorDisplay({ authors }: { authors: any[] }) { + if (!authors?.length) return null; + + const authorsToDisplay = authors.slice(0, 3); + const hasMore = authors.length > 3; + const hasResolvedAuthors = authorsToDisplay.some(author => + typeof author === 'object' && (author.imageURL || author.image_url) + ); + + if (hasResolvedAuthors) { + return ( +
+ {authorsToDisplay.map((author, index) => ( +
+ {(author.imageURL || author.image_url) && ( + {getAuthorName(author)} + )} + {getAuthorName(author)} +
+ ))} + {hasMore && +{authors.length - 3} more} +
+ ); + } + + const authorNames = authorsToDisplay.map(getAuthorName); + const displayText = authorNames.join(', ') + (hasMore ? `, +${authors.length - 3} more` : ''); + + return ( +
+ {displayText} +
+ ); +} + +function FeaturedPost({ post }: { post: any }) { + const url = useBaseUrl(post.content.metadata.permalink); + const imageUrl = post.content.frontMatter.image ? useBaseUrl(post.content.frontMatter.image) : null; + const title = post.content.metadata.title; + const formattedDate = post.content.metadata.formattedDate; + const description = post.content.metadata.description || post.content.frontMatter.description; + const authors = post.content?.metadata?.authors || post.content?.frontMatter?.authors || []; + + return ( + + ); +} + +function BlogPostCard({ post }: { post: any }) { + const url = useBaseUrl(post.content.metadata.permalink); + const imageUrl = post.content.frontMatter.image ? useBaseUrl(post.content.frontMatter.image) : null; + const title = post.content.metadata.title; + const formattedDate = post.content.metadata.formattedDate; + const description = post.content.metadata.description || post.content.frontMatter.description; + const authors = post.content?.metadata?.authors || post.content?.frontMatter?.authors || []; + + return ( +
+ {imageUrl && ( +
+ {title} +
+ )} +
+
{formattedDate}
+

+ {title} +

+ +
{description}
+
+
+ ); +} + +function BlogPostGrid({ posts }: { posts: any[] }) { + return ( +
+ {posts.map((post, index) => ( + + ))} +
+ ); +} + +function BlogListPageContent(props: Props): ReactNode { + const { metadata, items } = props; + const isFirstPage = !metadata.permalink.includes('/page/'); + + const validItems = items.filter(item => + item.content?.metadata?.title && item.content?.frontMatter + ); + + const featuredPosts = isFirstPage + ? validItems.filter(item => item.content.frontMatter.featured === true) + : []; + + const regularPosts = isFirstPage + ? validItems.filter(item => item !== featuredPosts[0]) + : validItems; + + return ( + +
+ {featuredPosts.length > 0 && ( +
+ +
+ )} + {regularPosts.length > 0 && } +
+ +
+
+
+ ); +} + +export default function BlogListPage(props: Props): ReactNode { + return ( + + + + + + ); +} \ No newline at end of file diff --git a/documentation/src/theme/BlogListPage/styles.module.css b/documentation/src/theme/BlogListPage/styles.module.css new file mode 100644 index 000000000000..3b2b0676e271 --- /dev/null +++ b/documentation/src/theme/BlogListPage/styles.module.css @@ -0,0 +1,258 @@ +/* Magazine-style Blog Layout */ + +.blogContainer { + max-width: 1200px; + margin: 0 auto; + padding: 0 1rem; +} + +.featuredSection { + margin-bottom: 3rem; +} + +.featuredPost { + background: var(--ifm-card-background-color); + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 8px; + overflow: hidden; + display: flex; + flex-direction: row; + gap: 2rem; + padding: 2rem; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + transition: box-shadow 0.3s ease; + margin-bottom: 2rem; +} + +.featuredPost:hover { + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); +} + +.featuredContent { + flex: 1; + display: flex; + flex-direction: column; +} + +.featuredImage { + flex: 0 0 350px; + order: 2; + display: flex; +} + +.featuredImage img { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: 8px; +} + +.featuredDate { + font-size: 0.9rem; + color: var(--ifm-color-content-secondary); + margin-bottom: 0.5rem; +} + +.featuredTitle { + font-size: 2.5rem; + font-weight: bold; + margin-bottom: 0.75rem; + color: var(--ifm-color-content); + line-height: 1.2; +} + +.featuredTitle a { + text-decoration: none; + color: inherit; +} + +.featuredTitle a:hover { + color: var(--ifm-color-primary); +} + + +.postAuthors { + display: flex; + gap: 0.5rem; + align-items: center; + margin-bottom: 1rem; +} + +.authorInfo { + display: flex; + align-items: center; + gap: 0.25rem; +} + +.authorAvatar { + width: 20px; + height: 20px; + border-radius: 50%; + border: 1px solid var(--ifm-color-emphasis-200); +} + +.authorName { + font-size: 0.85rem; + color: var(--ifm-color-content-secondary); +} + +.featuredDescription { + color: var(--ifm-color-content-secondary); + line-height: 1.6; + margin-bottom: 1.5rem; + flex-grow: 1; +} + +.featuredButton { + align-self: flex-start; + background: var(--ifm-color-primary); + color: white; + padding: 0.5rem 1rem; + border: none; + border-radius: 4px; + text-decoration: none; + font-weight: 500; + font-size: 0.9rem; + transition: background-color 0.3s ease; + width: fit-content; +} + +.featuredButton:hover { + background: var(--ifm-color-primary-dark); + color: white; + text-decoration: none; +} + +.postsGrid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 2rem; + margin-bottom: 3rem; +} + +.postCard { + background: var(--ifm-card-background-color); + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 8px; + overflow: hidden; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + transition: box-shadow 0.3s ease; + display: flex; + flex-direction: column; + height: 100%; +} + +.postCard:hover { + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); +} + +.postImage { + width: 100%; + height: 200px; + overflow: hidden; +} + +.postImage img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.postContent { + padding: 1.5rem; + display: flex; + flex-direction: column; + flex-grow: 1; +} + +.postDate { + font-size: 0.85rem; + color: var(--ifm-color-content-secondary); + margin-bottom: 0.5rem; +} + +.postTitle { + font-size: 1.25rem; + font-weight: bold; + margin-bottom: 0.75rem; + color: var(--ifm-color-content); + line-height: 1.3; +} + +.postTitle a { + text-decoration: none; + color: inherit; +} + +.postTitle a:hover { + color: var(--ifm-color-primary); +} + + +.postDescription { + color: var(--ifm-color-content-secondary); + line-height: 1.6; + margin-bottom: 1rem; + flex-grow: 1; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; +} + +.paginationWrapper { + margin-top: 2rem; + padding-top: 2rem; + border-top: 1px solid var(--ifm-color-emphasis-200); +} + +/* Responsive Design */ +@media (max-width: 996px) { + .postsGrid { + grid-template-columns: repeat(2, 1fr); + gap: 1.5rem; + } + + .featuredPost { + flex-direction: column; + gap: 1.5rem; + } + + .featuredImage { + order: 0; + flex: none; + } + + .featuredImage img { + height: 250px; + } +} + +@media (max-width: 768px) { + .postsGrid { + grid-template-columns: 1fr; + gap: 1.5rem; + } + + .blogContainer { + padding: 0 0.5rem; + } + + .featuredPost { + padding: 1.5rem; + } + + .featuredTitle { + font-size: 1.5rem; + } +} + +@media (max-width: 480px) { + .postContent { + padding: 1rem; + } + + .featuredPost { + padding: 1rem; + } +} \ No newline at end of file diff --git a/documentation/blog/2026-03-31-adversary-mode/adversary-mode.png b/documentation/static/img/blog/adversary-mode.png similarity index 100% rename from documentation/blog/2026-03-31-adversary-mode/adversary-mode.png rename to documentation/static/img/blog/adversary-mode.png diff --git a/documentation/blog/2026-01-05-agentic-guardrails-and-controls/agentic_guardrails_header.jpg b/documentation/static/img/blog/agentic_guardrails_header.jpg similarity index 100% rename from documentation/blog/2026-01-05-agentic-guardrails-and-controls/agentic_guardrails_header.jpg rename to documentation/static/img/blog/agentic_guardrails_header.jpg diff --git a/documentation/static/img/blog/automate-taste.png b/documentation/static/img/blog/automate-taste.png new file mode 100644 index 000000000000..eea7fea95ca7 Binary files /dev/null and b/documentation/static/img/blog/automate-taste.png differ diff --git a/documentation/blog/2026-02-06-8-things-you-didnt-know-about-code-mode/header-image.png b/documentation/static/img/blog/code-mode-header-image.png similarity index 100% rename from documentation/blog/2026-02-06-8-things-you-didnt-know-about-code-mode/header-image.png rename to documentation/static/img/blog/code-mode-header-image.png diff --git a/documentation/static/img/blog/context-engineering-blogbanner.png b/documentation/static/img/blog/context-engineering-blogbanner.png new file mode 100644 index 000000000000..e39a03ba041e Binary files /dev/null and b/documentation/static/img/blog/context-engineering-blogbanner.png differ diff --git a/documentation/blog/2026-04-08-goose-acp-and-new-tui/goose-2-blog-cover.jpg b/documentation/static/img/blog/goose-2-blog-cover.jpg similarity index 100% rename from documentation/blog/2026-04-08-goose-acp-and-new-tui/goose-2-blog-cover.jpg rename to documentation/static/img/blog/goose-2-blog-cover.jpg diff --git a/documentation/blog/2026-02-24-goose-grant-goose-in-a-pond/banner.png b/documentation/static/img/blog/goose-grant-goose-in-a-pond.png similarity index 100% rename from documentation/blog/2026-02-24-goose-grant-goose-in-a-pond/banner.png rename to documentation/static/img/blog/goose-grant-goose-in-a-pond.png diff --git a/documentation/blog/2026-01-06-mcp-apps/goose-lands-mcp-apps-header-image.png b/documentation/static/img/blog/goose-lands-mcp-apps-header-image.png similarity index 100% rename from documentation/blog/2026-01-06-mcp-apps/goose-lands-mcp-apps-header-image.png rename to documentation/static/img/blog/goose-lands-mcp-apps-header-image.png diff --git a/documentation/static/img/blog/goose-maintains-goose.png b/documentation/static/img/blog/goose-maintains-goose.png new file mode 100644 index 000000000000..e0a6731b5124 Binary files /dev/null and b/documentation/static/img/blog/goose-maintains-goose.png differ diff --git a/documentation/blog/2026-01-20-goose-mobile-apps/goose-mobile-apps-banner.png b/documentation/static/img/blog/goose-mobile-apps-banner.png similarity index 100% rename from documentation/blog/2026-01-20-goose-mobile-apps/goose-mobile-apps-banner.png rename to documentation/static/img/blog/goose-mobile-apps-banner.png diff --git a/documentation/blog/2026-02-23-goose-v1-25-0/banner.png b/documentation/static/img/blog/goose-v1-25-0.png similarity index 100% rename from documentation/blog/2026-02-23-goose-v1-25-0/banner.png rename to documentation/static/img/blog/goose-v1-25-0.png diff --git a/documentation/static/img/blog/goosetown.png b/documentation/static/img/blog/goosetown.png new file mode 100644 index 000000000000..c4f8ec33fee7 Binary files /dev/null and b/documentation/static/img/blog/goosetown.png differ diff --git a/documentation/static/img/blog/how-to-break-up-with-your-agent.png b/documentation/static/img/blog/how-to-break-up-with-your-agent.png new file mode 100644 index 000000000000..276aa5e3011e Binary files /dev/null and b/documentation/static/img/blog/how-to-break-up-with-your-agent.png differ diff --git a/documentation/blog/2026-02-25-order-lunch-with-goose/banner.png b/documentation/static/img/blog/lunch-with-goose.png similarity index 100% rename from documentation/blog/2026-02-25-order-lunch-with-goose/banner.png rename to documentation/static/img/blog/lunch-with-goose.png diff --git a/documentation/blog/2026-01-30-5-tips-building-mcp-apps/blogbanner.png b/documentation/static/img/blog/mcp-apps-tips-blogbanner.png similarity index 100% rename from documentation/blog/2026-01-30-5-tips-building-mcp-apps/blogbanner.png rename to documentation/static/img/blog/mcp-apps-tips-blogbanner.png diff --git a/documentation/blog/2026-01-22-mcp-ui-to-mcp-apps/blogbanner.png b/documentation/static/img/blog/mcp-ui-to-apps-blogbanner.png similarity index 100% rename from documentation/blog/2026-01-22-mcp-ui-to-mcp-apps/blogbanner.png rename to documentation/static/img/blog/mcp-ui-to-apps-blogbanner.png diff --git a/documentation/blog/2026-02-06-rp-why-skill/rp-why-banner.png b/documentation/static/img/blog/rp-why-banner.png similarity index 100% rename from documentation/blog/2026-02-06-rp-why-skill/rp-why-banner.png rename to documentation/static/img/blog/rp-why-banner.png diff --git a/documentation/static/img/blog/rpi-openclaw-blogbanner.png b/documentation/static/img/blog/rpi-openclaw-blogbanner.png new file mode 100644 index 000000000000..a992fc0273cf Binary files /dev/null and b/documentation/static/img/blog/rpi-openclaw-blogbanner.png differ diff --git a/documentation/blog/2026-01-15-why-tool-descriptions-arent-enough/blogbanner.png b/documentation/static/img/blog/tool-descriptions-banner.png similarity index 100% rename from documentation/blog/2026-01-15-why-tool-descriptions-arent-enough/blogbanner.png rename to documentation/static/img/blog/tool-descriptions-banner.png diff --git a/documentation/blog/2026-03-17-webmcp-for-beginners/webmcp-for-beginners.png b/documentation/static/img/blog/webmcp-for-beginners.png similarity index 100% rename from documentation/blog/2026-03-17-webmcp-for-beginners/webmcp-for-beginners.png rename to documentation/static/img/blog/webmcp-for-beginners.png