diff --git a/app/_components/examples-gallery.tsx b/app/_components/examples-gallery.tsx new file mode 100644 index 000000000..020a34a9f --- /dev/null +++ b/app/_components/examples-gallery.tsx @@ -0,0 +1,676 @@ +"use client"; + +import { + ChevronDown, + LayoutGrid, + List, + type LucideIcon, + Network, + Plug, + Search, + SlidersHorizontal, + Workflow, + X, +} from "lucide-react"; +import Link from "next/link"; +import posthog from "posthog-js"; +import { type Dispatch, type SetStateAction, useMemo, useState } from "react"; +import { + EXAMPLES, + type ExampleItem, + type ExampleLevel, + type ExampleType, + LEVELS, +} from "../en/resources/examples/examples-data"; +import { SampleAppCard } from "./sample-app-card"; + +// Tag taxonomy mirrors the badge colors in so the filter +// rail groups tags the same way the cards present them. +const LANGUAGES = ["JavaScript", "Python", "TypeScript", "Java", "Go", "Rust"]; +const FRAMEWORKS = [ + "Langchain", + "mastra", + "CrewAI", + "LangGraph", + "OpenAI", + "Anthropic", + "Next.js", +]; +const INTEGRATIONS = [ + "Slack", + "GitHub", + "Gmail", + "Discord", + "Notion", + "Linear", + "Jira", + "Weaviate", + "Email", + "Stytch", +]; + +const TYPES: ExampleType[] = ["Sample app", "MCP server"]; + +// The outcome-driven skill levels, in display order (beginner first). +const LEVEL_VALUES: ExampleLevel[] = LEVELS.map((meta) => meta.level); + +// Display label for the primary (skill-level) facet. Change it in one place. +const LEVEL_FACET_LABEL = "Goal"; + +function levelId(level: string): string { + return `level-${level.toLowerCase()}`; +} + +// Seconds between each goal card's "alive" pulse so they breathe out of sync. +const PULSE_STAGGER_S = 0.4; + +// An icon per goal so the overview cards read as the page's focal point. +const LEVEL_ICONS: Record = { + Connect: Plug, + Automate: Workflow, + Orchestrate: Network, +}; + +const MONTHS: Record = { + Jan: 1, + Feb: 2, + Mar: 3, + Apr: 4, + May: 5, + Jun: 6, + Jul: 7, + Aug: 8, + Sep: 9, + Oct: 10, + Nov: 11, + Dec: 12, +}; + +// Weight years above months so "Dec 2025" sorts after "Jan 2025". +const YEAR_WEIGHT = 100; + +function sortKey(date: string): number { + const [mon, year] = date.split(" "); + return Number(year) * YEAR_WEIGHT + (MONTHS[mon] ?? 0); +} + +type FacetGroup = { + label: string; + options: { value: string; count: number }[]; +}; + +function buildGroups(items: ExampleItem[]): FacetGroup[] { + const count = (predicate: (item: ExampleItem) => boolean) => + items.filter(predicate).length; + + const pick = (label: string, candidates: string[]): FacetGroup => ({ + label, + options: candidates + .map((value) => ({ + value, + count: count((item) => item.tags.includes(value)), + })) + .filter((opt) => opt.count > 0), + }); + + // Goal (skill level) is intentionally NOT a filter facet: it's already the + // page's grouping + the jump nav, so a chip row would just duplicate those. + return [ + { + label: "Type", + options: TYPES.map((value) => ({ + value, + count: count((item) => item.type === value), + })).filter((opt) => opt.count > 0), + }, + pick("Language", LANGUAGES), + pick("Framework", FRAMEWORKS), + pick("Integration", INTEGRATIONS), + ].filter((group) => group.options.length > 0); +} + +function filterItems( + items: ExampleItem[], + query: string, + active: Set +): ExampleItem[] { + const q = query.trim().toLowerCase(); + const selectedTypes = TYPES.filter((t) => active.has(t)); + const selectedLevels = LEVEL_VALUES.filter((l) => active.has(l)); + const selectedTags = [...active].filter( + (v) => + !( + TYPES.includes(v as ExampleType) || + LEVEL_VALUES.includes(v as ExampleLevel) + ) + ); + + return items.filter((item) => { + const matchesType = + selectedTypes.length === 0 || selectedTypes.includes(item.type); + const matchesLevel = + selectedLevels.length === 0 || selectedLevels.includes(item.level); + const matchesTags = + selectedTags.length === 0 || + selectedTags.every((tag) => item.tags.includes(tag)); + const haystack = + `${item.title} ${item.description} ${item.tags.join(" ")} ${item.type} ${item.level}`.toLowerCase(); + const matchesQuery = q === "" || haystack.includes(q); + return matchesType && matchesLevel && matchesTags && matchesQuery; + }); +} + +// One facet's label + its selectable chips. Counts are intentionally omitted to +// keep the bar calm; the running "N examples" total below already conveys scope. +function FacetChips({ + group, + active, + onToggle, +}: { + group: FacetGroup; + active: Set; + onToggle: (value: string) => void; +}) { + return ( +
+ + {group.label} + + {group.options.map((opt) => { + const on = active.has(opt.value); + return ( + + ); + })} +
+ ); +} + +function CardGrid({ items }: { items: ExampleItem[] }) { + return ( +
+ {items.map((item) => ( + + ))} +
+ ); +} + +// A numbered header + short description for each skill-level bucket. +function LevelHeading({ + index, + level, + tier, + outcome, +}: { + index: number; + level: string; + tier: string; + outcome: string; +}) { + return ( +
+ + {index} + +
+
+

