diff --git a/.schemas/cookbook.schema.json b/.schemas/cookbook.schema.json new file mode 100644 index 00000000..857bd84e --- /dev/null +++ b/.schemas/cookbook.schema.json @@ -0,0 +1,99 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Cookbook Manifest", + "description": "Schema for cookbook.yml manifest defining cookbooks and recipes", + "type": "object", + "required": ["cookbooks"], + "properties": { + "cookbooks": { + "type": "array", + "description": "List of cookbooks", + "items": { + "type": "object", + "required": ["id", "name", "description", "path", "languages", "recipes"], + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the cookbook", + "pattern": "^[a-z0-9-]+$" + }, + "name": { + "type": "string", + "description": "Display name for the cookbook" + }, + "description": { + "type": "string", + "description": "Brief description of the cookbook" + }, + "path": { + "type": "string", + "description": "Relative path to the cookbook folder" + }, + "featured": { + "type": "boolean", + "description": "Whether this cookbook should be featured", + "default": false + }, + "languages": { + "type": "array", + "description": "Programming languages supported by this cookbook", + "items": { + "type": "object", + "required": ["id", "name"], + "properties": { + "id": { + "type": "string", + "description": "Language identifier (folder name)", + "pattern": "^[a-z0-9-]+$" + }, + "name": { + "type": "string", + "description": "Display name for the language" + }, + "icon": { + "type": "string", + "description": "Emoji icon for the language" + }, + "extension": { + "type": "string", + "description": "File extension for runnable examples", + "pattern": "^\\.[a-z]+$" + } + } + } + }, + "recipes": { + "type": "array", + "description": "List of recipes in this cookbook", + "items": { + "type": "object", + "required": ["id", "name", "description"], + "properties": { + "id": { + "type": "string", + "description": "Recipe identifier (matches markdown filename without extension)", + "pattern": "^[a-z0-9-]+$" + }, + "name": { + "type": "string", + "description": "Display name for the recipe" + }, + "description": { + "type": "string", + "description": "Brief description of what the recipe covers" + }, + "tags": { + "type": "array", + "description": "Tags for filtering and categorization", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } +} diff --git a/cookbook/cookbook.yml b/cookbook/cookbook.yml new file mode 100644 index 00000000..a4e94334 --- /dev/null +++ b/cookbook/cookbook.yml @@ -0,0 +1,63 @@ +# yaml-language-server: $schema=../.schemas/cookbook.schema.json +# Cookbook manifest for the Awesome GitHub Copilot website +# This file defines the structure of cookbooks and recipes for the Samples page + +cookbooks: + - id: copilot-sdk + name: GitHub Copilot SDK + description: Ready-to-use recipes for building with the GitHub Copilot SDK across multiple languages + path: cookbook/copilot-sdk + featured: true + languages: + - id: nodejs + name: Node.js / TypeScript + icon: 🟢 + extension: .ts + - id: python + name: Python + icon: 🐍 + extension: .py + - id: dotnet + name: .NET (C#) + icon: 🟣 + extension: .cs + - id: go + name: Go + icon: 🔵 + extension: .go + recipes: + - id: error-handling + name: Error Handling + description: Handle errors gracefully including connection failures, timeouts, and cleanup + tags: + - errors + - basics + - reliability + - id: multiple-sessions + name: Multiple Sessions + description: Manage multiple independent conversations simultaneously + tags: + - sessions + - advanced + - concurrency + - id: managing-local-files + name: Managing Local Files + description: Organize files by metadata using AI-powered grouping strategies + tags: + - files + - organization + - ai-powered + - id: pr-visualization + name: PR Visualization + description: Generate interactive PR age charts using GitHub MCP Server + tags: + - github + - visualization + - mcp + - id: persisting-sessions + name: Persisting Sessions + description: Save and resume sessions across restarts + tags: + - sessions + - persistence + - state-management diff --git a/eng/constants.mjs b/eng/constants.mjs index a690076e..180980a2 100644 --- a/eng/constants.mjs +++ b/eng/constants.mjs @@ -123,6 +123,7 @@ const PROMPTS_DIR = path.join(ROOT_FOLDER, "prompts"); const AGENTS_DIR = path.join(ROOT_FOLDER, "agents"); const SKILLS_DIR = path.join(ROOT_FOLDER, "skills"); const COLLECTIONS_DIR = path.join(ROOT_FOLDER, "collections"); +const COOKBOOK_DIR = path.join(ROOT_FOLDER, "cookbook"); const MAX_COLLECTION_ITEMS = 50; // Agent Skills validation constants @@ -145,6 +146,7 @@ export { AGENTS_DIR, SKILLS_DIR, COLLECTIONS_DIR, + COOKBOOK_DIR, MAX_COLLECTION_ITEMS, SKILL_NAME_MIN_LENGTH, SKILL_NAME_MAX_LENGTH, diff --git a/eng/generate-website-data.mjs b/eng/generate-website-data.mjs index ed7d09b1..ae8e2ec2 100644 --- a/eng/generate-website-data.mjs +++ b/eng/generate-website-data.mjs @@ -16,6 +16,7 @@ import { PROMPTS_DIR, SKILLS_DIR, COLLECTIONS_DIR, + COOKBOOK_DIR, ROOT_FOLDER, } from "./constants.mjs"; import { @@ -559,6 +560,89 @@ function generateSearchIndex(agents, prompts, instructions, skills, collections) return index; } +/** + * Generate samples/cookbook data from cookbook.yml + */ +function generateSamplesData() { + const cookbookYamlPath = path.join(COOKBOOK_DIR, "cookbook.yml"); + + if (!fs.existsSync(cookbookYamlPath)) { + console.warn("Warning: cookbook/cookbook.yml not found, skipping samples generation"); + return { cookbooks: [], totalRecipes: 0, totalCookbooks: 0, filters: { languages: [], tags: [] } }; + } + + const cookbookManifest = parseYamlFile(cookbookYamlPath); + if (!cookbookManifest || !cookbookManifest.cookbooks) { + console.warn("Warning: Invalid cookbook.yml format"); + return { cookbooks: [], totalRecipes: 0, totalCookbooks: 0, filters: { languages: [], tags: [] } }; + } + + const allLanguages = new Set(); + const allTags = new Set(); + let totalRecipes = 0; + + const cookbooks = cookbookManifest.cookbooks.map(cookbook => { + // Collect languages + cookbook.languages.forEach(lang => allLanguages.add(lang.id)); + + // Process recipes and add file paths + const recipes = cookbook.recipes.map(recipe => { + // Collect tags + if (recipe.tags) { + recipe.tags.forEach(tag => allTags.add(tag)); + } + + // Build variants with file paths for each language + const variants = {}; + cookbook.languages.forEach(lang => { + const docPath = `${cookbook.path}/${lang.id}/${recipe.id}.md`; + const examplePath = `${cookbook.path}/${lang.id}/recipe/${recipe.id}${lang.extension}`; + + // Check if files exist + const docFullPath = path.join(ROOT_FOLDER, docPath); + const exampleFullPath = path.join(ROOT_FOLDER, examplePath); + + if (fs.existsSync(docFullPath)) { + variants[lang.id] = { + doc: docPath, + example: fs.existsSync(exampleFullPath) ? examplePath : null + }; + } + }); + + totalRecipes++; + + return { + id: recipe.id, + name: recipe.name, + description: recipe.description, + tags: recipe.tags || [], + variants + }; + }); + + return { + id: cookbook.id, + name: cookbook.name, + description: cookbook.description, + path: cookbook.path, + featured: cookbook.featured || false, + languages: cookbook.languages, + recipes + }; + }); + + return { + cookbooks, + totalRecipes, + totalCookbooks: cookbooks.length, + filters: { + languages: Array.from(allLanguages).sort(), + tags: Array.from(allTags).sort() + } + }; +} + /** * Main function */ @@ -592,6 +676,9 @@ async function main() { const tools = toolsData.items; console.log(`✓ Generated ${tools.length} tools (${toolsData.filters.categories.length} categories)`); + const samplesData = generateSamplesData(); + console.log(`✓ Generated ${samplesData.totalRecipes} recipes in ${samplesData.totalCookbooks} cookbooks (${samplesData.filters.languages.length} languages, ${samplesData.filters.tags.length} tags)`); + const searchIndex = generateSearchIndex(agents, prompts, instructions, skills, collections); console.log(`✓ Generated search index with ${searchIndex.length} items`); @@ -626,6 +713,11 @@ async function main() { JSON.stringify(toolsData, null, 2) ); + fs.writeFileSync( + path.join(WEBSITE_DATA_DIR, "samples.json"), + JSON.stringify(samplesData, null, 2) + ); + fs.writeFileSync( path.join(WEBSITE_DATA_DIR, "search-index.json"), JSON.stringify(searchIndex, null, 2) @@ -641,6 +733,7 @@ async function main() { skills: skills.length, collections: collections.length, tools: tools.length, + samples: samplesData.totalRecipes, total: searchIndex.length, }, }; diff --git a/website/public/data/agents.json b/website/public/data/agents.json index e3f7dde6..ad114985 100644 --- a/website/public/data/agents.json +++ b/website/public/data/agents.json @@ -148,6 +148,24 @@ "path": "agents/apify-integration-expert.agent.md", "filename": "apify-integration-expert.agent.md" }, + { + "id": "arch-linux-expert", + "title": "Arch Linux Expert", + "description": "Arch Linux specialist focused on pacman, rolling-release maintenance, and Arch-centric system administration workflows.", + "model": "GPT-5", + "tools": [ + "codebase", + "search", + "terminalCommand", + "runCommands", + "edit/editFiles" + ], + "hasHandoffs": false, + "handoffs": [], + "mcpServers": [], + "path": "agents/arch-linux-expert.agent.md", + "filename": "arch-linux-expert.agent.md" + }, { "id": "arm-migration", "title": "Arm Migration Agent", @@ -569,6 +587,24 @@ "path": "agents/cast-imaging-structural-quality-advisor.agent.md", "filename": "cast-imaging-structural-quality-advisor.agent.md" }, + { + "id": "centos-linux-expert", + "title": "CentOS Linux Expert", + "description": "CentOS (Stream/Legacy) Linux specialist focused on RHEL-compatible administration, yum/dnf workflows, and enterprise hardening.", + "model": "GPT-4.1", + "tools": [ + "codebase", + "search", + "terminalCommand", + "runCommands", + "edit/editFiles" + ], + "hasHandoffs": false, + "handoffs": [], + "mcpServers": [], + "path": "agents/centos-linux-expert.agent.md", + "filename": "centos-linux-expert.agent.md" + }, { "id": "clojure-interactive-programming", "title": "Clojure Interactive Programming", @@ -730,6 +766,24 @@ "path": "agents/custom-agent-foundry.agent.md", "filename": "custom-agent-foundry.agent.md" }, + { + "id": "debian-linux-expert", + "title": "Debian Linux Expert", + "description": "Debian Linux specialist focused on stable system administration, apt-based package management, and Debian policy-aligned practices.", + "model": "Claude Sonnet 4", + "tools": [ + "codebase", + "search", + "terminalCommand", + "runCommands", + "edit/editFiles" + ], + "hasHandoffs": false, + "handoffs": [], + "mcpServers": [], + "path": "agents/debian-linux-expert.agent.md", + "filename": "debian-linux-expert.agent.md" + }, { "id": "debug", "title": "Debug", @@ -1103,6 +1157,24 @@ "path": "agents/expert-react-frontend-engineer.agent.md", "filename": "expert-react-frontend-engineer.agent.md" }, + { + "id": "fedora-linux-expert", + "title": "Fedora Linux Expert", + "description": "Fedora (Red Hat family) Linux specialist focused on dnf, SELinux, and modern systemd-based workflows.", + "model": "GPT-5", + "tools": [ + "codebase", + "search", + "terminalCommand", + "runCommands", + "edit/editFiles" + ], + "hasHandoffs": false, + "handoffs": [], + "mcpServers": [], + "path": "agents/fedora-linux-expert.agent.md", + "filename": "fedora-linux-expert.agent.md" + }, { "id": "gilfoyle", "title": "Gilfoyle", @@ -2232,6 +2304,28 @@ "path": "agents/refine-issue.agent.md", "filename": "refine-issue.agent.md" }, + { + "id": "repo-architect", + "title": "Repo Architect", + "description": "Bootstraps and validates agentic project structures for GitHub Copilot (VS Code) and OpenCode CLI workflows. Run after `opencode /init` or VS Code Copilot initialization to scaffold proper folder hierarchies, instructions, agents, skills, and prompts.", + "model": "GPT-4.1", + "tools": [ + "changes", + "codebase", + "editFiles", + "fetch", + "new", + "problems", + "runCommands", + "search", + "terminalLastCommand" + ], + "hasHandoffs": false, + "handoffs": [], + "mcpServers": [], + "path": "agents/repo-architect.agent.md", + "filename": "repo-architect.agent.md" + }, { "id": "ruby-mcp-expert", "title": "Ruby MCP Expert", diff --git a/website/public/data/collections.json b/website/public/data/collections.json index 5c06764b..f48912b8 100644 --- a/website/public/data/collections.json +++ b/website/public/data/collections.json @@ -78,6 +78,11 @@ "path": "instructions/copilot-sdk-python.instructions.md", "kind": "instruction", "usage": null + }, + { + "path": "skills/copilot-sdk/SKILL.md", + "kind": "skill", + "usage": null } ], "path": "collections/copilot-sdk.collection.yml", diff --git a/website/public/data/instructions.json b/website/public/data/instructions.json index 6852cab1..20a825f1 100644 --- a/website/public/data/instructions.json +++ b/website/public/data/instructions.json @@ -113,6 +113,18 @@ "path": "instructions/apex.instructions.md", "filename": "apex.instructions.md" }, + { + "id": "arch-linux", + "title": "Arch Linux", + "description": "Guidance for Arch Linux administration, pacman workflows, and rolling-release best practices.", + "applyTo": "**", + "applyToPatterns": [ + "**" + ], + "extensions": [], + "path": "instructions/arch-linux.instructions.md", + "filename": "arch-linux.instructions.md" + }, { "id": "aspnet-rest-apis", "title": "Aspnet Rest Apis", @@ -272,6 +284,18 @@ "path": "instructions/blazor.instructions.md", "filename": "blazor.instructions.md" }, + { + "id": "centos-linux", + "title": "Centos Linux", + "description": "Guidance for CentOS administration, RHEL-compatible tooling, and SELinux-aware operations.", + "applyTo": "**", + "applyToPatterns": [ + "**" + ], + "extensions": [], + "path": "instructions/centos-linux.instructions.md", + "filename": "centos-linux.instructions.md" + }, { "id": "clojure", "title": "Clojure", @@ -675,6 +699,18 @@ "path": "instructions/dataverse-python-testing-debugging.instructions.md", "filename": "dataverse-python-testing-debugging.instructions.md" }, + { + "id": "debian-linux", + "title": "Debian Linux", + "description": "Guidance for Debian-based Linux administration, apt workflows, and Debian policy conventions.", + "applyTo": "**", + "applyToPatterns": [ + "**" + ], + "extensions": [], + "path": "instructions/debian-linux.instructions.md", + "filename": "debian-linux.instructions.md" + }, { "id": "declarative-agents-microsoft365", "title": "Declarative Agents Microsoft365", @@ -807,6 +843,18 @@ "path": "instructions/dotnet-wpf.instructions.md", "filename": "dotnet-wpf.instructions.md" }, + { + "id": "fedora-linux", + "title": "Fedora Linux", + "description": "Guidance for Fedora (Red Hat family) systems, dnf workflows, SELinux, and modern systemd practices.", + "applyTo": "**", + "applyToPatterns": [ + "**" + ], + "extensions": [], + "path": "instructions/fedora-linux.instructions.md", + "filename": "fedora-linux.instructions.md" + }, { "id": "genaiscript", "title": "Genaiscript", diff --git a/website/public/data/manifest.json b/website/public/data/manifest.json index c195cb95..e3178a77 100644 --- a/website/public/data/manifest.json +++ b/website/public/data/manifest.json @@ -1,12 +1,13 @@ { - "generated": "2026-02-02T02:45:34.292Z", + "generated": "2026-02-02T04:05:33.889Z", "counts": { - "agents": 140, - "prompts": 134, - "instructions": 163, - "skills": 28, + "agents": 145, + "prompts": 138, + "instructions": 167, + "skills": 32, "collections": 39, "tools": 6, - "total": 504 + "samples": 5, + "total": 521 } } \ No newline at end of file diff --git a/website/public/data/prompts.json b/website/public/data/prompts.json index 4d371b5b..773ca3eb 100644 --- a/website/public/data/prompts.json +++ b/website/public/data/prompts.json @@ -53,6 +53,21 @@ "path": "prompts/apple-appstore-reviewer.prompt.md", "filename": "apple-appstore-reviewer.prompt.md" }, + { + "id": "arch-linux-triage", + "title": "Arch Linux Triage", + "description": "Triage and resolve Arch Linux issues with pacman, systemd, and rolling-release best practices.", + "agent": "agent", + "model": "gpt-4.1", + "tools": [ + "search", + "runCommands", + "terminalCommand", + "edit/editFiles" + ], + "path": "prompts/arch-linux-triage.prompt.md", + "filename": "arch-linux-triage.prompt.md" + }, { "id": "architecture-blueprint-generator", "title": "Architecture Blueprint Generator", @@ -168,6 +183,21 @@ "path": "prompts/breakdown-test.prompt.md", "filename": "breakdown-test.prompt.md" }, + { + "id": "centos-linux-triage", + "title": "Centos Linux Triage", + "description": "Triage and resolve CentOS issues using RHEL-compatible tooling, SELinux-aware practices, and firewalld.", + "agent": "agent", + "model": "gpt-4.1", + "tools": [ + "search", + "runCommands", + "terminalCommand", + "edit/editFiles" + ], + "path": "prompts/centos-linux-triage.prompt.md", + "filename": "centos-linux-triage.prompt.md" + }, { "id": "code-exemplars-blueprint-generator", "title": "Code Exemplars Blueprint Generator", @@ -731,6 +761,21 @@ "path": "prompts/dataverse-python-quickstart.prompt.md", "filename": "dataverse-python-quickstart.prompt.md" }, + { + "id": "debian-linux-triage", + "title": "Debian Linux Triage", + "description": "Triage and resolve Debian Linux issues with apt, systemd, and AppArmor-aware guidance.", + "agent": "agent", + "model": "gpt-4.1", + "tools": [ + "search", + "runCommands", + "terminalCommand", + "edit/editFiles" + ], + "path": "prompts/debian-linux-triage.prompt.md", + "filename": "debian-linux-triage.prompt.md" + }, { "id": "declarative-agents", "title": "Declarative Agents", @@ -816,6 +861,21 @@ "path": "prompts/ef-core.prompt.md", "filename": "ef-core.prompt.md" }, + { + "id": "fedora-linux-triage", + "title": "Fedora Linux Triage", + "description": "Triage and resolve Fedora issues with dnf, systemd, and SELinux-aware guidance.", + "agent": "agent", + "model": "gpt-4.1", + "tools": [ + "search", + "runCommands", + "terminalCommand", + "edit/editFiles" + ], + "path": "prompts/fedora-linux-triage.prompt.md", + "filename": "fedora-linux-triage.prompt.md" + }, { "id": "finalize-agent-prompt", "title": "Finalize Agent Prompt", diff --git a/website/public/data/samples.json b/website/public/data/samples.json new file mode 100644 index 00000000..ed525bc8 --- /dev/null +++ b/website/public/data/samples.json @@ -0,0 +1,205 @@ +{ + "cookbooks": [ + { + "id": "copilot-sdk", + "name": "GitHub Copilot SDK", + "description": "Ready-to-use recipes for building with the GitHub Copilot SDK across multiple languages", + "path": "cookbook/copilot-sdk", + "featured": true, + "languages": [ + { + "id": "nodejs", + "name": "Node.js / TypeScript", + "icon": "🟢", + "extension": ".ts" + }, + { + "id": "python", + "name": "Python", + "icon": "🐍", + "extension": ".py" + }, + { + "id": "dotnet", + "name": ".NET (C#)", + "icon": "🟣", + "extension": ".cs" + }, + { + "id": "go", + "name": "Go", + "icon": "🔵", + "extension": ".go" + } + ], + "recipes": [ + { + "id": "error-handling", + "name": "Error Handling", + "description": "Handle errors gracefully including connection failures, timeouts, and cleanup", + "tags": [ + "errors", + "basics", + "reliability" + ], + "variants": { + "nodejs": { + "doc": "cookbook/copilot-sdk/nodejs/error-handling.md", + "example": "cookbook/copilot-sdk/nodejs/recipe/error-handling.ts" + }, + "python": { + "doc": "cookbook/copilot-sdk/python/error-handling.md", + "example": null + }, + "dotnet": { + "doc": "cookbook/copilot-sdk/dotnet/error-handling.md", + "example": "cookbook/copilot-sdk/dotnet/recipe/error-handling.cs" + }, + "go": { + "doc": "cookbook/copilot-sdk/go/error-handling.md", + "example": "cookbook/copilot-sdk/go/recipe/error-handling.go" + } + } + }, + { + "id": "multiple-sessions", + "name": "Multiple Sessions", + "description": "Manage multiple independent conversations simultaneously", + "tags": [ + "sessions", + "advanced", + "concurrency" + ], + "variants": { + "nodejs": { + "doc": "cookbook/copilot-sdk/nodejs/multiple-sessions.md", + "example": "cookbook/copilot-sdk/nodejs/recipe/multiple-sessions.ts" + }, + "python": { + "doc": "cookbook/copilot-sdk/python/multiple-sessions.md", + "example": null + }, + "dotnet": { + "doc": "cookbook/copilot-sdk/dotnet/multiple-sessions.md", + "example": "cookbook/copilot-sdk/dotnet/recipe/multiple-sessions.cs" + }, + "go": { + "doc": "cookbook/copilot-sdk/go/multiple-sessions.md", + "example": "cookbook/copilot-sdk/go/recipe/multiple-sessions.go" + } + } + }, + { + "id": "managing-local-files", + "name": "Managing Local Files", + "description": "Organize files by metadata using AI-powered grouping strategies", + "tags": [ + "files", + "organization", + "ai-powered" + ], + "variants": { + "nodejs": { + "doc": "cookbook/copilot-sdk/nodejs/managing-local-files.md", + "example": "cookbook/copilot-sdk/nodejs/recipe/managing-local-files.ts" + }, + "python": { + "doc": "cookbook/copilot-sdk/python/managing-local-files.md", + "example": null + }, + "dotnet": { + "doc": "cookbook/copilot-sdk/dotnet/managing-local-files.md", + "example": "cookbook/copilot-sdk/dotnet/recipe/managing-local-files.cs" + }, + "go": { + "doc": "cookbook/copilot-sdk/go/managing-local-files.md", + "example": "cookbook/copilot-sdk/go/recipe/managing-local-files.go" + } + } + }, + { + "id": "pr-visualization", + "name": "PR Visualization", + "description": "Generate interactive PR age charts using GitHub MCP Server", + "tags": [ + "github", + "visualization", + "mcp" + ], + "variants": { + "nodejs": { + "doc": "cookbook/copilot-sdk/nodejs/pr-visualization.md", + "example": "cookbook/copilot-sdk/nodejs/recipe/pr-visualization.ts" + }, + "python": { + "doc": "cookbook/copilot-sdk/python/pr-visualization.md", + "example": null + }, + "dotnet": { + "doc": "cookbook/copilot-sdk/dotnet/pr-visualization.md", + "example": "cookbook/copilot-sdk/dotnet/recipe/pr-visualization.cs" + }, + "go": { + "doc": "cookbook/copilot-sdk/go/pr-visualization.md", + "example": "cookbook/copilot-sdk/go/recipe/pr-visualization.go" + } + } + }, + { + "id": "persisting-sessions", + "name": "Persisting Sessions", + "description": "Save and resume sessions across restarts", + "tags": [ + "sessions", + "persistence", + "state-management" + ], + "variants": { + "nodejs": { + "doc": "cookbook/copilot-sdk/nodejs/persisting-sessions.md", + "example": "cookbook/copilot-sdk/nodejs/recipe/persisting-sessions.ts" + }, + "python": { + "doc": "cookbook/copilot-sdk/python/persisting-sessions.md", + "example": null + }, + "dotnet": { + "doc": "cookbook/copilot-sdk/dotnet/persisting-sessions.md", + "example": "cookbook/copilot-sdk/dotnet/recipe/persisting-sessions.cs" + }, + "go": { + "doc": "cookbook/copilot-sdk/go/persisting-sessions.md", + "example": "cookbook/copilot-sdk/go/recipe/persisting-sessions.go" + } + } + } + ] + } + ], + "totalRecipes": 5, + "totalCookbooks": 1, + "filters": { + "languages": [ + "dotnet", + "go", + "nodejs", + "python" + ], + "tags": [ + "advanced", + "ai-powered", + "basics", + "concurrency", + "errors", + "files", + "github", + "mcp", + "organization", + "persistence", + "reliability", + "sessions", + "state-management", + "visualization" + ] + } +} \ No newline at end of file diff --git a/website/public/data/search-index.json b/website/public/data/search-index.json index 2c7fea50..6adc55e9 100644 --- a/website/public/data/search-index.json +++ b/website/public/data/search-index.json @@ -63,6 +63,14 @@ "path": "agents/apify-integration-expert.agent.md", "searchText": "apify integration expert expert agent for integrating apify actors into codebases. handles actor selection, workflow design, implementation across javascript/typescript and python, testing, and production-ready deployment. " }, + { + "type": "agent", + "id": "arch-linux-expert", + "title": "Arch Linux Expert", + "description": "Arch Linux specialist focused on pacman, rolling-release maintenance, and Arch-centric system administration workflows.", + "path": "agents/arch-linux-expert.agent.md", + "searchText": "arch linux expert arch linux specialist focused on pacman, rolling-release maintenance, and arch-centric system administration workflows. codebase search terminalcommand runcommands edit/editfiles" + }, { "type": "agent", "id": "arm-migration", @@ -223,6 +231,14 @@ "path": "agents/cast-imaging-structural-quality-advisor.agent.md", "searchText": "cast imaging structural quality advisor agent specialized agent for identifying, analyzing, and providing remediation guidance for code quality issues using cast imaging " }, + { + "type": "agent", + "id": "centos-linux-expert", + "title": "CentOS Linux Expert", + "description": "CentOS (Stream/Legacy) Linux specialist focused on RHEL-compatible administration, yum/dnf workflows, and enterprise hardening.", + "path": "agents/centos-linux-expert.agent.md", + "searchText": "centos linux expert centos (stream/legacy) linux specialist focused on rhel-compatible administration, yum/dnf workflows, and enterprise hardening. codebase search terminalcommand runcommands edit/editfiles" + }, { "type": "agent", "id": "clojure-interactive-programming", @@ -279,6 +295,14 @@ "path": "agents/custom-agent-foundry.agent.md", "searchText": "custom agent foundry expert at designing and creating vs code custom agents with optimal configurations vscode execute read edit search web agent github/* todo" }, + { + "type": "agent", + "id": "debian-linux-expert", + "title": "Debian Linux Expert", + "description": "Debian Linux specialist focused on stable system administration, apt-based package management, and Debian policy-aligned practices.", + "path": "agents/debian-linux-expert.agent.md", + "searchText": "debian linux expert debian linux specialist focused on stable system administration, apt-based package management, and debian policy-aligned practices. codebase search terminalcommand runcommands edit/editfiles" + }, { "type": "agent", "id": "debug", @@ -407,6 +431,14 @@ "path": "agents/expert-react-frontend-engineer.agent.md", "searchText": "expert react frontend engineer expert react 19.2 frontend engineer specializing in modern hooks, server components, actions, typescript, and performance optimization changes codebase edit/editfiles extensions fetch findtestfiles githubrepo new opensimplebrowser problems runcommands runtasks runtests search searchresults terminallastcommand terminalselection testfailure usages vscodeapi microsoft.docs.mcp" }, + { + "type": "agent", + "id": "fedora-linux-expert", + "title": "Fedora Linux Expert", + "description": "Fedora (Red Hat family) Linux specialist focused on dnf, SELinux, and modern systemd-based workflows.", + "path": "agents/fedora-linux-expert.agent.md", + "searchText": "fedora linux expert fedora (red hat family) linux specialist focused on dnf, selinux, and modern systemd-based workflows. codebase search terminalcommand runcommands edit/editfiles" + }, { "type": "agent", "id": "gilfoyle", @@ -807,6 +839,14 @@ "path": "agents/refine-issue.agent.md", "searchText": "refine issue refine the requirement or issue with acceptance criteria, technical considerations, edge cases, and nfrs list_issues githubrepo search add_issue_comment create_issue create_issue_comment update_issue delete_issue get_issue search_issues" }, + { + "type": "agent", + "id": "repo-architect", + "title": "Repo Architect", + "description": "Bootstraps and validates agentic project structures for GitHub Copilot (VS Code) and OpenCode CLI workflows. Run after `opencode /init` or VS Code Copilot initialization to scaffold proper folder hierarchies, instructions, agents, skills, and prompts.", + "path": "agents/repo-architect.agent.md", + "searchText": "repo architect bootstraps and validates agentic project structures for github copilot (vs code) and opencode cli workflows. run after `opencode /init` or vs code copilot initialization to scaffold proper folder hierarchies, instructions, agents, skills, and prompts. changes codebase editfiles fetch new problems runcommands search terminallastcommand" + }, { "type": "agent", "id": "ruby-mcp-expert", @@ -1151,6 +1191,14 @@ "path": "prompts/apple-appstore-reviewer.prompt.md", "searchText": "apple app store reviewer serves as a reviewer of the codebase with instructions on looking for apple app store optimizations or rejection reasons." }, + { + "type": "prompt", + "id": "arch-linux-triage", + "title": "Arch Linux Triage", + "description": "Triage and resolve Arch Linux issues with pacman, systemd, and rolling-release best practices.", + "path": "prompts/arch-linux-triage.prompt.md", + "searchText": "arch linux triage triage and resolve arch linux issues with pacman, systemd, and rolling-release best practices." + }, { "type": "prompt", "id": "architecture-blueprint-generator", @@ -1239,6 +1287,14 @@ "path": "prompts/breakdown-test.prompt.md", "searchText": "breakdown test test planning and quality assurance prompt that generates comprehensive test strategies, task breakdowns, and quality validation plans for github projects." }, + { + "type": "prompt", + "id": "centos-linux-triage", + "title": "Centos Linux Triage", + "description": "Triage and resolve CentOS issues using RHEL-compatible tooling, SELinux-aware practices, and firewalld.", + "path": "prompts/centos-linux-triage.prompt.md", + "searchText": "centos linux triage triage and resolve centos issues using rhel-compatible tooling, selinux-aware practices, and firewalld." + }, { "type": "prompt", "id": "code-exemplars-blueprint-generator", @@ -1519,6 +1575,14 @@ "path": "prompts/dataverse-python-quickstart.prompt.md", "searchText": "dataverse python quickstart generator generate python sdk setup + crud + bulk + paging snippets using official patterns." }, + { + "type": "prompt", + "id": "debian-linux-triage", + "title": "Debian Linux Triage", + "description": "Triage and resolve Debian Linux issues with apt, systemd, and AppArmor-aware guidance.", + "path": "prompts/debian-linux-triage.prompt.md", + "searchText": "debian linux triage triage and resolve debian linux issues with apt, systemd, and apparmor-aware guidance." + }, { "type": "prompt", "id": "declarative-agents", @@ -1575,6 +1639,14 @@ "path": "prompts/ef-core.prompt.md", "searchText": "ef core get best practices for entity framework core" }, + { + "type": "prompt", + "id": "fedora-linux-triage", + "title": "Fedora Linux Triage", + "description": "Triage and resolve Fedora issues with dnf, systemd, and SELinux-aware guidance.", + "path": "prompts/fedora-linux-triage.prompt.md", + "searchText": "fedora linux triage triage and resolve fedora issues with dnf, systemd, and selinux-aware guidance." + }, { "type": "prompt", "id": "finalize-agent-prompt", @@ -2255,6 +2327,14 @@ "path": "instructions/apex.instructions.md", "searchText": "apex guidelines and best practices for apex development on the salesforce platform **/*.cls, **/*.trigger" }, + { + "type": "instruction", + "id": "arch-linux", + "title": "Arch Linux", + "description": "Guidance for Arch Linux administration, pacman workflows, and rolling-release best practices.", + "path": "instructions/arch-linux.instructions.md", + "searchText": "arch linux guidance for arch linux administration, pacman workflows, and rolling-release best practices. **" + }, { "type": "instruction", "id": "aspnet-rest-apis", @@ -2327,6 +2407,14 @@ "path": "instructions/blazor.instructions.md", "searchText": "blazor blazor component and application patterns **/*.razor, **/*.razor.cs, **/*.razor.css" }, + { + "type": "instruction", + "id": "centos-linux", + "title": "Centos Linux", + "description": "Guidance for CentOS administration, RHEL-compatible tooling, and SELinux-aware operations.", + "path": "instructions/centos-linux.instructions.md", + "searchText": "centos linux guidance for centos administration, rhel-compatible tooling, and selinux-aware operations. **" + }, { "type": "instruction", "id": "clojure", @@ -2567,6 +2655,14 @@ "path": "instructions/dataverse-python-testing-debugging.instructions.md", "searchText": "dataverse python testing debugging **" }, + { + "type": "instruction", + "id": "debian-linux", + "title": "Debian Linux", + "description": "Guidance for Debian-based Linux administration, apt workflows, and Debian policy conventions.", + "path": "instructions/debian-linux.instructions.md", + "searchText": "debian linux guidance for debian-based linux administration, apt workflows, and debian policy conventions. **" + }, { "type": "instruction", "id": "declarative-agents-microsoft365", @@ -2631,6 +2727,14 @@ "path": "instructions/dotnet-wpf.instructions.md", "searchText": "dotnet wpf .net wpf component and application patterns **/*.xaml, **/*.cs" }, + { + "type": "instruction", + "id": "fedora-linux", + "title": "Fedora Linux", + "description": "Guidance for Fedora (Red Hat family) systems, dnf workflows, SELinux, and modern systemd practices.", + "path": "instructions/fedora-linux.instructions.md", + "searchText": "fedora linux guidance for fedora (red hat family) systems, dnf workflows, selinux, and modern systemd practices. **" + }, { "type": "instruction", "id": "genaiscript", @@ -3559,6 +3663,14 @@ "path": "skills/chrome-devtools", "searchText": "chrome devtools expert-level browser automation, debugging, and performance analysis using chrome devtools mcp. use for interacting with web pages, capturing screenshots, analyzing network traffic, and profiling performance." }, + { + "type": "skill", + "id": "copilot-sdk", + "title": "Copilot Sdk", + "description": "Build agentic applications with GitHub Copilot SDK. Use when embedding AI agents in apps, creating custom tools, implementing streaming responses, managing sessions, connecting to MCP servers, or creating custom agents. Triggers on Copilot SDK, GitHub SDK, agentic app, embed Copilot, programmable agent, MCP server, custom agent.", + "path": "skills/copilot-sdk", + "searchText": "copilot sdk build agentic applications with github copilot sdk. use when embedding ai agents in apps, creating custom tools, implementing streaming responses, managing sessions, connecting to mcp servers, or creating custom agents. triggers on copilot sdk, github sdk, agentic app, embed copilot, programmable agent, mcp server, custom agent." + }, { "type": "skill", "id": "gh-cli", @@ -3607,6 +3719,14 @@ "path": "skills/make-skill-template", "searchText": "make skill template create new agent skills for github copilot from prompts or by duplicating this template. use when asked to \"create a skill\", \"make a new skill\", \"scaffold a skill\", or when building specialized ai capabilities with bundled resources. generates skill.md files with proper frontmatter, directory structure, and optional scripts/references/assets folders." }, + { + "type": "skill", + "id": "markdown-to-html", + "title": "Markdown To Html", + "description": "Convert Markdown files to HTML similar to `marked.js`, `pandoc`, `gomarkdown/markdown`, or similar tools; or writing custom script to convert markdown to html and/or working on web template systems like `jekyll/jekyll`, `gohugoio/hugo`, or similar web templating systems that utilize markdown documents, converting them to html. Use when asked to \"convert markdown to html\", \"transform md to html\", \"render markdown\", \"generate html from markdown\", or when working with .md files and/or web a templating system that converts markdown to HTML output. Supports CLI and Node.js workflows with GFM, CommonMark, and standard Markdown flavors.", + "path": "skills/markdown-to-html", + "searchText": "markdown to html convert markdown files to html similar to `marked.js`, `pandoc`, `gomarkdown/markdown`, or similar tools; or writing custom script to convert markdown to html and/or working on web template systems like `jekyll/jekyll`, `gohugoio/hugo`, or similar web templating systems that utilize markdown documents, converting them to html. use when asked to \"convert markdown to html\", \"transform md to html\", \"render markdown\", \"generate html from markdown\", or when working with .md files and/or web a templating system that converts markdown to html output. supports cli and node.js workflows with gfm, commonmark, and standard markdown flavors." + }, { "type": "skill", "id": "mcp-cli", @@ -3679,6 +3799,14 @@ "path": "skills/snowflake-semanticview", "searchText": "snowflake semanticview create, alter, and validate snowflake semantic views using snowflake cli (snow). use when asked to build or troubleshoot semantic views/semantic layer definitions with create/alter semantic view, to validate semantic-view ddl against snowflake via cli, or to guide snowflake cli installation and connection setup." }, + { + "type": "skill", + "id": "terraform-azurerm-set-diff-analyzer", + "title": "Terraform Azurerm Set Diff Analyzer", + "description": "Analyze Terraform plan JSON output for AzureRM Provider to distinguish between false-positive diffs (order-only changes in Set-type attributes) and actual resource changes. Use when reviewing terraform plan output for Azure resources like Application Gateway, Load Balancer, Firewall, Front Door, NSG, and other resources with Set-type attributes that cause spurious diffs due to internal ordering changes.", + "path": "skills/terraform-azurerm-set-diff-analyzer", + "searchText": "terraform azurerm set diff analyzer analyze terraform plan json output for azurerm provider to distinguish between false-positive diffs (order-only changes in set-type attributes) and actual resource changes. use when reviewing terraform plan output for azure resources like application gateway, load balancer, firewall, front door, nsg, and other resources with set-type attributes that cause spurious diffs due to internal ordering changes." + }, { "type": "skill", "id": "vscode-ext-commands", @@ -3711,6 +3839,14 @@ "path": "skills/webapp-testing", "searchText": "webapp testing toolkit for interacting with and testing local web applications using playwright. supports verifying frontend functionality, debugging ui behavior, capturing browser screenshots, and viewing browser logs." }, + { + "type": "skill", + "id": "winapp-cli", + "title": "Winapp Cli", + "description": "Windows App Development CLI (winapp) for building, packaging, and deploying Windows applications. Use when asked to initialize Windows app projects, create MSIX packages, generate AppxManifest.xml, manage development certificates, add package identity for debugging, sign packages, or access Windows SDK build tools. Supports .NET, C++, Electron, Rust, Tauri, and cross-platform frameworks targeting Windows.", + "path": "skills/winapp-cli", + "searchText": "winapp cli windows app development cli (winapp) for building, packaging, and deploying windows applications. use when asked to initialize windows app projects, create msix packages, generate appxmanifest.xml, manage development certificates, add package identity for debugging, sign packages, or access windows sdk build tools. supports .net, c++, electron, rust, tauri, and cross-platform frameworks targeting windows." + }, { "type": "skill", "id": "workiq-copilot", diff --git a/website/public/data/skills.json b/website/public/data/skills.json index 40531df4..2fe886b7 100644 --- a/website/public/data/skills.json +++ b/website/public/data/skills.json @@ -234,6 +234,25 @@ } ] }, + { + "id": "copilot-sdk", + "name": "copilot-sdk", + "title": "Copilot Sdk", + "description": "Build agentic applications with GitHub Copilot SDK. Use when embedding AI agents in apps, creating custom tools, implementing streaming responses, managing sessions, connecting to MCP servers, or creating custom agents. Triggers on Copilot SDK, GitHub SDK, agentic app, embed Copilot, programmable agent, MCP server, custom agent.", + "assets": [], + "hasAssets": false, + "assetCount": 0, + "category": "Git & GitHub", + "path": "skills/copilot-sdk", + "skillFile": "skills/copilot-sdk/SKILL.md", + "files": [ + { + "path": "skills/copilot-sdk/SKILL.md", + "name": "SKILL.md", + "size": 22409 + } + ] + }, { "id": "gh-cli", "name": "gh-cli", @@ -476,6 +495,116 @@ } ] }, + { + "id": "markdown-to-html", + "name": "markdown-to-html", + "title": "Markdown To Html", + "description": "Convert Markdown files to HTML similar to `marked.js`, `pandoc`, `gomarkdown/markdown`, or similar tools; or writing custom script to convert markdown to html and/or working on web template systems like `jekyll/jekyll`, `gohugoio/hugo`, or similar web templating systems that utilize markdown documents, converting them to html. Use when asked to \"convert markdown to html\", \"transform md to html\", \"render markdown\", \"generate html from markdown\", or when working with .md files and/or web a templating system that converts markdown to HTML output. Supports CLI and Node.js workflows with GFM, CommonMark, and standard Markdown flavors.", + "assets": [ + "references/basic-markdown-to-html.md", + "references/basic-markdown.md", + "references/code-blocks-to-html.md", + "references/code-blocks.md", + "references/collapsed-sections-to-html.md", + "references/collapsed-sections.md", + "references/gomarkdown.md", + "references/hugo.md", + "references/jekyll.md", + "references/marked.md", + "references/pandoc.md", + "references/tables-to-html.md", + "references/tables.md", + "references/writing-mathematical-expressions-to-html.md", + "references/writing-mathematical-expressions.md" + ], + "hasAssets": true, + "assetCount": 15, + "category": "CLI Tools", + "path": "skills/markdown-to-html", + "skillFile": "skills/markdown-to-html/SKILL.md", + "files": [ + { + "path": "skills/markdown-to-html/SKILL.md", + "name": "SKILL.md", + "size": 24632 + }, + { + "path": "skills/markdown-to-html/references/basic-markdown-to-html.md", + "name": "references/basic-markdown-to-html.md", + "size": 4291 + }, + { + "path": "skills/markdown-to-html/references/basic-markdown.md", + "name": "references/basic-markdown.md", + "size": 31397 + }, + { + "path": "skills/markdown-to-html/references/code-blocks-to-html.md", + "name": "references/code-blocks-to-html.md", + "size": 2704 + }, + { + "path": "skills/markdown-to-html/references/code-blocks.md", + "name": "references/code-blocks.md", + "size": 3810 + }, + { + "path": "skills/markdown-to-html/references/collapsed-sections-to-html.md", + "name": "references/collapsed-sections-to-html.md", + "size": 2608 + }, + { + "path": "skills/markdown-to-html/references/collapsed-sections.md", + "name": "references/collapsed-sections.md", + "size": 2787 + }, + { + "path": "skills/markdown-to-html/references/gomarkdown.md", + "name": "references/gomarkdown.md", + "size": 6253 + }, + { + "path": "skills/markdown-to-html/references/hugo.md", + "name": "references/hugo.md", + "size": 7029 + }, + { + "path": "skills/markdown-to-html/references/jekyll.md", + "name": "references/jekyll.md", + "size": 5760 + }, + { + "path": "skills/markdown-to-html/references/marked.md", + "name": "references/marked.md", + "size": 2984 + }, + { + "path": "skills/markdown-to-html/references/pandoc.md", + "name": "references/pandoc.md", + "size": 4123 + }, + { + "path": "skills/markdown-to-html/references/tables-to-html.md", + "name": "references/tables-to-html.md", + "size": 2665 + }, + { + "path": "skills/markdown-to-html/references/tables.md", + "name": "references/tables.md", + "size": 3767 + }, + { + "path": "skills/markdown-to-html/references/writing-mathematical-expressions-to-html.md", + "name": "references/writing-mathematical-expressions-to-html.md", + "size": 6004 + }, + { + "path": "skills/markdown-to-html/references/writing-mathematical-expressions.md", + "name": "references/writing-mathematical-expressions.md", + "size": 4886 + } + ] + }, { "id": "mcp-cli", "name": "mcp-cli", @@ -647,6 +776,56 @@ } ] }, + { + "id": "terraform-azurerm-set-diff-analyzer", + "name": "terraform-azurerm-set-diff-analyzer", + "title": "Terraform Azurerm Set Diff Analyzer", + "description": "Analyze Terraform plan JSON output for AzureRM Provider to distinguish between false-positive diffs (order-only changes in Set-type attributes) and actual resource changes. Use when reviewing terraform plan output for Azure resources like Application Gateway, Load Balancer, Firewall, Front Door, NSG, and other resources with Set-type attributes that cause spurious diffs due to internal ordering changes.", + "assets": [ + "references/azurerm_set_attributes.json", + "references/azurerm_set_attributes.md", + "scripts/.gitignore", + "scripts/README.md", + "scripts/analyze_plan.py" + ], + "hasAssets": true, + "assetCount": 5, + "category": "Azure", + "path": "skills/terraform-azurerm-set-diff-analyzer", + "skillFile": "skills/terraform-azurerm-set-diff-analyzer/SKILL.md", + "files": [ + { + "path": "skills/terraform-azurerm-set-diff-analyzer/SKILL.md", + "name": "SKILL.md", + "size": 2187 + }, + { + "path": "skills/terraform-azurerm-set-diff-analyzer/references/azurerm_set_attributes.json", + "name": "references/azurerm_set_attributes.json", + "size": 5106 + }, + { + "path": "skills/terraform-azurerm-set-diff-analyzer/references/azurerm_set_attributes.md", + "name": "references/azurerm_set_attributes.md", + "size": 3966 + }, + { + "path": "skills/terraform-azurerm-set-diff-analyzer/scripts/.gitignore", + "name": "scripts/.gitignore", + "size": 742 + }, + { + "path": "skills/terraform-azurerm-set-diff-analyzer/scripts/README.md", + "name": "scripts/README.md", + "size": 5306 + }, + { + "path": "skills/terraform-azurerm-set-diff-analyzer/scripts/analyze_plan.py", + "name": "scripts/analyze_plan.py", + "size": 30996 + } + ] + }, { "id": "vscode-ext-commands", "name": "vscode-ext-commands", @@ -743,6 +922,25 @@ } ] }, + { + "id": "winapp-cli", + "name": "winapp-cli", + "title": "Winapp Cli", + "description": "Windows App Development CLI (winapp) for building, packaging, and deploying Windows applications. Use when asked to initialize Windows app projects, create MSIX packages, generate AppxManifest.xml, manage development certificates, add package identity for debugging, sign packages, or access Windows SDK build tools. Supports .NET, C++, Electron, Rust, Tauri, and cross-platform frameworks targeting Windows.", + "assets": [], + "hasAssets": false, + "assetCount": 0, + "category": "CLI Tools", + "path": "skills/winapp-cli", + "skillFile": "skills/winapp-cli/SKILL.md", + "files": [ + { + "path": "skills/winapp-cli/SKILL.md", + "name": "SKILL.md", + "size": 7654 + } + ] + }, { "id": "workiq-copilot", "name": "workiq-copilot", diff --git a/website/src/pages/samples.astro b/website/src/pages/samples.astro index 722b20d3..3604ac41 100644 --- a/website/src/pages/samples.astro +++ b/website/src/pages/samples.astro @@ -1,95 +1,246 @@ --- import BaseLayout from '../layouts/BaseLayout.astro'; +import Modal from '../components/Modal.astro'; const base = import.meta.env.BASE_URL; --- - +
-
- -

Coming Soon

-

We're migrating code samples from the Copilot SDK Cookbook to this repository.

-

Check back soon for examples including:

-
    -
  • Building custom agents
  • -
  • Integrating with MCP servers
  • -
  • Creating prompt templates
  • -
  • Working with Copilot APIs
  • -
-
- - View Current Cookbook - - - Watch Repository - + + +
+
+ +
+
+ + +
+ +
+ +
+ +
+
Loading samples...
- + +
diff --git a/website/src/scripts/pages/samples.ts b/website/src/scripts/pages/samples.ts new file mode 100644 index 00000000..046895be --- /dev/null +++ b/website/src/scripts/pages/samples.ts @@ -0,0 +1,477 @@ +/** + * Samples/Cookbook page functionality + */ + +import { FuzzySearch, type SearchableItem } from '../search'; +import { fetchData, fetchFileContent, escapeHtml } from '../utils'; + +// Types +interface Language { + id: string; + name: string; + icon: string; + extension: string; +} + +interface RecipeVariant { + doc: string; + example: string | null; +} + +interface Recipe extends SearchableItem { + id: string; + name: string; + description: string; + tags: string[]; + variants: Record; +} + +interface Cookbook { + id: string; + name: string; + description: string; + path: string; + featured: boolean; + languages: Language[]; + recipes: Recipe[]; +} + +interface SamplesData { + cookbooks: Cookbook[]; + totalRecipes: number; + totalCookbooks: number; + filters: { + languages: string[]; + tags: string[]; + }; +} + +// State +let samplesData: SamplesData | null = null; +let search: FuzzySearch | null = null; +let selectedLanguage: string | null = null; +let selectedTags: string[] = []; +let expandedRecipes: Set = new Set(); + +/** + * Initialize the samples page + */ +export async function initSamplesPage(): Promise { + // Load samples data + samplesData = await fetchData('samples.json'); + + if (!samplesData || samplesData.cookbooks.length === 0) { + showEmptyState(); + return; + } + + // Initialize search with all recipes + const allRecipes = samplesData.cookbooks.flatMap(cookbook => + cookbook.recipes.map(recipe => ({ + ...recipe, + title: recipe.name, + cookbookId: cookbook.id + })) + ); + search = new FuzzySearch(allRecipes); + + // Setup UI + setupFilters(); + setupSearch(); + renderCookbooks(); + updateResultsCount(); +} + +/** + * Show empty state when no cookbooks are available + */ +function showEmptyState(): void { + const container = document.getElementById('samples-list'); + if (container) { + container.innerHTML = ` +
+

No Samples Available

+

Check back soon for code samples and recipes.

+
+ `; + } + + // Hide filters + const filtersBar = document.getElementById('filters-bar'); + if (filtersBar) filtersBar.style.display = 'none'; +} + +/** + * Setup language and tag filters + */ +function setupFilters(): void { + if (!samplesData) return; + + // Language filter + const languageSelect = document.getElementById('filter-language') as HTMLSelectElement; + if (languageSelect) { + // Get unique languages across all cookbooks + const languages = new Map(); + samplesData.cookbooks.forEach(cookbook => { + cookbook.languages.forEach(lang => { + if (!languages.has(lang.id)) { + languages.set(lang.id, lang); + } + }); + }); + + languageSelect.innerHTML = ''; + languages.forEach((lang, id) => { + const option = document.createElement('option'); + option.value = id; + option.textContent = `${lang.icon} ${lang.name}`; + languageSelect.appendChild(option); + }); + + languageSelect.addEventListener('change', () => { + selectedLanguage = languageSelect.value || null; + renderCookbooks(); + updateResultsCount(); + }); + } + + // Tag filter (multi-select with Choices.js if available) + const tagSelect = document.getElementById('filter-tag') as HTMLSelectElement; + if (tagSelect && samplesData.filters.tags.length > 0) { + tagSelect.innerHTML = ''; + samplesData.filters.tags.forEach(tag => { + const option = document.createElement('option'); + option.value = tag; + option.textContent = tag; + tagSelect.appendChild(option); + }); + + // Initialize Choices.js if available + if (typeof window !== 'undefined' && (window as any).Choices) { + const choices = new (window as any).Choices(tagSelect, { + removeItemButton: true, + placeholder: true, + placeholderValue: 'Filter by tags...', + searchPlaceholderValue: 'Search tags...', + noResultsText: 'No tags found', + noChoicesText: 'No tags available', + }); + + tagSelect.addEventListener('change', () => { + selectedTags = choices.getValue(true) as string[]; + renderCookbooks(); + updateResultsCount(); + }); + } else { + tagSelect.multiple = true; + tagSelect.addEventListener('change', () => { + selectedTags = Array.from(tagSelect.selectedOptions).map(o => o.value); + renderCookbooks(); + updateResultsCount(); + }); + } + } + + // Clear filters button + const clearBtn = document.getElementById('clear-filters'); + clearBtn?.addEventListener('click', clearFilters); +} + +/** + * Setup search functionality + */ +function setupSearch(): void { + const searchInput = document.getElementById('search-input') as HTMLInputElement; + if (!searchInput) return; + + let debounceTimer: number; + searchInput.addEventListener('input', () => { + clearTimeout(debounceTimer); + debounceTimer = window.setTimeout(() => { + renderCookbooks(); + updateResultsCount(); + }, 200); + }); +} + +/** + * Clear all filters + */ +function clearFilters(): void { + selectedLanguage = null; + selectedTags = []; + + const languageSelect = document.getElementById('filter-language') as HTMLSelectElement; + if (languageSelect) languageSelect.value = ''; + + const tagSelect = document.getElementById('filter-tag') as HTMLSelectElement; + if (tagSelect && (window as any).Choices) { + // Clear Choices.js selection + const choicesInstance = tagSelect.closest('.choices'); + if (choicesInstance) { + const choices = (tagSelect as any).choices; + if (choices) choices.removeActiveItems(); + } + } else if (tagSelect) { + Array.from(tagSelect.options).forEach(o => o.selected = false); + } + + const searchInput = document.getElementById('search-input') as HTMLInputElement; + if (searchInput) searchInput.value = ''; + + renderCookbooks(); + updateResultsCount(); +} + +/** + * Get filtered recipes + */ +function getFilteredRecipes(): { cookbook: Cookbook; recipe: Recipe; highlighted?: string }[] { + if (!samplesData || !search) return []; + + const searchInput = document.getElementById('search-input') as HTMLInputElement; + const query = searchInput?.value.trim() || ''; + + let results: { cookbook: Cookbook; recipe: Recipe; highlighted?: string }[] = []; + + if (query) { + // Use fuzzy search + const searchResults = search.search(query); + results = searchResults.map(result => { + const cookbook = samplesData!.cookbooks.find(c => c.id === result.item.cookbookId)!; + return { + cookbook, + recipe: result.item, + highlighted: search!.highlight(result.item.title, query) + }; + }); + } else { + // No search query - return all recipes + results = samplesData.cookbooks.flatMap(cookbook => + cookbook.recipes.map(recipe => ({ cookbook, recipe })) + ); + } + + // Apply language filter + if (selectedLanguage) { + results = results.filter(({ recipe }) => + recipe.variants[selectedLanguage!] + ); + } + + // Apply tag filter + if (selectedTags.length > 0) { + results = results.filter(({ recipe }) => + selectedTags.some(tag => recipe.tags.includes(tag)) + ); + } + + return results; +} + +/** + * Render cookbooks and recipes + */ +function renderCookbooks(): void { + const container = document.getElementById('samples-list'); + if (!container || !samplesData) return; + + const filteredResults = getFilteredRecipes(); + + if (filteredResults.length === 0) { + container.innerHTML = ` +
+

No Results Found

+

Try adjusting your search or filters.

+
+ `; + return; + } + + // Group by cookbook + const byCookbook = new Map(); + filteredResults.forEach(({ cookbook, recipe, highlighted }) => { + if (!byCookbook.has(cookbook.id)) { + byCookbook.set(cookbook.id, { cookbook, recipes: [] }); + } + byCookbook.get(cookbook.id)!.recipes.push({ recipe, highlighted }); + }); + + let html = ''; + byCookbook.forEach(({ cookbook, recipes }) => { + html += renderCookbookSection(cookbook, recipes); + }); + + container.innerHTML = html; + + // Setup event listeners + setupRecipeListeners(); +} + +/** + * Render a cookbook section + */ +function renderCookbookSection(cookbook: Cookbook, recipes: { recipe: Recipe; highlighted?: string }[]): string { + const languageTabs = cookbook.languages.map(lang => ` + + `).join(''); + + const recipeCards = recipes.map(({ recipe, highlighted }) => + renderRecipeCard(cookbook, recipe, highlighted) + ).join(''); + + return ` +
+
+
+

${escapeHtml(cookbook.name)}

+

${escapeHtml(cookbook.description)}

+
+
+ ${languageTabs} +
+
+
+ ${recipeCards} +
+
+ `; +} + +/** + * Render a recipe card + */ +function renderRecipeCard(cookbook: Cookbook, recipe: Recipe, highlightedName?: string): string { + const recipeKey = `${cookbook.id}-${recipe.id}`; + const isExpanded = expandedRecipes.has(recipeKey); + + // Determine which language to show + const displayLang = selectedLanguage || cookbook.languages[0]?.id || 'nodejs'; + const variant = recipe.variants[displayLang]; + + const tags = recipe.tags.map(tag => + `${escapeHtml(tag)}` + ).join(''); + + const langIndicators = cookbook.languages + .filter(lang => recipe.variants[lang.id]) + .map(lang => `${lang.icon}`) + .join(''); + + return ` +
+
+

${highlightedName || escapeHtml(recipe.name)}

+
${langIndicators}
+
+

${escapeHtml(recipe.description)}

+
${tags}
+
+ ${variant ? ` + + ${variant.example ? ` + + ` : ''} + + + GitHub + + ` : 'Not available for selected language'} +
+
+ `; +} + +/** + * Setup event listeners for recipe interactions + */ +function setupRecipeListeners(): void { + // View recipe buttons + document.querySelectorAll('.view-recipe-btn').forEach(btn => { + btn.addEventListener('click', async (e) => { + e.stopPropagation(); + const docPath = (btn as HTMLElement).dataset.doc; + if (docPath) { + await showRecipeContent(docPath, 'recipe'); + } + }); + }); + + // View example buttons + document.querySelectorAll('.view-example-btn').forEach(btn => { + btn.addEventListener('click', async (e) => { + e.stopPropagation(); + const examplePath = (btn as HTMLElement).dataset.example; + if (examplePath) { + await showRecipeContent(examplePath, 'example'); + } + }); + }); + + // Language tab clicks + document.querySelectorAll('.lang-tab').forEach(tab => { + tab.addEventListener('click', (e) => { + const langId = (tab as HTMLElement).dataset.lang; + if (langId) { + selectedLanguage = langId; + // Update language filter select + const languageSelect = document.getElementById('filter-language') as HTMLSelectElement; + if (languageSelect) languageSelect.value = langId; + renderCookbooks(); + updateResultsCount(); + } + }); + }); +} + +/** + * Show recipe/example content in modal + */ +async function showRecipeContent(filePath: string, type: 'recipe' | 'example'): Promise { + // Use existing modal infrastructure + const { openFileModal } = await import('../modal'); + await openFileModal(filePath, type); +} + +/** + * Update results count display + */ +function updateResultsCount(): void { + const resultsCount = document.getElementById('results-count'); + if (!resultsCount || !samplesData) return; + + const filtered = getFilteredRecipes(); + const total = samplesData.totalRecipes; + + if (filtered.length === total) { + resultsCount.textContent = `${total} recipe${total !== 1 ? 's' : ''}`; + } else { + resultsCount.textContent = `${filtered.length} of ${total} recipe${total !== 1 ? 's' : ''}`; + } +} + +// Auto-initialize when DOM is ready +if (typeof document !== 'undefined') { + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => initSamplesPage()); + } else { + initSamplesPage(); + } +}