diff --git a/frontend/src/landing/components/docs/DocsMissingPage.tsx b/frontend/src/landing/components/docs/DocsMissingPage.tsx new file mode 100644 index 000000000..fede1d97d --- /dev/null +++ b/frontend/src/landing/components/docs/DocsMissingPage.tsx @@ -0,0 +1,65 @@ +import Link from "next/link"; +import { DocsBody, DocsPage } from "fumadocs-ui/page"; + +export function DocsMissingPage() { + return ( + + + + + + docs / checkout failed + + + + + This page checked out the wrong worktree. + + + The docs were rebuilt, and this URL did not survive the merge. Start from the docs + index, or use search in the sidebar to find where it landed. + + + + Browse docs + + + Home + + + + + + + + + + $ ao docs resolve + status: missing + next: /docs + + + + + + + ); +} diff --git a/frontend/src/landing/components/docs/Logo.tsx b/frontend/src/landing/components/docs/Logo.tsx new file mode 100644 index 000000000..d14632a3c --- /dev/null +++ b/frontend/src/landing/components/docs/Logo.tsx @@ -0,0 +1,100 @@ +/** + * Brand logo component for docs pages. + * + * Renders real brand assets from /public/docs/logos/ when available, with + * name-aliasing. Mono brand SVGs are pre-processed to use white fill for the + * dark theme. Falls back to a monogram badge for anything not in the set. + */ +import type { CSSProperties } from "react"; + +/** Aliases: request name -> filename under /docs/logos/. */ +const ALIASES: Record = { + claude: "claude-code", + chatgpt: "openai", +}; + +/** Extension for each logo file. Defaults to svg; override for raster assets. */ +const LOGO_EXT: Record = { + aider: "png", +}; + +/** Brands with a real asset file under /public/docs/logos/. */ +const FILE_LOGOS = new Set([ + "aider", + "anthropic", + "apple", + "claude-code", + "codex", + "composio", + "cursor", + "discord", + "docker", + "github", + "gitlab", + "iterm2", + "linear", + "linux", + "microsoft", + "openai", + "openclaw", + "opencode", + "slack", + "tmux", + "web", + "webhook", + "windows", +]); + +export interface LogoProps { + /** Brand name (case-insensitive). */ + name: string; + /** Size in pixels. Default 20. */ + size?: number; + className?: string; + /** Accepted for backwards compat with existing MDX; no-op. */ + color?: boolean; +} + +export function Logo({ name, size = 20, className }: LogoProps) { + const key = name.toLowerCase(); + const resolved = ALIASES[key] ?? key; + const baseStyle: CSSProperties = { flexShrink: 0, width: size, height: size }; + + if (FILE_LOGOS.has(resolved)) { + const ext = LOGO_EXT[resolved] ?? "svg"; + return ( + + ); + } + + const initial = name.charAt(0).toUpperCase(); + return ( + + {initial} + + ); +} diff --git a/frontend/src/landing/components/docs/PlatformSupport.tsx b/frontend/src/landing/components/docs/PlatformSupport.tsx new file mode 100644 index 000000000..374dd8be3 --- /dev/null +++ b/frontend/src/landing/components/docs/PlatformSupport.tsx @@ -0,0 +1,102 @@ +/** + * Shows a three-column support matrix for macOS / Linux / Windows. + * Use at the top of plugin pages to set platform expectations immediately. + */ +import type { ReactNode } from "react"; +import { Logo } from "./Logo"; + +type Status = "full" | "partial" | "none"; + +export interface PlatformSupportProps { + macos?: Status; + linux?: Status; + windows?: Status; + note?: ReactNode; +} + +const LABEL: Record = { + full: "Supported", + partial: "In progress", + none: "Not supported", +}; + +const DOT_COLOR: Record = { + full: "var(--color-accent-amber, #f97316)", + partial: "var(--color-accent-amber-dim, #a3581b)", + none: "var(--color-text-muted, #605e5c)", +}; + +function Cell({ platform, status }: { platform: "macos" | "linux" | "windows"; status: Status }) { + const logoName = platform === "macos" ? "apple" : platform; + const title = platform === "macos" ? "macOS" : platform === "linux" ? "Linux" : "Windows"; + return ( + + + + + {title} + + + + {LABEL[status]} + + + + ); +} + +export function PlatformSupport({ + macos = "full", + linux = "full", + windows = "full", + note, +}: PlatformSupportProps) { + return ( + + + + + + + {note && ( + + {note} + + )} + + ); +} diff --git a/frontend/src/landing/components/docs/PluginCard.tsx b/frontend/src/landing/components/docs/PluginCard.tsx new file mode 100644 index 000000000..9f4c2b81c --- /dev/null +++ b/frontend/src/landing/components/docs/PluginCard.tsx @@ -0,0 +1,91 @@ +/** + * Catalog-style card for a single plugin. + * Used on the plugin overview pages to let users scan by logo + one-liner. + */ +import Link from "next/link"; +import type { ReactNode } from "react"; +import { Logo } from "./Logo"; + +export interface PluginCardProps { + name: string; + logo: string; + href: string; + description: string; + badge?: ReactNode; +} + +export function PluginCard({ name, logo, href, description, badge }: PluginCardProps) { + return ( + + + + + + + {name} + {badge} + + + {description} + + + + ); +} + +export function PluginGrid({ children }: { children: ReactNode }) { + return ( + + {children} + + ); +} diff --git a/frontend/src/landing/components/docs/mdx-components.tsx b/frontend/src/landing/components/docs/mdx-components.tsx new file mode 100644 index 000000000..c712fd06f --- /dev/null +++ b/frontend/src/landing/components/docs/mdx-components.tsx @@ -0,0 +1,37 @@ +/** + * Shared MDX component registry for docs pages. + * Exposes docs-specific components and a small Accordion pair used by content. + */ +import type { ReactNode } from "react"; +import defaultMdxComponents from "fumadocs-ui/mdx"; +import type { MDXComponents } from "mdx/types"; +import { Logo } from "./Logo"; +import { PlatformSupport } from "./PlatformSupport"; +import { PluginCard, PluginGrid } from "./PluginCard"; + +function Accordions({ children }: { children: ReactNode }) { + return {children}; +} + +function Accordion({ title, children }: { title: ReactNode; children: ReactNode }) { + return ( + + + {title} + + {children} + + ); +} + +export function getMDXComponents(): MDXComponents { + return { + ...defaultMdxComponents, + Accordion, + Accordions, + Logo, + PlatformSupport, + PluginCard, + PluginGrid, + }; +} \ No newline at end of file diff --git a/frontend/src/landing/lib/source.ts b/frontend/src/landing/lib/source.ts new file mode 100644 index 000000000..718603215 --- /dev/null +++ b/frontend/src/landing/lib/source.ts @@ -0,0 +1,7 @@ +import { loader } from "fumadocs-core/source"; +import { docs } from ".source"; + +export const source = loader({ + baseUrl: "/docs", + source: docs.toFumadocsSource(), +});
+ The docs were rebuilt, and this URL did not survive the merge. Start from the docs + index, or use search in the sidebar to find where it landed. +
$ ao docs resolve
status: missing
next: /docs
+ {note} +