+ {level} +

+ + {tier} + +
+

+ {outcome} +

+
+
+ ); +} + +function FiltersToggle({ + showMore, + setShowMore, + secondaryActiveCount, +}: { + showMore: boolean; + setShowMore: Dispatch>; + secondaryActiveCount: number; +}) { + const on = showMore || secondaryActiveCount > 0; + return ( + + ); +} + +function Controls({ + query, + setQuery, + view, + setView, + showMore, + setShowMore, + hasSecondary, + secondaryActiveCount, + hasFilters, + clear, +}: { + query: string; + setQuery: Dispatch>; + view: "grid" | "list"; + setView: Dispatch>; + showMore: boolean; + setShowMore: Dispatch>; + hasSecondary: boolean; + secondaryActiveCount: number; + hasFilters: boolean; + clear: () => void; +}) { + const tabClass = (active: boolean) => + `inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 font-medium text-sm transition-colors ${ + active + ? "bg-gray-100 text-gray-900 dark:bg-gray-800 dark:text-white" + : "text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white" + }`; + + return ( +
+
+ + setQuery(event.target.value)} + placeholder="Search examples" + type="search" + value={query} + /> +
+ +
+ {hasSecondary && ( + + )} + {hasFilters && ( + + )} +
+ + +
+
+
+ ); +} + +function SecondaryFilters({ + groups, + active, + toggle, +}: { + groups: FacetGroup[]; + active: Set; + toggle: (value: string) => void; +}) { + return ( +
+ {groups.map((group) => ( + + ))} +
+ ); +} + +function LevelSections({ gridItems }: { gridItems: ExampleItem[] }) { + return ( + <> + {LEVELS.map((meta, idx) => { + const levelItems = gridItems.filter( + (item) => item.level === meta.level + ); + if (levelItems.length === 0) { + return null; + } + return ( +
+ + +
+ ); + })} + + ); +} + +function ListView({ items }: { items: ExampleItem[] }) { + return ( +
+
+ Example + {LEVEL_FACET_LABEL} + Type + Date +
+ {items.map((item) => ( + + posthog.capture("Sample app clicked", { + app_title: item.title, + app_href: item.href, + tags: item.tags, + opens_in_new_tab: true, + }) + } + target="_blank" + > +
+

+ {item.title} +

+

+ {item.description} +

+
+ {item.tags.map((tag) => ( + + {tag} + + ))} +
+
+
+ {item.level} +
+
+ {item.type} +
+
+ {item.date} +
+ + ))} +
+ ); +} + +// Each goal card previews one example from its bucket (the newest) so the +// overview features an example per goal instead of a single hero. +function LevelNav({ gridItems }: { gridItems: ExampleItem[] }) { + return ( + + ); +} + +function Results({ + view, + grouped, + gridItems, + visibleCount, + total, + clear, +}: { + view: "grid" | "list"; + grouped: boolean; + gridItems: ExampleItem[]; + visibleCount: number; + total: number; + clear: () => void; +}) { + const hasCards = gridItems.length > 0; + const showFlatGrid = !grouped && view === "grid" && hasCards; + const showList = view === "list" && hasCards; + + return ( +
+

