import Layout from "@theme/Layout"; import { ArrowLeft } from "lucide-react"; import { useLocation } from "@docusaurus/router"; import { useEffect, useState } from "react"; import Link from "@docusaurus/Link"; import Admonition from "@theme/Admonition"; import CodeBlock from "@theme/CodeBlock"; import { Button } from "@site/src/components/ui/button"; import { getRecipeById } from "@site/src/utils/recipes"; import type { Recipe } from "@site/src/components/recipe-card"; import toast from "react-hot-toast"; const colorMap: { [key: string]: string } = { "GitHub MCP": "bg-yellow-100 text-yellow-800 border-yellow-200", "Context7 MCP": "bg-purple-100 text-purple-800 border-purple-200", "Memory": "bg-blue-100 text-blue-800 border-blue-200", }; export default function RecipeDetailPage(): JSX.Element { const location = useLocation(); const [recipe, setRecipe] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [showParamsPrompt, setShowParamsPrompt] = useState(false); const [paramValues, setParamValues] = useState>({}); useEffect(() => { const loadRecipe = async () => { try { setLoading(true); setError(null); setParamValues({}); setShowParamsPrompt(false); const params = new URLSearchParams(location.search); const id = params.get("id"); if (!id) { setError("No recipe ID provided"); return; } const recipeData = await getRecipeById(id); if (recipeData) { setRecipe(recipeData); } else { setError("Recipe not found"); } } catch (err) { setError("Failed to load recipe details"); console.error(err); } finally { setLoading(false); } }; loadRecipe(); }, [location]); const allParams = recipe?.parameters || []; const requiredParams = allParams.filter((p) => p.requirement === "required"); const handleCopyCLI = () => { if (allParams.length > 0) { setParamValues({}); setShowParamsPrompt(true); return; } const command = `goose run --recipe ${recipe?.localPath}`; navigator.clipboard.writeText(command); toast.success("CLI command copied!"); }; const handleSubmitParams = () => { const filledParams = Object.entries(paramValues) .filter(([, val]) => val !== "") .map(([key, val]) => `${key}=${val}`) .join(" "); const command = `goose run --recipe ${recipe?.localPath}${ filledParams ? ` --params ${filledParams}` : "" }`; navigator.clipboard.writeText(command); toast.success("CLI command copied with params!"); setShowParamsPrompt(false); }; if (loading) { return (
); } if (error || !recipe) { return (
{error || "Recipe not found"}
); } const authorUsername = typeof recipe.author === "string" ? recipe.author : recipe.author?.contact; return (
{authorUsername && ( {authorUsername} @{authorUsername} )}

{recipe.title}

{recipe.description}

{/* Activities */} {recipe.activities?.length > 0 && (

Activities

{recipe.activities.map((activity, index) => ( {activity} ))}
)} {/* Extensions */} {recipe.extensions?.length > 0 && (

Extensions

{recipe.extensions.map((ext, index) => { const name = typeof ext === "string" ? ext : ext.name; return ( {name} ); })}
)} {/* Prompt */} {recipe.prompt && (

Initial Prompt

This prompt auto-starts the recipe when launched in Goose. {recipe.prompt}
)} {/* Instructions */} {recipe.instructions && (

Instructions

{recipe.instructions}
)} {/* Launch */}
Launch in Goose Desktop →
Copies the CLI command to run this recipe
{showParamsPrompt && (

Fill in parameters

{allParams.map((param) => (
setParamValues((prev) => ({ ...prev, [param.key]: e.target.value })) } className="w-full px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded bg-white dark:bg-zinc-700 text-zinc-900 dark:text-white" />
))}
)}
); }