+ {visibleCount === total + ? `${total} examples` + : `${visibleCount} of ${total} examples`} +

+ + {grouped && } + {showFlatGrid && } + {showList && } + + {visibleCount === 0 && ( +
+ No examples match your filters.{" "} + +
+ )} +
+ ); +} + +export function ExamplesGallery() { + const items = useMemo( + () => [...EXAMPLES].sort((a, b) => sortKey(b.date) - sortKey(a.date)), + [] + ); + const groups = useMemo(() => buildGroups(items), [items]); + + const [query, setQuery] = useState(""); + const [active, setActive] = useState>(new Set()); + const [view, setView] = useState<"grid" | "list">("grid"); + const [showMore, setShowMore] = useState(false); + + // Goal isn't a filter chip (it's the grouping + jump nav), so every facet + // here is "secondary" and lives behind the Filters disclosure. + const secondaryActiveCount = active.size; + + const toggle = (value: string) => { + setActive((prev) => { + const next = new Set(prev); + if (next.has(value)) { + next.delete(value); + } else { + next.add(value); + } + return next; + }); + }; + + const clear = () => { + setActive(new Set()); + setQuery(""); + }; + + const visible = useMemo( + () => filterItems(items, query, active), + [items, query, active] + ); + + const hasFilters = active.size > 0 || query.trim() !== ""; + + const gridItems = visible; + + // Default browse state groups cards into outcome buckets so people can find + // the right starting point. Filtering/searching collapses to a flat result + // set (grouping by level no longer helps once you've narrowed). + const grouped = view === "grid" && !hasFilters; + + return ( +
+ {grouped && } + +
+ 0} + query={query} + secondaryActiveCount={secondaryActiveCount} + setQuery={setQuery} + setShowMore={setShowMore} + setView={setView} + showMore={showMore} + view={view} + /> + {showMore && groups.length > 0 && ( + + )} +
+ + +
+ ); +} diff --git a/app/_components/sample-app-card.tsx b/app/_components/sample-app-card.tsx index b94fe7f47..92d409778 100644 --- a/app/_components/sample-app-card.tsx +++ b/app/_components/sample-app-card.tsx @@ -12,8 +12,38 @@ type SampleAppCardProps = { blank?: boolean; tags?: string[]; date?: string; + // When there's no `image`, render a generated gradient header with a monogram + // so cards still have a visual anchor. Opt-in so other usages stay unchanged. + fallbackVisual?: boolean; }; +// Tinted gradients that read well on both light and dark surfaces. +const FALLBACK_GRADIENTS = [ + "from-emerald-500/30 to-teal-600/10", + "from-violet-500/30 to-fuchsia-600/10", + "from-amber-500/30 to-orange-600/10", + "from-sky-500/30 to-blue-600/10", + "from-rose-500/30 to-pink-600/10", + "from-lime-500/30 to-green-600/10", +]; +const MONOGRAM_WORDS = 2; +const WHITESPACE = /\s+/; + +function monogram(title: string): string { + return title + .trim() + .split(WHITESPACE) + .slice(0, MONOGRAM_WORDS) + .map((word) => word.charAt(0)) + .join("") + .toUpperCase(); +} + +function gradientFor(title: string): string { + const sum = [...title].reduce((acc, ch) => acc + ch.charCodeAt(0), 0); + return FALLBACK_GRADIENTS[sum % FALLBACK_GRADIENTS.length]; +} + export function SampleAppCard({ title, description, @@ -22,6 +52,7 @@ export function SampleAppCard({ blank = false, tags = [], date, + fallbackVisual = false, }: SampleAppCardProps) { const handleClick = () => { posthog.capture("Sample app clicked", { @@ -57,6 +88,15 @@ export function SampleAppCard({ /> )} + {!image && fallbackVisual && ( +
+ + {monogram(title)} + +
+ )}

diff --git a/app/en/resources/examples/_meta.tsx b/app/en/resources/examples/_meta.tsx new file mode 100644 index 000000000..a98f4b9ae --- /dev/null +++ b/app/en/resources/examples/_meta.tsx @@ -0,0 +1,24 @@ +import type { MetaRecord } from "nextra"; + +// Nest the outcome buckets under "Examples" in the sidebar. Each is a link to +// the matching section anchor on the gallery page (ids set by `levelId` in +// examples-gallery.tsx). The parent "Examples" still opens the full gallery. +const meta: MetaRecord = { + index: { + title: "Overview", + }, + connect: { + title: "Connect", + href: "/en/resources/examples#level-connect", + }, + automate: { + title: "Automate", + href: "/en/resources/examples#level-automate", + }, + orchestrate: { + title: "Orchestrate", + href: "/en/resources/examples#level-orchestrate", + }, +}; + +export default meta; diff --git a/app/en/resources/examples/examples-data.ts b/app/en/resources/examples/examples-data.ts new file mode 100644 index 000000000..9d0280e76 --- /dev/null +++ b/app/en/resources/examples/examples-data.ts @@ -0,0 +1,193 @@ +export type ExampleType = "Sample app" | "MCP server"; + +// Outcome-driven skill levels (beginner -> advanced). The gallery groups +// examples into these buckets so a developer can find the right starting point +// for what they're trying to achieve, not just filter by tech. +export type ExampleLevel = "Connect" | "Automate" | "Orchestrate"; + +export type LevelMeta = { + level: ExampleLevel; + // Short difficulty label shown as a badge. + tier: string; + // Plain-English outcome: what you can do after working through this level. + outcome: string; +}; + +// Order here defines the order the buckets render in (beginner first). +export const LEVELS: LevelMeta[] = [ + { + level: "Connect", + tier: "Beginner", + outcome: + "Authorize an agent and make its first real tool call in a live app.", + }, + { + level: "Automate", + tier: "Intermediate", + outcome: + "Ship an agent that finishes a real task across your apps, end to end.", + }, + { + level: "Orchestrate", + tier: "Advanced", + outcome: + "Go further with multi-agent systems, frameworks, and per-user auth in production.", + }, +]; + +export type ExampleItem = { + title: string; + description: string; + href: string; + tags: string[]; + date: string; + type: ExampleType; + // Outcome-driven skill level used to group the gallery. + level: ExampleLevel; + // Optional cover art (served from /public). Cards fall back to a generated + // gradient + monogram when this is omitted. + image?: string; + // Set on one entry to spotlight it in a large hero above the grid. If more + // than one is flagged, the newest wins. + featured?: boolean; +}; + +// To feature your project, add an entry below following the existing pattern. +// `date` uses "Mon YYYY"; the gallery sorts newest-first within each level. +// `level` places it in a bucket: "Connect" (beginner), "Automate" +// (intermediate), or "Orchestrate" (advanced). +export const EXAMPLES: ExampleItem[] = [ + { + title: "Baseball dugout", + description: + "Ask about any player and the agent researches them, then emails you a full scouting report, all from one conversation.", + href: "https://github.com/ArcadeAI/baseball-dugout", + tags: ["JavaScript", "GitHub", "Email"], + date: "Dec 2025", + type: "Sample app", + level: "Automate", + image: "/images/examples/example-baseball-dugout.jpg", + featured: true, + }, + { + title: "Agent Templates", + description: + "Copy-paste starting points for common agent use cases, so you can stand up your first working agent in minutes.", + href: "https://github.com/ArcadeAI/agent-templates", + tags: ["Python"], + date: "Dec 2025", + type: "Sample app", + level: "Connect", + image: "/images/examples/example-agent-templates.jpg", + }, + { + title: "OpenAI Agents SDK + Arcade MCP Gateway", + description: + "Give an OpenAI Agents SDK app instant, authorized access to hundreds of tools through a single Arcade gateway.", + href: "https://github.com/ArcadeAI/openaisdk-mcpgateway", + tags: ["TypeScript", "OpenAI"], + date: "Nov 2025", + type: "Sample app", + level: "Orchestrate", + image: "/images/examples/example-openai-mcp-gateway.jpg", + }, + { + title: "Agent Kitchen Sink", + description: + "One TypeScript app that wires up many tools, auth flows, and integrations to show everything an agent can do with Arcade.", + href: "https://github.com/ArcadeAI/agent-kitchen-sink-typescript", + tags: ["TypeScript"], + date: "Nov 2025", + type: "Sample app", + level: "Orchestrate", + image: "/images/examples/example-agent-kitchen-sink.jpg", + }, + { + title: "Arcade Custom Verifier for Next.js apps", + description: + "Drop-in user verification for Next.js apps, so your own users can securely connect their accounts.", + href: "https://github.com/ArcadeAI/arcade-custom-verifier-next", + tags: ["TypeScript", "Next.js"], + date: "Aug 2025", + type: "Sample app", + level: "Connect", + image: "/images/examples/example-custom-verifier-next.jpg", + }, + { + title: "Agency Tutorial with Stytch", + description: + "Build an app where agents act for each signed-in user, with Stytch handling login and Arcade handling tool access.", + href: "https://github.com/ArcadeAI/agency-tutorial-stytch", + tags: ["TypeScript", "Stytch"], + date: "Aug 2025", + type: "Sample app", + level: "Connect", + image: "/images/examples/example-agency-stytch.jpg", + }, + { + title: "Arcade CLI Agent Template", + description: + "A minimal terminal agent you can talk to, so you can start building command-line tools fast.", + href: "https://github.com/ArcadeAI/cli-agent-template", + tags: ["TypeScript"], + date: "Jul 2025", + type: "Sample app", + level: "Connect", + image: "/images/examples/example-cli-agent-template.jpg", + }, + { + title: "Megaforce", + description: + "Turn one piece of content into platform-ready posts for every social channel, automatically.", + href: "https://github.com/ArcadeAI/megaforce", + tags: ["TypeScript"], + date: "Jul 2025", + type: "Sample app", + level: "Automate", + image: "/images/examples/example-megaforce.jpg", + }, + { + title: "Human-in-the-loop (HITL) Agent Frameworks Showdown", + description: + "Put a human in the loop before agents act, with the same approval workflow built three ways (LangGraph, OpenAI Agents SDK, Google ADK) so you can compare.", + href: "https://github.com/ArcadeAI/framework-showdown", + tags: ["TypeScript"], + date: "May 2025", + type: "Sample app", + level: "Orchestrate", + image: "/images/examples/example-hitl-showdown.jpg", + }, + { + title: "YouTube Transcript Bot", + description: + "Drop a YouTube link in Slack and get an instant, searchable summary, with transcripts fetched, summarized, and stored in Weaviate.", + href: "https://github.com/dforwardfeed/slack-AIpodcast-summaries", + tags: ["Python", "Langchain", "Slack", "Weaviate"], + date: "Mar 2025", + type: "Sample app", + level: "Automate", + image: "/images/examples/example-youtube-transcript.jpg", + }, + { + title: "Archer: Agentic Slack Assistant", + description: + "Run your day from Slack with one assistant that handles Google Calendar, Gmail, GitHub, and web research on your behalf.", + href: "https://github.com/ArcadeAI/ArcadeSlackAgent", + tags: ["JavaScript", "Slack"], + date: "Oct 2024", + type: "Sample app", + level: "Automate", + image: "/images/examples/example-archer-slack.jpg", + }, + { + title: "Granola MCP Server", + description: + "Give any AI client access to your Granola meeting notes and transcripts through a clean MCP server you can build on.", + href: "https://github.com/ArcadeAI/granola-mcp-server", + tags: ["Python"], + date: "Mar 2026", + type: "MCP server", + level: "Connect", + image: "/images/examples/example-granola-mcp.jpg", + }, +]; diff --git a/app/en/resources/examples/page.mdx b/app/en/resources/examples/page.mdx index 1aefa332e..0c3a56299 100644 --- a/app/en/resources/examples/page.mdx +++ b/app/en/resources/examples/page.mdx @@ -5,168 +5,30 @@ description: "Example apps and MCP servers using Arcade's tools and MCP servers ## Examples -Get up and running faster with ready-to-use example repositories. +import { ExamplesGallery } from "../../../_components/examples-gallery"; -Browse sample apps and MCP servers to see how Arcade works in practice, then fork them as a starting point or use them as a reference while building your own projects and integrations. + -import { SampleAppCard } from "../../../_components/sample-app-card"; -import { Tabs } from "nextra/components"; +### Submit your example - - - -
- - - - - - - - - - - -
- -### Submit your app - -Built something with Arcade? The team would love to feature it! Submit your app by creating a pull request to the documentation site. +Built something with Arcade? The team would love to feature it! Submit your sample app or MCP server by creating a pull request to the documentation site. #### Guidelines -- **Open source**: Your app should be publicly available on GitHub -- **Uses Arcade**: Your app should integrate with Arcade's tools, MCP servers, or SDK -- **Working demo**: Include clear setup instructions and ensure your app runs +- **Open source**: Your project should be publicly available on GitHub +- **Uses Arcade**: Your project should integrate with Arcade's tools, MCP servers, auth, or SDK +- **Working demo**: Include clear setup instructions and ensure your project runs - **Good documentation**: Provide a clear README with installation and usage instructions -- **Appropriate content**: Family friendly and professional applications only +- **Appropriate content**: Family friendly and professional projects only #### How to submit 1. Fork the [Arcade docs repository](https://github.com/ArcadeAI/docs) -2. Add your app to `/app/en/resources/examples/page.mdx` following the existing pattern -3. Include a descriptive title, clear description, and appropriate tags -4. Create a pull request with details about your app and its Arcade integration -5. The team will review and potentially feature your app +2. Add an entry to `/app/en/resources/examples/examples-data.ts` following the existing pattern, setting `type` to either `"Sample app"` or `"MCP server"` and `level` to `"Connect"` (beginner), `"Automate"` (intermediate), or `"Orchestrate"` (advanced) +3. Write a benefit-first description (lead with what the user can _do_, not how it's built), plus a descriptive title, appropriate tags, and the release date +4. Create a pull request with details about your project and its Arcade integration +5. The team will review and potentially feature your project #### Need help? -If you have questions about submitting your app, feel free to [contact the team](/resources/contact-us) or open an issue in the docs repository. - -
- - -
- -
- -### Submit your MCP server - -Built an MCP server with Arcade? The team would love to feature it! Submit your server by creating a pull request to the documentation site. - -#### Guidelines - -- **Open source**: Your MCP server should be publicly available on GitHub -- **Uses Arcade**: Your server should integrate with Arcade's tools, auth, or SDK -- **Working demo**: Include clear setup instructions and ensure your server runs -- **Good documentation**: Provide a clear README with installation and usage instructions -- **Appropriate content**: Family friendly and professional servers only - -#### How to submit - -1. Fork the [Arcade docs repository](https://github.com/ArcadeAI/docs) -2. Add your server to `/app/en/resources/examples/page.mdx` following the existing pattern -3. Include a descriptive title, clear description, and appropriate tags -4. Create a pull request with details about your server, its Arcade integration, and a link to the public repository. -5. The team will review and potentially feature your server - -#### Need help? - -If you have questions about submitting your MCP server, feel free to [contact the team](/resources/contact-us) or open an issue in the docs repository. - -
-
+If you have questions about submitting your project, feel free to [contact the team](/resources/contact-us) or open an issue in the docs repository. diff --git a/app/globals.css b/app/globals.css index e0a653de7..35abda5e3 100644 --- a/app/globals.css +++ b/app/globals.css @@ -216,6 +216,24 @@ nav > div:has(.algolia-search-button) { } } +/* Subtle "alive" glow on the Examples overview goal cards. Staggered per card + * via inline animation-delay; disabled for reduced-motion users. */ +@media (prefers-reduced-motion: no-preference) { + @keyframes goal-pulse { + 0%, + 100% { + box-shadow: 0 0 0 0 transparent; + } + 50% { + box-shadow: 0 0 24px 2px color-mix(in oklch, var(--brand-accent) 32%, transparent); + } + } + + .goal-pulse-card { + animation: goal-pulse 2.8s ease-in-out infinite; + } +} + /* Only number h3 (###) in Steps component, not smaller nested headings */ .nextra-steps h4, .nextra-steps h5, diff --git a/public/images/examples/example-agency-stytch.jpg b/public/images/examples/example-agency-stytch.jpg new file mode 100644 index 000000000..226d1ad02 Binary files /dev/null and b/public/images/examples/example-agency-stytch.jpg differ diff --git a/public/images/examples/example-agent-kitchen-sink.jpg b/public/images/examples/example-agent-kitchen-sink.jpg new file mode 100644 index 000000000..ad9758afb Binary files /dev/null and b/public/images/examples/example-agent-kitchen-sink.jpg differ diff --git a/public/images/examples/example-agent-templates.jpg b/public/images/examples/example-agent-templates.jpg new file mode 100644 index 000000000..7b62896c7 Binary files /dev/null and b/public/images/examples/example-agent-templates.jpg differ diff --git a/public/images/examples/example-archer-slack.jpg b/public/images/examples/example-archer-slack.jpg new file mode 100644 index 000000000..df4ffb8c6 Binary files /dev/null and b/public/images/examples/example-archer-slack.jpg differ diff --git a/public/images/examples/example-baseball-dugout.jpg b/public/images/examples/example-baseball-dugout.jpg new file mode 100644 index 000000000..f7f9f2401 Binary files /dev/null and b/public/images/examples/example-baseball-dugout.jpg differ diff --git a/public/images/examples/example-cli-agent-template.jpg b/public/images/examples/example-cli-agent-template.jpg new file mode 100644 index 000000000..694e1f4b6 Binary files /dev/null and b/public/images/examples/example-cli-agent-template.jpg differ diff --git a/public/images/examples/example-custom-verifier-next.jpg b/public/images/examples/example-custom-verifier-next.jpg new file mode 100644 index 000000000..6eb93e146 Binary files /dev/null and b/public/images/examples/example-custom-verifier-next.jpg differ diff --git a/public/images/examples/example-granola-mcp.jpg b/public/images/examples/example-granola-mcp.jpg new file mode 100644 index 000000000..ab1615ae7 Binary files /dev/null and b/public/images/examples/example-granola-mcp.jpg differ diff --git a/public/images/examples/example-hitl-showdown.jpg b/public/images/examples/example-hitl-showdown.jpg new file mode 100644 index 000000000..884df958c Binary files /dev/null and b/public/images/examples/example-hitl-showdown.jpg differ diff --git a/public/images/examples/example-megaforce.jpg b/public/images/examples/example-megaforce.jpg new file mode 100644 index 000000000..2b847e474 Binary files /dev/null and b/public/images/examples/example-megaforce.jpg differ diff --git a/public/images/examples/example-openai-mcp-gateway.jpg b/public/images/examples/example-openai-mcp-gateway.jpg new file mode 100644 index 000000000..b245b1e5b Binary files /dev/null and b/public/images/examples/example-openai-mcp-gateway.jpg differ diff --git a/public/images/examples/example-youtube-transcript.jpg b/public/images/examples/example-youtube-transcript.jpg new file mode 100644 index 000000000..669038d10 Binary files /dev/null and b/public/images/examples/example-youtube-transcript.jpg differ