refactor(website): convert to ES modules with TypeScript

- Replace all inline scripts with TypeScript modules
- Create page-specific modules for agents, prompts, instructions, skills, collections, index
- Create core modules: utils.ts, search.ts, modal.ts, choices.ts, jszip.ts, theme.ts
- Remove window global exports, use proper ES module imports
- Add type interfaces for all data structures
- Use data-base-path attribute on body for base URL handling
- Bundle Choices.js and JSZip via npm instead of CDN
- Astro pages now just have single script import each
This commit is contained in:
Aaron Powell
2026-01-28 16:38:49 +11:00
parent 875219812e
commit 6bcb6ffc37
69 changed files with 42046 additions and 3 deletions

View File

@@ -16,8 +16,11 @@
"skill:validate": "node ./eng/validate-skills.mjs",
"skill:create": "node ./eng/create-skill.mjs",
"website:build-data": "node ./eng/generate-website-data.mjs",
"website:build": "npm run build && npm run website:build-data",
"website:serve": "npx serve website -l 3000"
"website:build-old": "npm run build && npm run website:build-data",
"website:serve-old": "npx serve website -l 3000",
"website:dev": "npm run website:build-data && cp website/data/*.json website-astro/public/data/ && npm run --prefix website-astro dev",
"website:build": "npm run build && npm run website:build-data && cp website/data/*.json website-astro/public/data/ && npm run --prefix website-astro build",
"website:preview": "npm run --prefix website-astro preview"
},
"repository": {
"type": "git",

View File

@@ -0,0 +1 @@
export default new Map();

View File

@@ -0,0 +1 @@
export default new Map();

199
website-astro/.astro/content.d.ts vendored Normal file
View File

@@ -0,0 +1,199 @@
declare module 'astro:content' {
export interface RenderResult {
Content: import('astro/runtime/server/index.js').AstroComponentFactory;
headings: import('astro').MarkdownHeading[];
remarkPluginFrontmatter: Record<string, any>;
}
interface Render {
'.md': Promise<RenderResult>;
}
export interface RenderedContent {
html: string;
metadata?: {
imagePaths: Array<string>;
[key: string]: unknown;
};
}
}
declare module 'astro:content' {
type Flatten<T> = T extends { [K: string]: infer U } ? U : never;
export type CollectionKey = keyof AnyEntryMap;
export type CollectionEntry<C extends CollectionKey> = Flatten<AnyEntryMap[C]>;
export type ContentCollectionKey = keyof ContentEntryMap;
export type DataCollectionKey = keyof DataEntryMap;
type AllValuesOf<T> = T extends any ? T[keyof T] : never;
type ValidContentEntrySlug<C extends keyof ContentEntryMap> = AllValuesOf<
ContentEntryMap[C]
>['slug'];
export type ReferenceDataEntry<
C extends CollectionKey,
E extends keyof DataEntryMap[C] = string,
> = {
collection: C;
id: E;
};
export type ReferenceContentEntry<
C extends keyof ContentEntryMap,
E extends ValidContentEntrySlug<C> | (string & {}) = string,
> = {
collection: C;
slug: E;
};
export type ReferenceLiveEntry<C extends keyof LiveContentConfig['collections']> = {
collection: C;
id: string;
};
/** @deprecated Use `getEntry` instead. */
export function getEntryBySlug<
C extends keyof ContentEntryMap,
E extends ValidContentEntrySlug<C> | (string & {}),
>(
collection: C,
// Note that this has to accept a regular string too, for SSR
entrySlug: E,
): E extends ValidContentEntrySlug<C>
? Promise<CollectionEntry<C>>
: Promise<CollectionEntry<C> | undefined>;
/** @deprecated Use `getEntry` instead. */
export function getDataEntryById<C extends keyof DataEntryMap, E extends keyof DataEntryMap[C]>(
collection: C,
entryId: E,
): Promise<CollectionEntry<C>>;
export function getCollection<C extends keyof AnyEntryMap, E extends CollectionEntry<C>>(
collection: C,
filter?: (entry: CollectionEntry<C>) => entry is E,
): Promise<E[]>;
export function getCollection<C extends keyof AnyEntryMap>(
collection: C,
filter?: (entry: CollectionEntry<C>) => unknown,
): Promise<CollectionEntry<C>[]>;
export function getLiveCollection<C extends keyof LiveContentConfig['collections']>(
collection: C,
filter?: LiveLoaderCollectionFilterType<C>,
): Promise<
import('astro').LiveDataCollectionResult<LiveLoaderDataType<C>, LiveLoaderErrorType<C>>
>;
export function getEntry<
C extends keyof ContentEntryMap,
E extends ValidContentEntrySlug<C> | (string & {}),
>(
entry: ReferenceContentEntry<C, E>,
): E extends ValidContentEntrySlug<C>
? Promise<CollectionEntry<C>>
: Promise<CollectionEntry<C> | undefined>;
export function getEntry<
C extends keyof DataEntryMap,
E extends keyof DataEntryMap[C] | (string & {}),
>(
entry: ReferenceDataEntry<C, E>,
): E extends keyof DataEntryMap[C]
? Promise<DataEntryMap[C][E]>
: Promise<CollectionEntry<C> | undefined>;
export function getEntry<
C extends keyof ContentEntryMap,
E extends ValidContentEntrySlug<C> | (string & {}),
>(
collection: C,
slug: E,
): E extends ValidContentEntrySlug<C>
? Promise<CollectionEntry<C>>
: Promise<CollectionEntry<C> | undefined>;
export function getEntry<
C extends keyof DataEntryMap,
E extends keyof DataEntryMap[C] | (string & {}),
>(
collection: C,
id: E,
): E extends keyof DataEntryMap[C]
? string extends keyof DataEntryMap[C]
? Promise<DataEntryMap[C][E]> | undefined
: Promise<DataEntryMap[C][E]>
: Promise<CollectionEntry<C> | undefined>;
export function getLiveEntry<C extends keyof LiveContentConfig['collections']>(
collection: C,
filter: string | LiveLoaderEntryFilterType<C>,
): Promise<import('astro').LiveDataEntryResult<LiveLoaderDataType<C>, LiveLoaderErrorType<C>>>;
/** Resolve an array of entry references from the same collection */
export function getEntries<C extends keyof ContentEntryMap>(
entries: ReferenceContentEntry<C, ValidContentEntrySlug<C>>[],
): Promise<CollectionEntry<C>[]>;
export function getEntries<C extends keyof DataEntryMap>(
entries: ReferenceDataEntry<C, keyof DataEntryMap[C]>[],
): Promise<CollectionEntry<C>[]>;
export function render<C extends keyof AnyEntryMap>(
entry: AnyEntryMap[C][string],
): Promise<RenderResult>;
export function reference<C extends keyof AnyEntryMap>(
collection: C,
): import('astro/zod').ZodEffects<
import('astro/zod').ZodString,
C extends keyof ContentEntryMap
? ReferenceContentEntry<C, ValidContentEntrySlug<C>>
: ReferenceDataEntry<C, keyof DataEntryMap[C]>
>;
// Allow generic `string` to avoid excessive type errors in the config
// if `dev` is not running to update as you edit.
// Invalid collection names will be caught at build time.
export function reference<C extends string>(
collection: C,
): import('astro/zod').ZodEffects<import('astro/zod').ZodString, never>;
type ReturnTypeOrOriginal<T> = T extends (...args: any[]) => infer R ? R : T;
type InferEntrySchema<C extends keyof AnyEntryMap> = import('astro/zod').infer<
ReturnTypeOrOriginal<Required<ContentConfig['collections'][C]>['schema']>
>;
type ContentEntryMap = {
};
type DataEntryMap = {
};
type AnyEntryMap = ContentEntryMap & DataEntryMap;
type ExtractLoaderTypes<T> = T extends import('astro/loaders').LiveLoader<
infer TData,
infer TEntryFilter,
infer TCollectionFilter,
infer TError
>
? { data: TData; entryFilter: TEntryFilter; collectionFilter: TCollectionFilter; error: TError }
: { data: never; entryFilter: never; collectionFilter: never; error: never };
type ExtractDataType<T> = ExtractLoaderTypes<T>['data'];
type ExtractEntryFilterType<T> = ExtractLoaderTypes<T>['entryFilter'];
type ExtractCollectionFilterType<T> = ExtractLoaderTypes<T>['collectionFilter'];
type ExtractErrorType<T> = ExtractLoaderTypes<T>['error'];
type LiveLoaderDataType<C extends keyof LiveContentConfig['collections']> =
LiveContentConfig['collections'][C]['schema'] extends undefined
? ExtractDataType<LiveContentConfig['collections'][C]['loader']>
: import('astro/zod').infer<
Exclude<LiveContentConfig['collections'][C]['schema'], undefined>
>;
type LiveLoaderEntryFilterType<C extends keyof LiveContentConfig['collections']> =
ExtractEntryFilterType<LiveContentConfig['collections'][C]['loader']>;
type LiveLoaderCollectionFilterType<C extends keyof LiveContentConfig['collections']> =
ExtractCollectionFilterType<LiveContentConfig['collections'][C]['loader']>;
type LiveLoaderErrorType<C extends keyof LiveContentConfig['collections']> = ExtractErrorType<
LiveContentConfig['collections'][C]['loader']
>;
export type ContentConfig = typeof import("../src/content.config.mjs");
export type LiveContentConfig = never;
}

View File

@@ -0,0 +1 @@
[["Map",1,2],"meta::meta",["Map",3,4,5,6],"astro-version","5.16.15","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"site\":\"https://github.github.io\",\"compressHTML\":true,\"base\":\"/awesome-copilot/\",\"trailingSlash\":\"always\",\"output\":\"static\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"assets\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image/\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true,\"allowedDomains\":[]},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false,\"liveContentCollections\":false,\"csp\":false,\"staticImportMetaEnv\":false,\"chromeDevtoolsWorkspace\":false,\"failOnPrerenderConflict\":false,\"svgo\":false},\"legacy\":{\"collections\":false}}"]

View File

@@ -0,0 +1,5 @@
{
"_variables": {
"lastUpdateCheck": 1769573490320
}
}

1
website-astro/.astro/types.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="astro/client" />

View File

@@ -0,0 +1,14 @@
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
// https://astro.build/config
export default defineConfig({
site: 'https://github.github.io',
base: '/awesome-copilot/',
output: 'static',
integrations: [sitemap()],
build: {
assets: 'assets',
},
trailingSlash: 'always',
});

9
website-astro/dist/agents/index.html vendored Normal file
View File

@@ -0,0 +1,9 @@
<!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Agents - Awesome GitHub Copilot</title><meta name="description" content="Specialized agents that enhance GitHub Copilot for specific technologies, workflows, and domains"><link rel="stylesheet" href="/awesome-copilot/styles/global.css"><link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🤖</text></svg>"><script type="module">const n="theme";function o(e){document.documentElement.setAttribute("data-theme",e)}function c(){const t=document.documentElement.getAttribute("data-theme")==="light"?"dark":"light";o(t),localStorage.setItem(n,t)}function d(){const e=document.getElementById("theme-toggle");e&&e.addEventListener("click",c),window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").addEventListener("change",t=>{localStorage.getItem(n)||o(t.matches?"light":"dark")})}document.addEventListener("DOMContentLoaded",d);</script><link rel="stylesheet" href="/awesome-copilot/assets/choices.Bblnwawv.css"></head> <body data-base-path="/awesome-copilot/"> <header class="site-header"> <div class="container"> <div class="header-content"> <a href="/awesome-copilot/" class="logo"> <span class="logo-icon">🤖</span> <span class="logo-text">Awesome Copilot</span> </a> <nav class="main-nav"> <a href="/awesome-copilot/agents/" class="active">Agents</a> <a href="/awesome-copilot/prompts/">Prompts</a> <a href="/awesome-copilot/instructions/">Instructions</a> <a href="/awesome-copilot/skills/">Skills</a> <a href="/awesome-copilot/collections/">Collections</a> <a href="/awesome-copilot/tools/">Tools</a> <a href="/awesome-copilot/samples/">Samples</a> </nav> <div class="header-actions"> <button id="theme-toggle" class="theme-toggle" title="Toggle theme"> <svg class="icon-sun" viewBox="0 0 16 16" fill="currentColor"> <path d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0V.75A.75.75 0 0 1 8 0zm0 13a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 8 13zM2.343 2.343a.75.75 0 0 1 1.061 0l1.06 1.061a.75.75 0 0 1-1.06 1.06l-1.06-1.06a.75.75 0 0 1 0-1.06zm9.193 9.193a.75.75 0 0 1 1.06 0l1.061 1.06a.75.75 0 0 1-1.06 1.061l-1.061-1.06a.75.75 0 0 1 0-1.061zM0 8a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 0 1.5H.75A.75.75 0 0 1 0 8zm13 0a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 0 1.5h-1.5A.75.75 0 0 1 13 8zM2.343 13.657a.75.75 0 0 1 0-1.061l1.06-1.06a.75.75 0 0 1 1.061 1.06l-1.06 1.06a.75.75 0 0 1-1.061 0zm9.193-9.193a.75.75 0 0 1 0-1.06l1.061-1.061a.75.75 0 0 1 1.06 1.06l-1.06 1.061a.75.75 0 0 1-1.061 0z"></path> </svg> <svg class="icon-moon" viewBox="0 0 16 16" fill="currentColor"> <path d="M9.598 1.591a.75.75 0 0 1 .785-.175 7 7 0 1 1-8.967 8.967.75.75 0 0 1 .961-.96 5.5 5.5 0 0 0 7.046-7.046.75.75 0 0 1 .175-.786zm1.616 1.945a7 7 0 0 1-7.678 7.678 5.5 5.5 0 1 0 7.678-7.678z"></path> </svg> </button> <a href="https://github.com/github/awesome-copilot" class="github-link" target="_blank" rel="noopener"> <svg viewBox="0 0 16 16" width="24" height="24" fill="currentColor"> <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path> </svg> </a> </div> </div> </div> </header> <main> <div class="page-header"> <div class="container"> <h1>🤖 Custom Agents</h1> <p>Specialized agents that enhance GitHub Copilot for specific technologies, workflows, and domains</p> </div> </div> <div class="page-content"> <div class="container"> <div class="search-bar"> <input type="text" id="search-input" placeholder="Search agents..." autocomplete="off"> </div> <!-- Filters --> <div class="filters-bar" id="filters-bar"> <div class="filter-group"> <label for="filter-model">Model:</label> <select id="filter-model" multiple></select> </div> <div class="filter-group"> <label for="filter-tool">Tool:</label> <select id="filter-tool" multiple></select> </div> <div class="filter-group"> <label class="checkbox-label"> <input type="checkbox" id="filter-handoffs">
Has Handoffs
</label> </div> <button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button> </div> <div class="results-count" id="results-count"></div> <div class="resource-list" id="resource-list"> <div class="loading">Loading agents...</div> </div> </div> </div> </main> <div id="file-modal" class="modal hidden"> <div class="modal-content"> <div class="modal-header"> <h3 id="modal-title">File</h3> <div class="modal-actions"> <button id="copy-btn" class="btn btn-secondary" title="Copy to clipboard"> <svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"> <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path> <path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> </svg>
Copy
</button> <a id="install-btn" class="btn btn-primary" target="_blank" rel="noopener" title="Install to VS Code"> <svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"> <path d="M7.25 1a.75.75 0 0 1 .75.75V11h6.25a.75.75 0 0 1 0 1.5H8v6.25a.75.75 0 0 1-1.5 0V12.5H.25a.75.75 0 0 1 0-1.5H6.5V1.75A.75.75 0 0 1 7.25 1Z" transform="scale(0.8) translate(2, 2)"></path> </svg>
Install
</a> <button id="close-modal" class="btn btn-icon" title="Close"> <svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"> <path d="M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z"></path> </svg> </button> </div> </div> <div class="modal-body"> <pre id="modal-content"><code></code></pre> </div> </div> </div> <script type="module" src="/awesome-copilot/assets/agents.astro_astro_type_script_index_0_lang.j8PeQ7-7.js"></script> <footer class="site-footer"> <div class="container"> <p> <a href="https://github.com/github/awesome-copilot" target="_blank" rel="noopener">GitHub</a> ·
<a href="https://github.com/github/awesome-copilot/blob/main/CONTRIBUTING.md" target="_blank" rel="noopener">Contribute</a> ·
<a href="https://github.com/github/awesome-copilot/blob/main/LICENSE" target="_blank" rel="noopener">MIT License</a> </p> </div> </footer> <script type="module">(function(){const e=localStorage.getItem("theme")||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light");document.documentElement.setAttribute("data-theme",e)})();</script> </body> </html>

View File

@@ -0,0 +1,24 @@
import{c as m,g}from"./choices.CFbCQwHQ.js";import{f as v,F as y,d as E,s as I,e as c,g as $,o as H}from"./modal.5jZNQ_ZW.js";const b="agent";let u=[],h=new y,i,f,s={models:[],tools:[],hasHandoffs:!1};function r(){const a=document.getElementById("search-input"),o=document.getElementById("results-count"),l=a?.value||"";let e=l?h.search(l):[...u];s.models.length>0&&(e=e.filter(d=>s.models.includes("(none)")&&!d.model?!0:d.model&&s.models.includes(d.model))),s.tools.length>0&&(e=e.filter(d=>d.tools?.some(p=>s.tools.includes(p)))),s.hasHandoffs&&(e=e.filter(d=>d.hasHandoffs)),L(e,l);const t=[];s.models.length>0&&t.push(`models: ${s.models.length}`),s.tools.length>0&&t.push(`tools: ${s.tools.length}`),s.hasHandoffs&&t.push("has handoffs");let n=`${e.length} of ${u.length} agents`;t.length>0&&(n+=` (filtered by ${t.join(", ")})`),o&&(o.textContent=n)}function L(a,o=""){const l=document.getElementById("resource-list");if(l){if(a.length===0){l.innerHTML=`
<div class="empty-state">
<h3>No agents found</h3>
<p>Try a different search term or adjust filters</p>
</div>
`;return}l.innerHTML=a.map(e=>`
<div class="resource-item" data-path="${c(e.path)}">
<div class="resource-info">
<div class="resource-title">${o?h.highlight(e.title,o):c(e.title)}</div>
<div class="resource-description">${c(e.description||"No description")}</div>
<div class="resource-meta">
${e.model?`<span class="resource-tag tag-model">${c(e.model)}</span>`:""}
${e.tools?.slice(0,3).map(t=>`<span class="resource-tag">${c(t)}</span>`).join("")||""}
${e.tools&&e.tools.length>3?`<span class="resource-tag">+${e.tools.length-3} more</span>`:""}
${e.hasHandoffs?'<span class="resource-tag tag-handoffs">handoffs</span>':""}
</div>
</div>
<div class="resource-actions">
<a href="${$(e.path)}" class="btn btn-secondary" target="_blank" onclick="event.stopPropagation()">
View on GitHub
</a>
</div>
</div>
`).join(""),l.querySelectorAll(".resource-item").forEach(e=>{e.addEventListener("click",()=>{const t=e.dataset.path;t&&H(t,b)})})}}async function B(){const a=document.getElementById("resource-list"),o=document.getElementById("search-input"),l=document.getElementById("filter-handoffs"),e=document.getElementById("clear-filters"),t=await v("agents.json");if(!t||!t.items){a&&(a.innerHTML='<div class="empty-state"><h3>Failed to load data</h3></div>');return}u=t.items,h.setItems(u),i=m("#filter-model",{placeholderValue:"All Models"}),i.setChoices(t.filters.models.map(n=>({value:n,label:n})),"value","label",!0),document.getElementById("filter-model")?.addEventListener("change",()=>{s.models=g(i),r()}),f=m("#filter-tool",{placeholderValue:"All Tools"}),f.setChoices(t.filters.tools.map(n=>({value:n,label:n})),"value","label",!0),document.getElementById("filter-tool")?.addEventListener("change",()=>{s.tools=g(f),r()}),r(),o?.addEventListener("input",E(()=>r(),200)),l?.addEventListener("change",()=>{s.hasHandoffs=l.checked,r()}),e?.addEventListener("click",()=>{s={models:[],tools:[],hasHandoffs:!1},i.removeActiveItems(),f.removeActiveItems(),l&&(l.checked=!1),o&&(o.value=""),r()}),I()}document.addEventListener("DOMContentLoaded",B);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,16 @@
import{c as h,g as p}from"./choices.CFbCQwHQ.js";import{f as m,F as v,d as y,s as $,e as i,g as E,o as I}from"./modal.5jZNQ_ZW.js";const L="collection";let u=[],g=new v,d,n={tags:[],featured:!1};function l(){const r=document.getElementById("search-input"),c=document.getElementById("results-count"),s=r?.value||"";let e=s?g.search(s):[...u];n.tags.length>0&&(e=e.filter(a=>a.tags?.some(f=>n.tags.includes(f)))),n.featured&&(e=e.filter(a=>a.featured)),b(e,s);const t=[];n.tags.length>0&&t.push(`${n.tags.length} tag${n.tags.length>1?"s":""}`),n.featured&&t.push("featured");let o=`${e.length} of ${u.length} collections`;t.length>0&&(o+=` (filtered by ${t.join(", ")})`),c&&(c.textContent=o)}function b(r,c=""){const s=document.getElementById("resource-list");if(s){if(r.length===0){s.innerHTML='<div class="empty-state"><h3>No collections found</h3><p>Try a different search term or adjust filters</p></div>';return}s.innerHTML=r.map(e=>`
<div class="resource-item" data-path="${i(e.path)}">
<div class="resource-info">
<div class="resource-title">${e.featured?"⭐ ":""}${c?g.highlight(e.name,c):i(e.name)}</div>
<div class="resource-description">${i(e.description||"No description")}</div>
<div class="resource-meta">
<span class="resource-tag">${e.itemCount} items</span>
${e.tags?.slice(0,4).map(t=>`<span class="resource-tag">${i(t)}</span>`).join("")||""}
${e.tags&&e.tags.length>4?`<span class="resource-tag">+${e.tags.length-4} more</span>`:""}
</div>
</div>
<div class="resource-actions">
<a href="${E(e.path)}" class="btn btn-secondary" target="_blank" onclick="event.stopPropagation()">View on GitHub</a>
</div>
</div>
`).join(""),s.querySelectorAll(".resource-item").forEach(e=>{e.addEventListener("click",()=>{const t=e.dataset.path;t&&I(t,L)})})}}async function B(){const r=document.getElementById("resource-list"),c=document.getElementById("search-input"),s=document.getElementById("filter-featured"),e=document.getElementById("clear-filters"),t=await m("collections.json");if(!t||!t.items){r&&(r.innerHTML='<div class="empty-state"><h3>Failed to load data</h3></div>');return}u=t.items;const o=u.map(a=>({...a,title:a.name,searchText:`${a.name} ${a.description} ${a.tags?.join(" ")||""}`.toLowerCase()}));g.setItems(o),d=h("#filter-tag",{placeholderValue:"All Tags"}),d.setChoices(t.filters.tags.map(a=>({value:a,label:a})),"value","label",!0),document.getElementById("filter-tag")?.addEventListener("change",()=>{n.tags=p(d),l()}),l(),c?.addEventListener("input",y(()=>l(),200)),s?.addEventListener("change",()=>{n.featured=s.checked,l()}),e?.addEventListener("click",()=>{n={tags:[],featured:!1},d.removeActiveItems(),s&&(s.checked=!1),c&&(c.value=""),l()}),$()}document.addEventListener("DOMContentLoaded",B);

View File

@@ -0,0 +1,24 @@
import{f as o,F as m,d as f,e as l,b as g,t as v,o as h,s as y}from"./modal.5jZNQ_ZW.js";async function $(){const c=await o("manifest.json");if(c&&c.counts){const a=document.getElementById("stats");a&&(a.innerHTML=`
<div class="stat"><span class="stat-value">${c.counts.agents}</span><span class="stat-label">Agents</span></div>
<div class="stat"><span class="stat-value">${c.counts.prompts}</span><span class="stat-label">Prompts</span></div>
<div class="stat"><span class="stat-value">${c.counts.instructions}</span><span class="stat-label">Instructions</span></div>
<div class="stat"><span class="stat-value">${c.counts.skills}</span><span class="stat-label">Skills</span></div>
<div class="stat"><span class="stat-value">${c.counts.collections}</span><span class="stat-label">Collections</span></div>
`)}const d=await o("search-index.json");if(d){const a=new m;a.setItems(d);const e=document.getElementById("global-search"),s=document.getElementById("search-results");e&&s&&(e.addEventListener("input",f(()=>{const t=e.value.trim();if(t.length<2){s.classList.add("hidden");return}const r=a.search(t).slice(0,10);r.length===0?s.innerHTML='<div class="search-result-empty">No results found</div>':(s.innerHTML=r.map(n=>`
<div class="search-result" data-path="${l(n.path)}" data-type="${l(n.type)}">
<span class="search-result-type">${g(n.type)}</span>
<div>
<div class="search-result-title">${a.highlight(n.title,t)}</div>
<div class="search-result-description">${v(n.description,60)}</div>
</div>
</div>
`).join(""),s.querySelectorAll(".search-result").forEach(n=>{n.addEventListener("click",()=>{const p=n.dataset.path,u=n.dataset.type;p&&u&&h(p,u)})})),s.classList.remove("hidden")},200)),document.addEventListener("click",t=>{!e.contains(t.target)&&!s.contains(t.target)&&s.classList.add("hidden")}))}const i=await o("collections.json");if(i&&i.items){const a=i.items.filter(s=>s.featured).slice(0,6),e=document.getElementById("featured-collections");e&&(a.length>0?(e.innerHTML=a.map(s=>`
<div class="card" data-path="${l(s.path)}">
<h3>${l(s.name)}</h3>
<p>${l(v(s.description,80))}</p>
<div class="resource-meta">
<span class="resource-tag">${s.itemCount} items</span>
${s.tags?.slice(0,3).map(t=>`<span class="resource-tag">${l(t)}</span>`).join("")||""}
</div>
</div>
`).join(""),e.querySelectorAll(".card").forEach(s=>{s.addEventListener("click",()=>{const t=s.dataset.path;t&&h(t,"collection")})})):e.innerHTML='<p style="text-align: center; color: var(--color-text-muted);">No featured collections yet</p>')}y()}document.addEventListener("DOMContentLoaded",$);

View File

@@ -0,0 +1,16 @@
import{c as h,g as f}from"./choices.CFbCQwHQ.js";import{f as g,F as v,d as m,s as x,e as a,g as y,o as E}from"./modal.5jZNQ_ZW.js";const I="instruction";let c=[],u=new v,r,i={extensions:[]};function l(){const o=document.getElementById("search-input"),n=document.getElementById("results-count"),t=o?.value||"";let e=t?u.search(t):[...c];i.extensions.length>0&&(e=e.filter(d=>i.extensions.includes("(none)")&&(!d.extensions||d.extensions.length===0)?!0:d.extensions?.some(p=>i.extensions.includes(p)))),$(e,t);let s=`${e.length} of ${c.length} instructions`;i.extensions.length>0&&(s+=` (filtered by ${i.extensions.length} extension${i.extensions.length>1?"s":""})`),n&&(n.textContent=s)}function $(o,n=""){const t=document.getElementById("resource-list");if(t){if(o.length===0){t.innerHTML='<div class="empty-state"><h3>No instructions found</h3><p>Try a different search term or adjust filters</p></div>';return}t.innerHTML=o.map(e=>`
<div class="resource-item" data-path="${a(e.path)}">
<div class="resource-info">
<div class="resource-title">${n?u.highlight(e.title,n):a(e.title)}</div>
<div class="resource-description">${a(e.description||"No description")}</div>
<div class="resource-meta">
${e.applyTo?`<span class="resource-tag">applies to: ${a(e.applyTo)}</span>`:""}
${e.extensions?.slice(0,4).map(s=>`<span class="resource-tag tag-extension">${a(s)}</span>`).join("")||""}
${e.extensions&&e.extensions.length>4?`<span class="resource-tag">+${e.extensions.length-4} more</span>`:""}
</div>
</div>
<div class="resource-actions">
<a href="${y(e.path)}" class="btn btn-secondary" target="_blank" onclick="event.stopPropagation()">View on GitHub</a>
</div>
</div>
`).join(""),t.querySelectorAll(".resource-item").forEach(e=>{e.addEventListener("click",()=>{const s=e.dataset.path;s&&E(s,I)})})}}async function b(){const o=document.getElementById("resource-list"),n=document.getElementById("search-input"),t=document.getElementById("clear-filters"),e=await g("instructions.json");if(!e||!e.items){o&&(o.innerHTML='<div class="empty-state"><h3>Failed to load data</h3></div>');return}c=e.items,u.setItems(c),r=h("#filter-extension",{placeholderValue:"All Extensions"}),r.setChoices(e.filters.extensions.map(s=>({value:s,label:s})),"value","label",!0),document.getElementById("filter-extension")?.addEventListener("change",()=>{i.extensions=f(r),l()}),l(),n?.addEventListener("input",m(()=>l(),200)),t?.addEventListener("click",()=>{i={extensions:[]},r.removeActiveItems(),n&&(n.value=""),l()}),x()}document.addEventListener("DOMContentLoaded",b);

View File

@@ -0,0 +1 @@
const f="https://raw.githubusercontent.com/github/awesome-copilot/main",p="https://github.com/github/awesome-copilot/blob/main",y={instructions:"https://aka.ms/awesome-copilot/install/instructions",prompt:"https://aka.ms/awesome-copilot/install/prompt",agent:"https://aka.ms/awesome-copilot/install/agent"};function g(){return typeof document<"u"&&document.body.dataset.basePath||"/"}async function $(e){try{const t=g(),n=await fetch(`${t}data/${e}`);if(!n.ok)throw new Error(`Failed to fetch ${e}`);return await n.json()}catch(t){return console.error(`Error fetching ${e}:`,t),null}}async function w(e){try{const t=await fetch(`${f}/${e}`);if(!t.ok)throw new Error(`Failed to fetch ${e}`);return await t.text()}catch(t){return console.error("Error fetching file content:",t),null}}async function E(e){try{return await navigator.clipboard.writeText(e),!0}catch{const t=document.createElement("textarea");t.value=e,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t),t.select();const n=document.execCommand("copy");return document.body.removeChild(t),n}}function b(e,t){const n=y[e];return n?`${n}?url=${encodeURIComponent(`${f}/${t}`)}`:null}function v(e){return`${p}/${e}`}function x(e){return`${f}/${e}`}function C(e,t="success"){const n=document.querySelector(".toast");n&&n.remove();const o=document.createElement("div");o.className=`toast ${t}`,o.textContent=e,document.body.appendChild(o),setTimeout(()=>{o.remove()},3e3)}function L(e,t){let n;return function(...c){const i=()=>{clearTimeout(n),e(...c)};clearTimeout(n),n=setTimeout(i,t)}}function h(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function S(e,t){return!e||e.length<=t?e||"":e.slice(0,t).trim()+"..."}function k(e){return{agent:"🤖",prompt:"🎯",instruction:"📋",skill:"⚡",collection:"📦"}[e]||"📄"}class B{constructor(t=[]){this.items=[],this.items=t}setItems(t){this.items=t}search(t,n={}){const{fields:o=["title","description","searchText"],limit:c=50,minScore:i=0}=n;if(!t||t.trim().length===0)return this.items.slice(0,c);const s=t.toLowerCase().trim().split(/\s+/),l=[];for(const u of this.items){const a=this.calculateScore(u,s,o);a>i&&l.push({item:u,score:a})}return l.sort((u,a)=>a.score-u.score),l.slice(0,c).map(u=>u.item)}calculateScore(t,n,o){let c=0;for(const r of n){let s=0;for(const l of o){const u=t[l];if(!u)continue;const a=String(u).toLowerCase();l==="title"&&a===r?s=Math.max(s,100):l==="title"&&a.startsWith(r)?s=Math.max(s,80):l==="title"&&a.includes(r)?s=Math.max(s,60):l==="description"&&a.includes(r)?s=Math.max(s,30):l==="searchText"&&a.includes(r)&&(s=Math.max(s,20))}c+=s}return n.every(r=>o.some(s=>{const l=t[s];return l&&String(l).toLowerCase().includes(r)}))&&n.length>1&&(c*=1.5),c}highlight(t,n){if(!n||!t)return h(t||"");const c=n.toLowerCase().trim().split(/\s+/);let i=h(t);for(const r of c){if(r.length<2)continue;const s=new RegExp(`(${r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")})`,"gi");i=i.replace(s,"<mark>$1</mark>")}return i}}let d=null;function I(){const e=document.getElementById("file-modal"),t=document.getElementById("close-modal"),n=document.getElementById("copy-btn");e&&(t?.addEventListener("click",m),e.addEventListener("click",o=>{o.target===e&&m()}),document.addEventListener("keydown",o=>{o.key==="Escape"&&!e.classList.contains("hidden")&&m()}),n?.addEventListener("click",async()=>{if(d){const o=await E(d);C(o?"Copied to clipboard!":"Failed to copy",o?"success":"error")}}))}async function T(e,t){const n=document.getElementById("file-modal"),o=document.getElementById("modal-title"),c=document.getElementById("modal-content")?.querySelector("code"),i=document.getElementById("install-vscode-btn");if(!n||!o||!c)return;o.textContent=e.split("/").pop()||e,c.textContent="Loading...",n.classList.remove("hidden");const r=b(t,e);r&&i?(i.href=r,i.style.display="inline-flex"):i&&(i.style.display="none");const s=await w(e);d=s,s?c.textContent=s:c.textContent="Failed to load file content. Click the button below to view on GitHub."}function m(){const e=document.getElementById("file-modal");e&&e.classList.add("hidden"),d=null}export{B as F,x as a,k as b,L as d,h as e,$ as f,v as g,T as o,I as s,S as t};

View File

@@ -0,0 +1,15 @@
import{c as h,g as m}from"./choices.CFbCQwHQ.js";import{f,F as g,d as v,s as y,e as a,g as E,o as I}from"./modal.5jZNQ_ZW.js";const $="prompt";let i=[],d=new g,r,n={tools:[]};function c(){const l=document.getElementById("search-input"),o=document.getElementById("results-count"),t=l?.value||"";let e=t?d.search(t):[...i];n.tools.length>0&&(e=e.filter(u=>u.tools?.some(p=>n.tools.includes(p)))),b(e,t);let s=`${e.length} of ${i.length} prompts`;n.tools.length>0&&(s+=` (filtered by ${n.tools.length} tool${n.tools.length>1?"s":""})`),o&&(o.textContent=s)}function b(l,o=""){const t=document.getElementById("resource-list");if(t){if(l.length===0){t.innerHTML='<div class="empty-state"><h3>No prompts found</h3><p>Try a different search term or adjust filters</p></div>';return}t.innerHTML=l.map(e=>`
<div class="resource-item" data-path="${a(e.path)}">
<div class="resource-info">
<div class="resource-title">${o?d.highlight(e.title,o):a(e.title)}</div>
<div class="resource-description">${a(e.description||"No description")}</div>
<div class="resource-meta">
${e.tools?.slice(0,4).map(s=>`<span class="resource-tag">${a(s)}</span>`).join("")||""}
${e.tools&&e.tools.length>4?`<span class="resource-tag">+${e.tools.length-4} more</span>`:""}
</div>
</div>
<div class="resource-actions">
<a href="${E(e.path)}" class="btn btn-secondary" target="_blank" onclick="event.stopPropagation()">View on GitHub</a>
</div>
</div>
`).join(""),t.querySelectorAll(".resource-item").forEach(e=>{e.addEventListener("click",()=>{const s=e.dataset.path;s&&I(s,$)})})}}async function L(){const l=document.getElementById("resource-list"),o=document.getElementById("search-input"),t=document.getElementById("clear-filters"),e=await f("prompts.json");if(!e||!e.items){l&&(l.innerHTML='<div class="empty-state"><h3>Failed to load data</h3></div>');return}i=e.items,d.setItems(i),r=h("#filter-tool",{placeholderValue:"All Tools"}),r.setChoices(e.filters.tools.map(s=>({value:s,label:s})),"value","label",!0),document.getElementById("filter-tool")?.addEventListener("change",()=>{n.tools=m(r),c()}),c(),o?.addEventListener("input",v(()=>c(),200)),t?.addEventListener("click",()=>{n={tools:[]},r.removeActiveItems(),o&&(o.value=""),c()}),y()}document.addEventListener("DOMContentLoaded",L);

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,9 @@
<!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Collections - Awesome GitHub Copilot</title><meta name="description" content="Curated collections of prompts, instructions, and agents for specific workflows"><link rel="stylesheet" href="/awesome-copilot/styles/global.css"><link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🤖</text></svg>"><script type="module">const n="theme";function o(e){document.documentElement.setAttribute("data-theme",e)}function c(){const t=document.documentElement.getAttribute("data-theme")==="light"?"dark":"light";o(t),localStorage.setItem(n,t)}function d(){const e=document.getElementById("theme-toggle");e&&e.addEventListener("click",c),window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").addEventListener("change",t=>{localStorage.getItem(n)||o(t.matches?"light":"dark")})}document.addEventListener("DOMContentLoaded",d);</script><link rel="stylesheet" href="/awesome-copilot/assets/choices.Bblnwawv.css"></head> <body data-base-path="/awesome-copilot/"> <header class="site-header"> <div class="container"> <div class="header-content"> <a href="/awesome-copilot/" class="logo"> <span class="logo-icon">🤖</span> <span class="logo-text">Awesome Copilot</span> </a> <nav class="main-nav"> <a href="/awesome-copilot/agents/">Agents</a> <a href="/awesome-copilot/prompts/">Prompts</a> <a href="/awesome-copilot/instructions/">Instructions</a> <a href="/awesome-copilot/skills/">Skills</a> <a href="/awesome-copilot/collections/" class="active">Collections</a> <a href="/awesome-copilot/tools/">Tools</a> <a href="/awesome-copilot/samples/">Samples</a> </nav> <div class="header-actions"> <button id="theme-toggle" class="theme-toggle" title="Toggle theme"> <svg class="icon-sun" viewBox="0 0 16 16" fill="currentColor"> <path d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0V.75A.75.75 0 0 1 8 0zm0 13a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 8 13zM2.343 2.343a.75.75 0 0 1 1.061 0l1.06 1.061a.75.75 0 0 1-1.06 1.06l-1.06-1.06a.75.75 0 0 1 0-1.06zm9.193 9.193a.75.75 0 0 1 1.06 0l1.061 1.06a.75.75 0 0 1-1.06 1.061l-1.061-1.06a.75.75 0 0 1 0-1.061zM0 8a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 0 1.5H.75A.75.75 0 0 1 0 8zm13 0a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 0 1.5h-1.5A.75.75 0 0 1 13 8zM2.343 13.657a.75.75 0 0 1 0-1.061l1.06-1.06a.75.75 0 0 1 1.061 1.06l-1.06 1.06a.75.75 0 0 1-1.061 0zm9.193-9.193a.75.75 0 0 1 0-1.06l1.061-1.061a.75.75 0 0 1 1.06 1.06l-1.06 1.061a.75.75 0 0 1-1.061 0z"></path> </svg> <svg class="icon-moon" viewBox="0 0 16 16" fill="currentColor"> <path d="M9.598 1.591a.75.75 0 0 1 .785-.175 7 7 0 1 1-8.967 8.967.75.75 0 0 1 .961-.96 5.5 5.5 0 0 0 7.046-7.046.75.75 0 0 1 .175-.786zm1.616 1.945a7 7 0 0 1-7.678 7.678 5.5 5.5 0 1 0 7.678-7.678z"></path> </svg> </button> <a href="https://github.com/github/awesome-copilot" class="github-link" target="_blank" rel="noopener"> <svg viewBox="0 0 16 16" width="24" height="24" fill="currentColor"> <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path> </svg> </a> </div> </div> </div> </header> <main> <div class="page-header"> <div class="container"> <h1>📦 Collections</h1> <p>Curated collections of prompts, instructions, and agents for specific workflows</p> </div> </div> <div class="page-content"> <div class="container"> <div class="search-bar"> <input type="text" id="search-input" placeholder="Search collections..." autocomplete="off"> </div> <div class="filters-bar" id="filters-bar"> <div class="filter-group"> <label for="filter-tag">Tag:</label> <select id="filter-tag" multiple></select> </div> <div class="filter-group"> <label class="checkbox-label"> <input type="checkbox" id="filter-featured">
Featured Only
</label> </div> <button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button> </div> <div class="results-count" id="results-count"></div> <div class="resource-list" id="resource-list"> <div class="loading">Loading collections...</div> </div> </div> </div> </main> <div id="file-modal" class="modal hidden"> <div class="modal-content"> <div class="modal-header"> <h3 id="modal-title">File</h3> <div class="modal-actions"> <button id="copy-btn" class="btn btn-secondary" title="Copy to clipboard"> <svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"> <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path> <path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> </svg>
Copy
</button> <a id="install-btn" class="btn btn-primary" target="_blank" rel="noopener" title="Install to VS Code"> <svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"> <path d="M7.25 1a.75.75 0 0 1 .75.75V11h6.25a.75.75 0 0 1 0 1.5H8v6.25a.75.75 0 0 1-1.5 0V12.5H.25a.75.75 0 0 1 0-1.5H6.5V1.75A.75.75 0 0 1 7.25 1Z" transform="scale(0.8) translate(2, 2)"></path> </svg>
Install
</a> <button id="close-modal" class="btn btn-icon" title="Close"> <svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"> <path d="M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z"></path> </svg> </button> </div> </div> <div class="modal-body"> <pre id="modal-content"><code></code></pre> </div> </div> </div> <script type="module" src="/awesome-copilot/assets/collections.astro_astro_type_script_index_0_lang.RqMV88cF.js"></script> <footer class="site-footer"> <div class="container"> <p> <a href="https://github.com/github/awesome-copilot" target="_blank" rel="noopener">GitHub</a> ·
<a href="https://github.com/github/awesome-copilot/blob/main/CONTRIBUTING.md" target="_blank" rel="noopener">Contribute</a> ·
<a href="https://github.com/github/awesome-copilot/blob/main/LICENSE" target="_blank" rel="noopener">MIT License</a> </p> </div> </footer> <script type="module">(function(){const e=localStorage.getItem("theme")||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light");document.documentElement.setAttribute("data-theme",e)})();</script> </body> </html>

3270
website-astro/dist/data/agents.json vendored Normal file

File diff suppressed because it is too large Load Diff

2129
website-astro/dist/data/collections.json vendored Normal file

File diff suppressed because it is too large Load Diff

2842
website-astro/dist/data/instructions.json vendored Normal file

File diff suppressed because it is too large Load Diff

11
website-astro/dist/data/manifest.json vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"generated": "2026-01-28T04:53:00.935Z",
"counts": {
"agents": 140,
"prompts": 134,
"instructions": 163,
"skills": 28,
"collections": 39,
"total": 504
}
}

2023
website-astro/dist/data/prompts.json vendored Normal file

File diff suppressed because it is too large Load Diff

4361
website-astro/dist/data/search-index.json vendored Normal file

File diff suppressed because it is too large Load Diff

782
website-astro/dist/data/skills.json vendored Normal file
View File

@@ -0,0 +1,782 @@
{
"items": [
{
"id": "agentic-eval",
"name": "agentic-eval",
"title": "Agentic Eval",
"description": "Patterns and techniques for evaluating and improving AI agent outputs. Use this skill when:\n- Implementing self-critique and reflection loops\n- Building evaluator-optimizer pipelines for quality-critical generation\n- Creating test-driven code refinement workflows\n- Designing rubric-based or LLM-as-judge evaluation systems\n- Adding iterative improvement to agent outputs (code, reports, analysis)\n- Measuring and improving agent response quality",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Testing",
"path": "skills/agentic-eval",
"skillFile": "skills/agentic-eval/SKILL.md",
"files": [
{
"path": "skills/agentic-eval/SKILL.md",
"name": "SKILL.md",
"size": 5940
}
]
},
{
"id": "appinsights-instrumentation",
"name": "appinsights-instrumentation",
"title": "Appinsights Instrumentation",
"description": "Instrument a webapp to send useful telemetry data to Azure App Insights",
"assets": [
"LICENSE.txt",
"examples/appinsights.bicep",
"references/ASPNETCORE.md",
"references/AUTO.md",
"references/NODEJS.md",
"references/PYTHON.md",
"scripts/appinsights.ps1"
],
"hasAssets": true,
"assetCount": 7,
"category": "Azure",
"path": "skills/appinsights-instrumentation",
"skillFile": "skills/appinsights-instrumentation/SKILL.md",
"files": [
{
"path": "skills/appinsights-instrumentation/LICENSE.txt",
"name": "LICENSE.txt",
"size": 1078
},
{
"path": "skills/appinsights-instrumentation/SKILL.md",
"name": "SKILL.md",
"size": 2462
},
{
"path": "skills/appinsights-instrumentation/examples/appinsights.bicep",
"name": "examples/appinsights.bicep",
"size": 759
},
{
"path": "skills/appinsights-instrumentation/references/ASPNETCORE.md",
"name": "references/ASPNETCORE.md",
"size": 1711
},
{
"path": "skills/appinsights-instrumentation/references/AUTO.md",
"name": "references/AUTO.md",
"size": 891
},
{
"path": "skills/appinsights-instrumentation/references/NODEJS.md",
"name": "references/NODEJS.md",
"size": 1815
},
{
"path": "skills/appinsights-instrumentation/references/PYTHON.md",
"name": "references/PYTHON.md",
"size": 1812
},
{
"path": "skills/appinsights-instrumentation/scripts/appinsights.ps1",
"name": "scripts/appinsights.ps1",
"size": 1221
}
]
},
{
"id": "azure-deployment-preflight",
"name": "azure-deployment-preflight",
"title": "Azure Deployment Preflight",
"description": "Performs comprehensive preflight validation of Bicep deployments to Azure, including template syntax validation, what-if analysis, and permission checks. Use this skill before any deployment to Azure to preview changes, identify potential issues, and ensure the deployment will succeed. Activate when users mention deploying to Azure, validating Bicep files, checking deployment permissions, previewing infrastructure changes, running what-if, or preparing for azd provision.",
"assets": [
"references/ERROR-HANDLING.md",
"references/REPORT-TEMPLATE.md",
"references/VALIDATION-COMMANDS.md"
],
"hasAssets": true,
"assetCount": 3,
"category": "Azure",
"path": "skills/azure-deployment-preflight",
"skillFile": "skills/azure-deployment-preflight/SKILL.md",
"files": [
{
"path": "skills/azure-deployment-preflight/SKILL.md",
"name": "SKILL.md",
"size": 7490
},
{
"path": "skills/azure-deployment-preflight/references/ERROR-HANDLING.md",
"name": "references/ERROR-HANDLING.md",
"size": 8896
},
{
"path": "skills/azure-deployment-preflight/references/REPORT-TEMPLATE.md",
"name": "references/REPORT-TEMPLATE.md",
"size": 7458
},
{
"path": "skills/azure-deployment-preflight/references/VALIDATION-COMMANDS.md",
"name": "references/VALIDATION-COMMANDS.md",
"size": 8379
}
]
},
{
"id": "azure-devops-cli",
"name": "azure-devops-cli",
"title": "Azure Devops Cli",
"description": "Manage Azure DevOps resources via CLI including projects, repos, pipelines, builds, pull requests, work items, artifacts, and service endpoints. Use when working with Azure DevOps, az commands, devops automation, CI/CD, or when user mentions Azure DevOps CLI.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Azure",
"path": "skills/azure-devops-cli",
"skillFile": "skills/azure-devops-cli/SKILL.md",
"files": [
{
"path": "skills/azure-devops-cli/SKILL.md",
"name": "SKILL.md",
"size": 55003
}
]
},
{
"id": "azure-resource-visualizer",
"name": "azure-resource-visualizer",
"title": "Azure Resource Visualizer",
"description": "Analyze Azure resource groups and generate detailed Mermaid architecture diagrams showing the relationships between individual resources. Use this skill when the user asks for a diagram of their Azure resources or help in understanding how the resources relate to each other.",
"assets": [
"LICENSE.txt",
"assets/template-architecture.md"
],
"hasAssets": true,
"assetCount": 2,
"category": "Azure",
"path": "skills/azure-resource-visualizer",
"skillFile": "skills/azure-resource-visualizer/SKILL.md",
"files": [
{
"path": "skills/azure-resource-visualizer/LICENSE.txt",
"name": "LICENSE.txt",
"size": 1078
},
{
"path": "skills/azure-resource-visualizer/SKILL.md",
"name": "SKILL.md",
"size": 9772
},
{
"path": "skills/azure-resource-visualizer/assets/template-architecture.md",
"name": "assets/template-architecture.md",
"size": 970
}
]
},
{
"id": "azure-role-selector",
"name": "azure-role-selector",
"title": "Azure Role Selector",
"description": "When user is asking for guidance for which role to assign to an identity given desired permissions, this agent helps them understand the role that will meet the requirements with least privilege access and how to apply that role.",
"assets": [
"LICENSE.txt"
],
"hasAssets": true,
"assetCount": 1,
"category": "Azure",
"path": "skills/azure-role-selector",
"skillFile": "skills/azure-role-selector/SKILL.md",
"files": [
{
"path": "skills/azure-role-selector/LICENSE.txt",
"name": "LICENSE.txt",
"size": 1078
},
{
"path": "skills/azure-role-selector/SKILL.md",
"name": "SKILL.md",
"size": 983
}
]
},
{
"id": "azure-static-web-apps",
"name": "azure-static-web-apps",
"title": "Azure Static Web Apps",
"description": "Helps create, configure, and deploy Azure Static Web Apps using the SWA CLI. Use when deploying static sites to Azure, setting up SWA local development, configuring staticwebapp.config.json, adding Azure Functions APIs to SWA, or setting up GitHub Actions CI/CD for Static Web Apps.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Azure",
"path": "skills/azure-static-web-apps",
"skillFile": "skills/azure-static-web-apps/SKILL.md",
"files": [
{
"path": "skills/azure-static-web-apps/SKILL.md",
"name": "SKILL.md",
"size": 9499
}
]
},
{
"id": "chrome-devtools",
"name": "chrome-devtools",
"title": "Chrome Devtools",
"description": "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.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Other",
"path": "skills/chrome-devtools",
"skillFile": "skills/chrome-devtools/SKILL.md",
"files": [
{
"path": "skills/chrome-devtools/SKILL.md",
"name": "SKILL.md",
"size": 4145
}
]
},
{
"id": "gh-cli",
"name": "gh-cli",
"title": "Gh Cli",
"description": "GitHub CLI (gh) comprehensive reference for repositories, issues, pull requests, Actions, projects, releases, gists, codespaces, organizations, extensions, and all GitHub operations from the command line.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Git & GitHub",
"path": "skills/gh-cli",
"skillFile": "skills/gh-cli/SKILL.md",
"files": [
{
"path": "skills/gh-cli/SKILL.md",
"name": "SKILL.md",
"size": 40503
}
]
},
{
"id": "git-commit",
"name": "git-commit",
"title": "Git Commit",
"description": "Execute git commit with conventional commit message analysis, intelligent staging, and message generation. Use when user asks to commit changes, create a git commit, or mentions \"/commit\". Supports: (1) Auto-detecting type and scope from changes, (2) Generating conventional commit messages from diff, (3) Interactive commit with optional type/scope/description overrides, (4) Intelligent file staging for logical grouping",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Git & GitHub",
"path": "skills/git-commit",
"skillFile": "skills/git-commit/SKILL.md",
"files": [
{
"path": "skills/git-commit/SKILL.md",
"name": "SKILL.md",
"size": 3198
}
]
},
{
"id": "github-issues",
"name": "github-issues",
"title": "Github Issues",
"description": "Create, update, and manage GitHub issues using MCP tools. Use this skill when users want to create bug reports, feature requests, or task issues, update existing issues, add labels/assignees/milestones, or manage issue workflows. Triggers on requests like \"create an issue\", \"file a bug\", \"request a feature\", \"update issue X\", or any GitHub issue management task.",
"assets": [
"references/templates.md"
],
"hasAssets": true,
"assetCount": 1,
"category": "Git & GitHub",
"path": "skills/github-issues",
"skillFile": "skills/github-issues/SKILL.md",
"files": [
{
"path": "skills/github-issues/SKILL.md",
"name": "SKILL.md",
"size": 4783
},
{
"path": "skills/github-issues/references/templates.md",
"name": "references/templates.md",
"size": 1384
}
]
},
{
"id": "image-manipulation-image-magick",
"name": "image-manipulation-image-magick",
"title": "Image Manipulation Image Magick",
"description": "Process and manipulate images using ImageMagick. Supports resizing, format conversion, batch processing, and retrieving image metadata. Use when working with images, creating thumbnails, resizing wallpapers, or performing batch image operations.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Other",
"path": "skills/image-manipulation-image-magick",
"skillFile": "skills/image-manipulation-image-magick/SKILL.md",
"files": [
{
"path": "skills/image-manipulation-image-magick/SKILL.md",
"name": "SKILL.md",
"size": 6963
}
]
},
{
"id": "legacy-circuit-mockups",
"name": "legacy-circuit-mockups",
"title": "Legacy Circuit Mockups",
"description": "Generate breadboard circuit mockups and visual diagrams using HTML5 Canvas drawing techniques. Use when asked to create circuit layouts, visualize electronic component placements, draw breadboard diagrams, mockup 6502 builds, generate retro computer schematics, or design vintage electronics projects. Supports 555 timers, W65C02S microprocessors, 28C256 EEPROMs, W65C22 VIA chips, 7400-series logic gates, LEDs, resistors, capacitors, switches, buttons, crystals, and wires.",
"assets": [
"references/28256-eeprom.md",
"references/555.md",
"references/6502.md",
"references/6522.md",
"references/6C62256.md",
"references/7400-series.md",
"references/assembly-compiler.md",
"references/assembly-language.md",
"references/basic-electronic-components.md",
"references/breadboard.md",
"references/common-breadboard-components.md",
"references/connecting-electronic-components.md",
"references/emulator-28256-eeprom.md",
"references/emulator-6502.md",
"references/emulator-6522.md",
"references/emulator-6C62256.md",
"references/emulator-lcd.md",
"references/lcd.md",
"references/minipro.md",
"references/t48eeprom-programmer.md"
],
"hasAssets": true,
"assetCount": 20,
"category": "Diagrams",
"path": "skills/legacy-circuit-mockups",
"skillFile": "skills/legacy-circuit-mockups/SKILL.md",
"files": [
{
"path": "skills/legacy-circuit-mockups/SKILL.md",
"name": "SKILL.md",
"size": 9249
},
{
"path": "skills/legacy-circuit-mockups/references/28256-eeprom.md",
"name": "references/28256-eeprom.md",
"size": 4667
},
{
"path": "skills/legacy-circuit-mockups/references/555.md",
"name": "references/555.md",
"size": 33114
},
{
"path": "skills/legacy-circuit-mockups/references/6502.md",
"name": "references/6502.md",
"size": 5807
},
{
"path": "skills/legacy-circuit-mockups/references/6522.md",
"name": "references/6522.md",
"size": 5881
},
{
"path": "skills/legacy-circuit-mockups/references/6C62256.md",
"name": "references/6C62256.md",
"size": 4214
},
{
"path": "skills/legacy-circuit-mockups/references/7400-series.md",
"name": "references/7400-series.md",
"size": 4759
},
{
"path": "skills/legacy-circuit-mockups/references/assembly-compiler.md",
"name": "references/assembly-compiler.md",
"size": 4860
},
{
"path": "skills/legacy-circuit-mockups/references/assembly-language.md",
"name": "references/assembly-language.md",
"size": 5359
},
{
"path": "skills/legacy-circuit-mockups/references/basic-electronic-components.md",
"name": "references/basic-electronic-components.md",
"size": 2784
},
{
"path": "skills/legacy-circuit-mockups/references/breadboard.md",
"name": "references/breadboard.md",
"size": 5025
},
{
"path": "skills/legacy-circuit-mockups/references/common-breadboard-components.md",
"name": "references/common-breadboard-components.md",
"size": 6565
},
{
"path": "skills/legacy-circuit-mockups/references/connecting-electronic-components.md",
"name": "references/connecting-electronic-components.md",
"size": 15302
},
{
"path": "skills/legacy-circuit-mockups/references/emulator-28256-eeprom.md",
"name": "references/emulator-28256-eeprom.md",
"size": 5198
},
{
"path": "skills/legacy-circuit-mockups/references/emulator-6502.md",
"name": "references/emulator-6502.md",
"size": 5853
},
{
"path": "skills/legacy-circuit-mockups/references/emulator-6522.md",
"name": "references/emulator-6522.md",
"size": 6698
},
{
"path": "skills/legacy-circuit-mockups/references/emulator-6C62256.md",
"name": "references/emulator-6C62256.md",
"size": 4869
},
{
"path": "skills/legacy-circuit-mockups/references/emulator-lcd.md",
"name": "references/emulator-lcd.md",
"size": 5118
},
{
"path": "skills/legacy-circuit-mockups/references/lcd.md",
"name": "references/lcd.md",
"size": 5291
},
{
"path": "skills/legacy-circuit-mockups/references/minipro.md",
"name": "references/minipro.md",
"size": 4130
},
{
"path": "skills/legacy-circuit-mockups/references/t48eeprom-programmer.md",
"name": "references/t48eeprom-programmer.md",
"size": 4398
}
]
},
{
"id": "make-skill-template",
"name": "make-skill-template",
"title": "Make Skill Template",
"description": "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.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Git & GitHub",
"path": "skills/make-skill-template",
"skillFile": "skills/make-skill-template/SKILL.md",
"files": [
{
"path": "skills/make-skill-template/SKILL.md",
"name": "SKILL.md",
"size": 5368
}
]
},
{
"id": "mcp-cli",
"name": "mcp-cli",
"title": "Mcp Cli",
"description": "Interface for MCP (Model Context Protocol) servers via CLI. Use when you need to interact with external tools, APIs, or data sources through MCP servers, list available MCP servers/tools, or call MCP tools from command line.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "CLI Tools",
"path": "skills/mcp-cli",
"skillFile": "skills/mcp-cli/SKILL.md",
"files": [
{
"path": "skills/mcp-cli/SKILL.md",
"name": "SKILL.md",
"size": 2539
}
]
},
{
"id": "microsoft-code-reference",
"name": "microsoft-code-reference",
"title": "Microsoft Code Reference",
"description": "Look up Microsoft API references, find working code samples, and verify SDK code is correct. Use when working with Azure SDKs, .NET libraries, or Microsoft APIs—to find the right method, check parameters, get working examples, or troubleshoot errors. Catches hallucinated methods, wrong signatures, and deprecated patterns by querying official docs.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Azure",
"path": "skills/microsoft-code-reference",
"skillFile": "skills/microsoft-code-reference/SKILL.md",
"files": [
{
"path": "skills/microsoft-code-reference/SKILL.md",
"name": "SKILL.md",
"size": 3353
}
]
},
{
"id": "microsoft-docs",
"name": "microsoft-docs",
"title": "Microsoft Docs",
"description": "Query official Microsoft documentation to understand concepts, find tutorials, and learn how services work. Use for Azure, .NET, Microsoft 365, Windows, Power Platform, and all Microsoft technologies. Get accurate, current information from learn.microsoft.com and other official Microsoft websites—architecture overviews, quickstarts, configuration guides, limits, and best practices.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Azure",
"path": "skills/microsoft-docs",
"skillFile": "skills/microsoft-docs/SKILL.md",
"files": [
{
"path": "skills/microsoft-docs/SKILL.md",
"name": "SKILL.md",
"size": 2142
}
]
},
{
"id": "nuget-manager",
"name": "nuget-manager",
"title": "Nuget Manager",
"description": "Manage NuGet packages in .NET projects/solutions. Use this skill when adding, removing, or updating NuGet package versions. It enforces using `dotnet` CLI for package management and provides strict procedures for direct file edits only when updating versions.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "CLI Tools",
"path": "skills/nuget-manager",
"skillFile": "skills/nuget-manager/SKILL.md",
"files": [
{
"path": "skills/nuget-manager/SKILL.md",
"name": "SKILL.md",
"size": 3418
}
]
},
{
"id": "plantuml-ascii",
"name": "plantuml-ascii",
"title": "Plantuml Ascii",
"description": "Generate ASCII art diagrams using PlantUML text mode. Use when user asks to create ASCII diagrams, text-based diagrams, terminal-friendly diagrams, or mentions plantuml ascii, text diagram, ascii art diagram. Supports: Converting PlantUML diagrams to ASCII art, Creating sequence diagrams, class diagrams, flowcharts in ASCII format, Generating Unicode-enhanced ASCII art with -utxt flag",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Diagrams",
"path": "skills/plantuml-ascii",
"skillFile": "skills/plantuml-ascii/SKILL.md",
"files": [
{
"path": "skills/plantuml-ascii/SKILL.md",
"name": "SKILL.md",
"size": 6096
}
]
},
{
"id": "prd",
"name": "prd",
"title": "Prd",
"description": "Generate high-quality Product Requirements Documents (PRDs) for software systems and AI-powered features. Includes executive summaries, user stories, technical specifications, and risk analysis.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Other",
"path": "skills/prd",
"skillFile": "skills/prd/SKILL.md",
"files": [
{
"path": "skills/prd/SKILL.md",
"name": "SKILL.md",
"size": 4307
}
]
},
{
"id": "refactor",
"name": "refactor",
"title": "Refactor",
"description": "Surgical code refactoring to improve maintainability without changing behavior. Covers extracting functions, renaming variables, breaking down god functions, improving type safety, eliminating code smells, and applying design patterns. Less drastic than repo-rebuilder; use for gradual improvements.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Other",
"path": "skills/refactor",
"skillFile": "skills/refactor/SKILL.md",
"files": [
{
"path": "skills/refactor/SKILL.md",
"name": "SKILL.md",
"size": 16842
}
]
},
{
"id": "scoutqa-test",
"name": "scoutqa-test",
"title": "Scoutqa Test",
"description": "This skill should be used when the user asks to \"test this website\", \"run exploratory testing\", \"check for accessibility issues\", \"verify the login flow works\", \"find bugs on this page\", or requests automated QA testing. Triggers on web application testing scenarios including smoke tests, accessibility audits, e-commerce flows, and user flow validation using ScoutQA CLI. IMPORTANT: Use this skill proactively after implementing web application features to verify they work correctly - don't wait for the user to ask for testing.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Testing",
"path": "skills/scoutqa-test",
"skillFile": "skills/scoutqa-test/SKILL.md",
"files": [
{
"path": "skills/scoutqa-test/SKILL.md",
"name": "SKILL.md",
"size": 12001
}
]
},
{
"id": "snowflake-semanticview",
"name": "snowflake-semanticview",
"title": "Snowflake Semanticview",
"description": "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.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "CLI Tools",
"path": "skills/snowflake-semanticview",
"skillFile": "skills/snowflake-semanticview/SKILL.md",
"files": [
{
"path": "skills/snowflake-semanticview/SKILL.md",
"name": "SKILL.md",
"size": 4411
}
]
},
{
"id": "vscode-ext-commands",
"name": "vscode-ext-commands",
"title": "Vscode Ext Commands",
"description": "Guidelines for contributing commands in VS Code extensions. Indicates naming convention, visibility, localization and other relevant attributes, following VS Code extension development guidelines, libraries and good practices",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "VS Code",
"path": "skills/vscode-ext-commands",
"skillFile": "skills/vscode-ext-commands/SKILL.md",
"files": [
{
"path": "skills/vscode-ext-commands/SKILL.md",
"name": "SKILL.md",
"size": 1545
}
]
},
{
"id": "vscode-ext-localization",
"name": "vscode-ext-localization",
"title": "Vscode Ext Localization",
"description": "Guidelines for proper localization of VS Code extensions, following VS Code extension development guidelines, libraries and good practices",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "VS Code",
"path": "skills/vscode-ext-localization",
"skillFile": "skills/vscode-ext-localization/SKILL.md",
"files": [
{
"path": "skills/vscode-ext-localization/SKILL.md",
"name": "SKILL.md",
"size": 1473
}
]
},
{
"id": "web-design-reviewer",
"name": "web-design-reviewer",
"title": "Web Design Reviewer",
"description": "This skill enables visual inspection of websites running locally or remotely to identify and fix design issues. Triggers on requests like \"review website design\", \"check the UI\", \"fix the layout\", \"find design problems\". Detects issues with responsive design, accessibility, visual consistency, and layout breakage, then performs fixes at the source code level.",
"assets": [
"references/framework-fixes.md",
"references/visual-checklist.md"
],
"hasAssets": true,
"assetCount": 2,
"category": "Diagrams",
"path": "skills/web-design-reviewer",
"skillFile": "skills/web-design-reviewer/SKILL.md",
"files": [
{
"path": "skills/web-design-reviewer/SKILL.md",
"name": "SKILL.md",
"size": 10520
},
{
"path": "skills/web-design-reviewer/references/framework-fixes.md",
"name": "references/framework-fixes.md",
"size": 7437
},
{
"path": "skills/web-design-reviewer/references/visual-checklist.md",
"name": "references/visual-checklist.md",
"size": 5989
}
]
},
{
"id": "webapp-testing",
"name": "webapp-testing",
"title": "Webapp Testing",
"description": "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.",
"assets": [
"test-helper.js"
],
"hasAssets": true,
"assetCount": 1,
"category": "Testing",
"path": "skills/webapp-testing",
"skillFile": "skills/webapp-testing/SKILL.md",
"files": [
{
"path": "skills/webapp-testing/SKILL.md",
"name": "SKILL.md",
"size": 3311
},
{
"path": "skills/webapp-testing/test-helper.js",
"name": "test-helper.js",
"size": 1521
}
]
},
{
"id": "workiq-copilot",
"name": "workiq-copilot",
"title": "Workiq Copilot",
"description": "Guides the Copilot CLI on how to use the WorkIQ CLI/MCP server to query Microsoft 365 Copilot data (emails, meetings, docs, Teams, people) for live context, summaries, and recommendations.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Microsoft",
"path": "skills/workiq-copilot",
"skillFile": "skills/workiq-copilot/SKILL.md",
"files": [
{
"path": "skills/workiq-copilot/SKILL.md",
"name": "SKILL.md",
"size": 5539
}
]
}
],
"filters": {
"categories": [
"Azure",
"CLI Tools",
"Diagrams",
"Git & GitHub",
"Microsoft",
"Other",
"Testing",
"VS Code"
],
"hasAssets": [
"Yes",
"No"
]
}
}

7
website-astro/dist/index.html vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

7
website-astro/dist/prompts/index.html vendored Normal file

File diff suppressed because one or more lines are too long

8
website-astro/dist/samples/index.html vendored Normal file
View File

@@ -0,0 +1,8 @@
<!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Samples - Awesome GitHub Copilot</title><meta name="description" content="Code samples and examples for building with GitHub Copilot"><link rel="stylesheet" href="/awesome-copilot/styles/global.css"><link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🤖</text></svg>"><script type="module">const n="theme";function o(e){document.documentElement.setAttribute("data-theme",e)}function c(){const t=document.documentElement.getAttribute("data-theme")==="light"?"dark":"light";o(t),localStorage.setItem(n,t)}function d(){const e=document.getElementById("theme-toggle");e&&e.addEventListener("click",c),window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").addEventListener("change",t=>{localStorage.getItem(n)||o(t.matches?"light":"dark")})}document.addEventListener("DOMContentLoaded",d);</script><style>.coming-soon[data-astro-cid-plglm3ua]{text-align:center;padding:64px 32px;background-color:var(--color-bg-secondary);border:1px dashed var(--color-border);border-radius:var(--border-radius-lg)}.coming-soon-icon[data-astro-cid-plglm3ua]{font-size:64px;margin-bottom:24px}.coming-soon[data-astro-cid-plglm3ua] h2[data-astro-cid-plglm3ua]{color:var(--color-text-emphasis);margin-bottom:16px;font-size:28px}.coming-soon[data-astro-cid-plglm3ua] p[data-astro-cid-plglm3ua]{color:var(--color-text-muted);max-width:500px;margin:0 auto 16px}.sample-list[data-astro-cid-plglm3ua]{list-style:none;padding:0;margin:24px auto;max-width:300px;text-align:left}.sample-list[data-astro-cid-plglm3ua] li[data-astro-cid-plglm3ua]{padding:8px 0;color:var(--color-text);border-bottom:1px solid var(--color-border)}.sample-list[data-astro-cid-plglm3ua] li[data-astro-cid-plglm3ua]:before{content:"→ ";color:var(--color-link)}.coming-soon-actions[data-astro-cid-plglm3ua]{margin-top:32px;display:flex;gap:12px;justify-content:center;flex-wrap:wrap}
</style></head> <body data-base-path="/awesome-copilot/"> <header class="site-header"> <div class="container"> <div class="header-content"> <a href="/awesome-copilot/" class="logo"> <span class="logo-icon">🤖</span> <span class="logo-text">Awesome Copilot</span> </a> <nav class="main-nav"> <a href="/awesome-copilot/agents/">Agents</a> <a href="/awesome-copilot/prompts/">Prompts</a> <a href="/awesome-copilot/instructions/">Instructions</a> <a href="/awesome-copilot/skills/">Skills</a> <a href="/awesome-copilot/collections/">Collections</a> <a href="/awesome-copilot/tools/">Tools</a> <a href="/awesome-copilot/samples/" class="active">Samples</a> </nav> <div class="header-actions"> <button id="theme-toggle" class="theme-toggle" title="Toggle theme"> <svg class="icon-sun" viewBox="0 0 16 16" fill="currentColor"> <path d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0V.75A.75.75 0 0 1 8 0zm0 13a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 8 13zM2.343 2.343a.75.75 0 0 1 1.061 0l1.06 1.061a.75.75 0 0 1-1.06 1.06l-1.06-1.06a.75.75 0 0 1 0-1.06zm9.193 9.193a.75.75 0 0 1 1.06 0l1.061 1.06a.75.75 0 0 1-1.06 1.061l-1.061-1.06a.75.75 0 0 1 0-1.061zM0 8a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 0 1.5H.75A.75.75 0 0 1 0 8zm13 0a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 0 1.5h-1.5A.75.75 0 0 1 13 8zM2.343 13.657a.75.75 0 0 1 0-1.061l1.06-1.06a.75.75 0 0 1 1.061 1.06l-1.06 1.06a.75.75 0 0 1-1.061 0zm9.193-9.193a.75.75 0 0 1 0-1.06l1.061-1.061a.75.75 0 0 1 1.06 1.06l-1.06 1.061a.75.75 0 0 1-1.061 0z"></path> </svg> <svg class="icon-moon" viewBox="0 0 16 16" fill="currentColor"> <path d="M9.598 1.591a.75.75 0 0 1 .785-.175 7 7 0 1 1-8.967 8.967.75.75 0 0 1 .961-.96 5.5 5.5 0 0 0 7.046-7.046.75.75 0 0 1 .175-.786zm1.616 1.945a7 7 0 0 1-7.678 7.678 5.5 5.5 0 1 0 7.678-7.678z"></path> </svg> </button> <a href="https://github.com/github/awesome-copilot" class="github-link" target="_blank" rel="noopener"> <svg viewBox="0 0 16 16" width="24" height="24" fill="currentColor"> <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path> </svg> </a> </div> </div> </div> </header> <main data-astro-cid-plglm3ua> <div class="page-header" data-astro-cid-plglm3ua> <div class="container" data-astro-cid-plglm3ua> <h1 data-astro-cid-plglm3ua>📚 Samples</h1> <p data-astro-cid-plglm3ua>Code samples and examples for building with GitHub Copilot</p> </div> </div> <div class="page-content" data-astro-cid-plglm3ua> <div class="container" data-astro-cid-plglm3ua> <div class="coming-soon" data-astro-cid-plglm3ua> <div class="coming-soon-icon" data-astro-cid-plglm3ua>🚧</div> <h2 data-astro-cid-plglm3ua>Coming Soon</h2> <p data-astro-cid-plglm3ua>We're migrating code samples from the <a href="https://github.com/github/copilot-sdk/tree/main/cookbook" target="_blank" rel="noopener" data-astro-cid-plglm3ua>Copilot SDK Cookbook</a> to this repository.</p> <p data-astro-cid-plglm3ua>Check back soon for examples including:</p> <ul class="sample-list" data-astro-cid-plglm3ua> <li data-astro-cid-plglm3ua>Building custom agents</li> <li data-astro-cid-plglm3ua>Integrating with MCP servers</li> <li data-astro-cid-plglm3ua>Creating prompt templates</li> <li data-astro-cid-plglm3ua>Working with Copilot APIs</li> </ul> <div class="coming-soon-actions" data-astro-cid-plglm3ua> <a href="https://github.com/github/copilot-sdk/tree/main/cookbook" class="btn btn-primary" target="_blank" rel="noopener" data-astro-cid-plglm3ua>
View Current Cookbook
</a> <a href="https://github.com/github/awesome-copilot" class="btn btn-secondary" target="_blank" rel="noopener" data-astro-cid-plglm3ua>
Watch Repository
</a> </div> </div> </div> </div> </main> <footer class="site-footer"> <div class="container"> <p> <a href="https://github.com/github/awesome-copilot" target="_blank" rel="noopener">GitHub</a> ·
<a href="https://github.com/github/awesome-copilot/blob/main/CONTRIBUTING.md" target="_blank" rel="noopener">Contribute</a> ·
<a href="https://github.com/github/awesome-copilot/blob/main/LICENSE" target="_blank" rel="noopener">MIT License</a> </p> </div> </footer> <script type="module">(function(){const e=localStorage.getItem("theme")||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light");document.documentElement.setAttribute("data-theme",e)})();</script> </body> </html>

1
website-astro/dist/sitemap-0.xml vendored Normal file
View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"><url><loc>https://github.github.io/awesome-copilot/</loc></url><url><loc>https://github.github.io/awesome-copilot/agents/</loc></url><url><loc>https://github.github.io/awesome-copilot/collections/</loc></url><url><loc>https://github.github.io/awesome-copilot/instructions/</loc></url><url><loc>https://github.github.io/awesome-copilot/prompts/</loc></url><url><loc>https://github.github.io/awesome-copilot/samples/</loc></url><url><loc>https://github.github.io/awesome-copilot/skills/</loc></url><url><loc>https://github.github.io/awesome-copilot/tools/</loc></url></urlset>

1
website-astro/dist/sitemap-index.xml vendored Normal file
View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><sitemap><loc>https://github.github.io/awesome-copilot/sitemap-0.xml</loc></sitemap></sitemapindex>

9
website-astro/dist/skills/index.html vendored Normal file
View File

@@ -0,0 +1,9 @@
<!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Skills - Awesome GitHub Copilot</title><meta name="description" content="Self-contained agent skills with instructions and bundled resources"><link rel="stylesheet" href="/awesome-copilot/styles/global.css"><link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🤖</text></svg>"><script type="module">const n="theme";function o(e){document.documentElement.setAttribute("data-theme",e)}function c(){const t=document.documentElement.getAttribute("data-theme")==="light"?"dark":"light";o(t),localStorage.setItem(n,t)}function d(){const e=document.getElementById("theme-toggle");e&&e.addEventListener("click",c),window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").addEventListener("change",t=>{localStorage.getItem(n)||o(t.matches?"light":"dark")})}document.addEventListener("DOMContentLoaded",d);</script><link rel="stylesheet" href="/awesome-copilot/assets/choices.Bblnwawv.css"></head> <body data-base-path="/awesome-copilot/"> <header class="site-header"> <div class="container"> <div class="header-content"> <a href="/awesome-copilot/" class="logo"> <span class="logo-icon">🤖</span> <span class="logo-text">Awesome Copilot</span> </a> <nav class="main-nav"> <a href="/awesome-copilot/agents/">Agents</a> <a href="/awesome-copilot/prompts/">Prompts</a> <a href="/awesome-copilot/instructions/">Instructions</a> <a href="/awesome-copilot/skills/" class="active">Skills</a> <a href="/awesome-copilot/collections/">Collections</a> <a href="/awesome-copilot/tools/">Tools</a> <a href="/awesome-copilot/samples/">Samples</a> </nav> <div class="header-actions"> <button id="theme-toggle" class="theme-toggle" title="Toggle theme"> <svg class="icon-sun" viewBox="0 0 16 16" fill="currentColor"> <path d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0V.75A.75.75 0 0 1 8 0zm0 13a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 8 13zM2.343 2.343a.75.75 0 0 1 1.061 0l1.06 1.061a.75.75 0 0 1-1.06 1.06l-1.06-1.06a.75.75 0 0 1 0-1.06zm9.193 9.193a.75.75 0 0 1 1.06 0l1.061 1.06a.75.75 0 0 1-1.06 1.061l-1.061-1.06a.75.75 0 0 1 0-1.061zM0 8a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 0 1.5H.75A.75.75 0 0 1 0 8zm13 0a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 0 1.5h-1.5A.75.75 0 0 1 13 8zM2.343 13.657a.75.75 0 0 1 0-1.061l1.06-1.06a.75.75 0 0 1 1.061 1.06l-1.06 1.06a.75.75 0 0 1-1.061 0zm9.193-9.193a.75.75 0 0 1 0-1.06l1.061-1.061a.75.75 0 0 1 1.06 1.06l-1.06 1.061a.75.75 0 0 1-1.061 0z"></path> </svg> <svg class="icon-moon" viewBox="0 0 16 16" fill="currentColor"> <path d="M9.598 1.591a.75.75 0 0 1 .785-.175 7 7 0 1 1-8.967 8.967.75.75 0 0 1 .961-.96 5.5 5.5 0 0 0 7.046-7.046.75.75 0 0 1 .175-.786zm1.616 1.945a7 7 0 0 1-7.678 7.678 5.5 5.5 0 1 0 7.678-7.678z"></path> </svg> </button> <a href="https://github.com/github/awesome-copilot" class="github-link" target="_blank" rel="noopener"> <svg viewBox="0 0 16 16" width="24" height="24" fill="currentColor"> <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path> </svg> </a> </div> </div> </div> </header> <main> <div class="page-header"> <div class="container"> <h1>⚡ Skills</h1> <p>Self-contained agent skills with instructions and bundled resources</p> </div> </div> <div class="page-content"> <div class="container"> <div class="search-bar"> <input type="text" id="search-input" placeholder="Search skills..." autocomplete="off"> </div> <div class="filters-bar" id="filters-bar"> <div class="filter-group"> <label for="filter-category">Category:</label> <select id="filter-category" multiple></select> </div> <div class="filter-group"> <label class="checkbox-label"> <input type="checkbox" id="filter-has-assets">
Has Bundled Assets
</label> </div> <button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button> </div> <div class="results-count" id="results-count"></div> <div class="resource-list" id="resource-list"> <div class="loading">Loading skills...</div> </div> </div> </div> </main> <div id="file-modal" class="modal hidden"> <div class="modal-content"> <div class="modal-header"> <h3 id="modal-title">File</h3> <div class="modal-actions"> <button id="copy-btn" class="btn btn-secondary" title="Copy to clipboard"> <svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"> <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path> <path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> </svg>
Copy
</button> <a id="install-btn" class="btn btn-primary" target="_blank" rel="noopener" title="Install to VS Code"> <svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"> <path d="M7.25 1a.75.75 0 0 1 .75.75V11h6.25a.75.75 0 0 1 0 1.5H8v6.25a.75.75 0 0 1-1.5 0V12.5H.25a.75.75 0 0 1 0-1.5H6.5V1.75A.75.75 0 0 1 7.25 1Z" transform="scale(0.8) translate(2, 2)"></path> </svg>
Install
</a> <button id="close-modal" class="btn btn-icon" title="Close"> <svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"> <path d="M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z"></path> </svg> </button> </div> </div> <div class="modal-body"> <pre id="modal-content"><code></code></pre> </div> </div> </div> <script type="module" src="/awesome-copilot/assets/skills.astro_astro_type_script_index_0_lang.CQVGf5fQ.js"></script> <footer class="site-footer"> <div class="container"> <p> <a href="https://github.com/github/awesome-copilot" target="_blank" rel="noopener">GitHub</a> ·
<a href="https://github.com/github/awesome-copilot/blob/main/CONTRIBUTING.md" target="_blank" rel="noopener">Contribute</a> ·
<a href="https://github.com/github/awesome-copilot/blob/main/LICENSE" target="_blank" rel="noopener">MIT License</a> </p> </div> </footer> <script type="module">(function(){const e=localStorage.getItem("theme")||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light");document.documentElement.setAttribute("data-theme",e)})();</script> </body> </html>

1106
website-astro/dist/styles/global.css vendored Normal file

File diff suppressed because it is too large Load Diff

6
website-astro/dist/tools/index.html vendored Normal file
View File

@@ -0,0 +1,6 @@
<!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Tools - Awesome GitHub Copilot</title><meta name="description" content="MCP servers and developer tools for GitHub Copilot"><link rel="stylesheet" href="/awesome-copilot/styles/global.css"><link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🤖</text></svg>"><script type="module">const n="theme";function o(e){document.documentElement.setAttribute("data-theme",e)}function c(){const t=document.documentElement.getAttribute("data-theme")==="light"?"dark":"light";o(t),localStorage.setItem(n,t)}function d(){const e=document.getElementById("theme-toggle");e&&e.addEventListener("click",c),window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").addEventListener("change",t=>{localStorage.getItem(n)||o(t.matches?"light":"dark")})}document.addEventListener("DOMContentLoaded",d);</script><style>.tool-card[data-astro-cid-mlc4vpxg]{background-color:var(--color-card-bg);border:1px solid var(--color-border);border-radius:var(--border-radius-lg);padding:32px;margin-bottom:32px}.tool-header[data-astro-cid-mlc4vpxg]{display:flex;align-items:center;gap:12px;margin-bottom:16px}.tool-header[data-astro-cid-mlc4vpxg] h2[data-astro-cid-mlc4vpxg]{margin:0;font-size:24px;color:var(--color-text-emphasis)}.badge[data-astro-cid-mlc4vpxg]{background-color:var(--color-accent);color:#fff;padding:4px 8px;border-radius:4px;font-size:12px;font-weight:500}.tool-card[data-astro-cid-mlc4vpxg] h3[data-astro-cid-mlc4vpxg]{margin-top:24px;margin-bottom:12px;font-size:16px;color:var(--color-text-emphasis)}.tool-card[data-astro-cid-mlc4vpxg] ul[data-astro-cid-mlc4vpxg]{margin:0;padding-left:24px;color:var(--color-text-muted)}.tool-card[data-astro-cid-mlc4vpxg] li[data-astro-cid-mlc4vpxg]{margin-bottom:8px}.tool-actions[data-astro-cid-mlc4vpxg]{margin-top:24px}.coming-soon[data-astro-cid-mlc4vpxg]{text-align:center;padding:48px;background-color:var(--color-bg-secondary);border:1px dashed var(--color-border);border-radius:var(--border-radius-lg)}.coming-soon[data-astro-cid-mlc4vpxg] h2[data-astro-cid-mlc4vpxg]{color:var(--color-text-muted);margin-bottom:8px}.coming-soon[data-astro-cid-mlc4vpxg] p[data-astro-cid-mlc4vpxg]{color:var(--color-text-muted)}
</style></head> <body data-base-path="/awesome-copilot/"> <header class="site-header"> <div class="container"> <div class="header-content"> <a href="/awesome-copilot/" class="logo"> <span class="logo-icon">🤖</span> <span class="logo-text">Awesome Copilot</span> </a> <nav class="main-nav"> <a href="/awesome-copilot/agents/">Agents</a> <a href="/awesome-copilot/prompts/">Prompts</a> <a href="/awesome-copilot/instructions/">Instructions</a> <a href="/awesome-copilot/skills/">Skills</a> <a href="/awesome-copilot/collections/">Collections</a> <a href="/awesome-copilot/tools/" class="active">Tools</a> <a href="/awesome-copilot/samples/">Samples</a> </nav> <div class="header-actions"> <button id="theme-toggle" class="theme-toggle" title="Toggle theme"> <svg class="icon-sun" viewBox="0 0 16 16" fill="currentColor"> <path d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0V.75A.75.75 0 0 1 8 0zm0 13a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 8 13zM2.343 2.343a.75.75 0 0 1 1.061 0l1.06 1.061a.75.75 0 0 1-1.06 1.06l-1.06-1.06a.75.75 0 0 1 0-1.06zm9.193 9.193a.75.75 0 0 1 1.06 0l1.061 1.06a.75.75 0 0 1-1.06 1.061l-1.061-1.06a.75.75 0 0 1 0-1.061zM0 8a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 0 1.5H.75A.75.75 0 0 1 0 8zm13 0a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 0 1.5h-1.5A.75.75 0 0 1 13 8zM2.343 13.657a.75.75 0 0 1 0-1.061l1.06-1.06a.75.75 0 0 1 1.061 1.06l-1.06 1.06a.75.75 0 0 1-1.061 0zm9.193-9.193a.75.75 0 0 1 0-1.06l1.061-1.061a.75.75 0 0 1 1.06 1.06l-1.06 1.061a.75.75 0 0 1-1.061 0z"></path> </svg> <svg class="icon-moon" viewBox="0 0 16 16" fill="currentColor"> <path d="M9.598 1.591a.75.75 0 0 1 .785-.175 7 7 0 1 1-8.967 8.967.75.75 0 0 1 .961-.96 5.5 5.5 0 0 0 7.046-7.046.75.75 0 0 1 .175-.786zm1.616 1.945a7 7 0 0 1-7.678 7.678 5.5 5.5 0 1 0 7.678-7.678z"></path> </svg> </button> <a href="https://github.com/github/awesome-copilot" class="github-link" target="_blank" rel="noopener"> <svg viewBox="0 0 16 16" width="24" height="24" fill="currentColor"> <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path> </svg> </a> </div> </div> </div> </header> <main data-astro-cid-mlc4vpxg> <div class="page-header" data-astro-cid-mlc4vpxg> <div class="container" data-astro-cid-mlc4vpxg> <h1 data-astro-cid-mlc4vpxg>🔧 Tools</h1> <p data-astro-cid-mlc4vpxg>MCP servers and developer tools for GitHub Copilot</p> </div> </div> <div class="page-content" data-astro-cid-mlc4vpxg> <div class="container" data-astro-cid-mlc4vpxg> <div class="tool-card" data-astro-cid-mlc4vpxg> <div class="tool-header" data-astro-cid-mlc4vpxg> <h2 data-astro-cid-mlc4vpxg>🖥️ Awesome Copilot MCP Server</h2> <span class="badge" data-astro-cid-mlc4vpxg>Official</span> </div> <p data-astro-cid-mlc4vpxg>A Model Context Protocol (MCP) server that provides prompts for searching and installing resources directly from this repository.</p> <h3 data-astro-cid-mlc4vpxg>Features</h3> <ul data-astro-cid-mlc4vpxg> <li data-astro-cid-mlc4vpxg>Search across all agents, prompts, instructions, skills, and collections</li> <li data-astro-cid-mlc4vpxg>Install resources directly to your project</li> <li data-astro-cid-mlc4vpxg>Browse featured and curated collections</li> </ul> <h3 data-astro-cid-mlc4vpxg>Requirements</h3> <ul data-astro-cid-mlc4vpxg> <li data-astro-cid-mlc4vpxg>Docker (required to run the server)</li> </ul> <h3 data-astro-cid-mlc4vpxg>Installation</h3> <p data-astro-cid-mlc4vpxg>See the <a href="https://github.com/github/awesome-copilot#mcp-server" target="_blank" rel="noopener" data-astro-cid-mlc4vpxg>README</a> for installation instructions.</p> <div class="tool-actions" data-astro-cid-mlc4vpxg> <a href="https://github.com/github/awesome-copilot#mcp-server" class="btn btn-primary" target="_blank" rel="noopener" data-astro-cid-mlc4vpxg>
View Documentation
</a> </div> </div> <div class="coming-soon" data-astro-cid-mlc4vpxg> <h2 data-astro-cid-mlc4vpxg>More Tools Coming Soon</h2> <p data-astro-cid-mlc4vpxg>We're working on additional tools to enhance your GitHub Copilot experience. Check back soon!</p> </div> </div> </div> </main> <footer class="site-footer"> <div class="container"> <p> <a href="https://github.com/github/awesome-copilot" target="_blank" rel="noopener">GitHub</a> ·
<a href="https://github.com/github/awesome-copilot/blob/main/CONTRIBUTING.md" target="_blank" rel="noopener">Contribute</a> ·
<a href="https://github.com/github/awesome-copilot/blob/main/LICENSE" target="_blank" rel="noopener">MIT License</a> </p> </div> </footer> <script type="module">(function(){const e=localStorage.getItem("theme")||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light");document.documentElement.setAttribute("data-theme",e)})();</script> </body> </html>

5191
website-astro/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
{
"name": "awesome-copilot-website",
"version": "1.0.0",
"description": "Awesome GitHub Copilot website",
"type": "module",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"keywords": [
"github",
"copilot",
"agents",
"prompts"
],
"author": "GitHub",
"license": "MIT",
"dependencies": {
"@astrojs/sitemap": "^3.7.0",
"astro": "^5.16.15",
"choices.js": "^11.1.0",
"jszip": "^3.10.1"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
{
"generated": "2026-01-28T04:53:00.935Z",
"counts": {
"agents": 140,
"prompts": 134,
"instructions": 163,
"skills": 28,
"collections": 39,
"total": 504
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,782 @@
{
"items": [
{
"id": "agentic-eval",
"name": "agentic-eval",
"title": "Agentic Eval",
"description": "Patterns and techniques for evaluating and improving AI agent outputs. Use this skill when:\n- Implementing self-critique and reflection loops\n- Building evaluator-optimizer pipelines for quality-critical generation\n- Creating test-driven code refinement workflows\n- Designing rubric-based or LLM-as-judge evaluation systems\n- Adding iterative improvement to agent outputs (code, reports, analysis)\n- Measuring and improving agent response quality",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Testing",
"path": "skills/agentic-eval",
"skillFile": "skills/agentic-eval/SKILL.md",
"files": [
{
"path": "skills/agentic-eval/SKILL.md",
"name": "SKILL.md",
"size": 5940
}
]
},
{
"id": "appinsights-instrumentation",
"name": "appinsights-instrumentation",
"title": "Appinsights Instrumentation",
"description": "Instrument a webapp to send useful telemetry data to Azure App Insights",
"assets": [
"LICENSE.txt",
"examples/appinsights.bicep",
"references/ASPNETCORE.md",
"references/AUTO.md",
"references/NODEJS.md",
"references/PYTHON.md",
"scripts/appinsights.ps1"
],
"hasAssets": true,
"assetCount": 7,
"category": "Azure",
"path": "skills/appinsights-instrumentation",
"skillFile": "skills/appinsights-instrumentation/SKILL.md",
"files": [
{
"path": "skills/appinsights-instrumentation/LICENSE.txt",
"name": "LICENSE.txt",
"size": 1078
},
{
"path": "skills/appinsights-instrumentation/SKILL.md",
"name": "SKILL.md",
"size": 2462
},
{
"path": "skills/appinsights-instrumentation/examples/appinsights.bicep",
"name": "examples/appinsights.bicep",
"size": 759
},
{
"path": "skills/appinsights-instrumentation/references/ASPNETCORE.md",
"name": "references/ASPNETCORE.md",
"size": 1711
},
{
"path": "skills/appinsights-instrumentation/references/AUTO.md",
"name": "references/AUTO.md",
"size": 891
},
{
"path": "skills/appinsights-instrumentation/references/NODEJS.md",
"name": "references/NODEJS.md",
"size": 1815
},
{
"path": "skills/appinsights-instrumentation/references/PYTHON.md",
"name": "references/PYTHON.md",
"size": 1812
},
{
"path": "skills/appinsights-instrumentation/scripts/appinsights.ps1",
"name": "scripts/appinsights.ps1",
"size": 1221
}
]
},
{
"id": "azure-deployment-preflight",
"name": "azure-deployment-preflight",
"title": "Azure Deployment Preflight",
"description": "Performs comprehensive preflight validation of Bicep deployments to Azure, including template syntax validation, what-if analysis, and permission checks. Use this skill before any deployment to Azure to preview changes, identify potential issues, and ensure the deployment will succeed. Activate when users mention deploying to Azure, validating Bicep files, checking deployment permissions, previewing infrastructure changes, running what-if, or preparing for azd provision.",
"assets": [
"references/ERROR-HANDLING.md",
"references/REPORT-TEMPLATE.md",
"references/VALIDATION-COMMANDS.md"
],
"hasAssets": true,
"assetCount": 3,
"category": "Azure",
"path": "skills/azure-deployment-preflight",
"skillFile": "skills/azure-deployment-preflight/SKILL.md",
"files": [
{
"path": "skills/azure-deployment-preflight/SKILL.md",
"name": "SKILL.md",
"size": 7490
},
{
"path": "skills/azure-deployment-preflight/references/ERROR-HANDLING.md",
"name": "references/ERROR-HANDLING.md",
"size": 8896
},
{
"path": "skills/azure-deployment-preflight/references/REPORT-TEMPLATE.md",
"name": "references/REPORT-TEMPLATE.md",
"size": 7458
},
{
"path": "skills/azure-deployment-preflight/references/VALIDATION-COMMANDS.md",
"name": "references/VALIDATION-COMMANDS.md",
"size": 8379
}
]
},
{
"id": "azure-devops-cli",
"name": "azure-devops-cli",
"title": "Azure Devops Cli",
"description": "Manage Azure DevOps resources via CLI including projects, repos, pipelines, builds, pull requests, work items, artifacts, and service endpoints. Use when working with Azure DevOps, az commands, devops automation, CI/CD, or when user mentions Azure DevOps CLI.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Azure",
"path": "skills/azure-devops-cli",
"skillFile": "skills/azure-devops-cli/SKILL.md",
"files": [
{
"path": "skills/azure-devops-cli/SKILL.md",
"name": "SKILL.md",
"size": 55003
}
]
},
{
"id": "azure-resource-visualizer",
"name": "azure-resource-visualizer",
"title": "Azure Resource Visualizer",
"description": "Analyze Azure resource groups and generate detailed Mermaid architecture diagrams showing the relationships between individual resources. Use this skill when the user asks for a diagram of their Azure resources or help in understanding how the resources relate to each other.",
"assets": [
"LICENSE.txt",
"assets/template-architecture.md"
],
"hasAssets": true,
"assetCount": 2,
"category": "Azure",
"path": "skills/azure-resource-visualizer",
"skillFile": "skills/azure-resource-visualizer/SKILL.md",
"files": [
{
"path": "skills/azure-resource-visualizer/LICENSE.txt",
"name": "LICENSE.txt",
"size": 1078
},
{
"path": "skills/azure-resource-visualizer/SKILL.md",
"name": "SKILL.md",
"size": 9772
},
{
"path": "skills/azure-resource-visualizer/assets/template-architecture.md",
"name": "assets/template-architecture.md",
"size": 970
}
]
},
{
"id": "azure-role-selector",
"name": "azure-role-selector",
"title": "Azure Role Selector",
"description": "When user is asking for guidance for which role to assign to an identity given desired permissions, this agent helps them understand the role that will meet the requirements with least privilege access and how to apply that role.",
"assets": [
"LICENSE.txt"
],
"hasAssets": true,
"assetCount": 1,
"category": "Azure",
"path": "skills/azure-role-selector",
"skillFile": "skills/azure-role-selector/SKILL.md",
"files": [
{
"path": "skills/azure-role-selector/LICENSE.txt",
"name": "LICENSE.txt",
"size": 1078
},
{
"path": "skills/azure-role-selector/SKILL.md",
"name": "SKILL.md",
"size": 983
}
]
},
{
"id": "azure-static-web-apps",
"name": "azure-static-web-apps",
"title": "Azure Static Web Apps",
"description": "Helps create, configure, and deploy Azure Static Web Apps using the SWA CLI. Use when deploying static sites to Azure, setting up SWA local development, configuring staticwebapp.config.json, adding Azure Functions APIs to SWA, or setting up GitHub Actions CI/CD for Static Web Apps.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Azure",
"path": "skills/azure-static-web-apps",
"skillFile": "skills/azure-static-web-apps/SKILL.md",
"files": [
{
"path": "skills/azure-static-web-apps/SKILL.md",
"name": "SKILL.md",
"size": 9499
}
]
},
{
"id": "chrome-devtools",
"name": "chrome-devtools",
"title": "Chrome Devtools",
"description": "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.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Other",
"path": "skills/chrome-devtools",
"skillFile": "skills/chrome-devtools/SKILL.md",
"files": [
{
"path": "skills/chrome-devtools/SKILL.md",
"name": "SKILL.md",
"size": 4145
}
]
},
{
"id": "gh-cli",
"name": "gh-cli",
"title": "Gh Cli",
"description": "GitHub CLI (gh) comprehensive reference for repositories, issues, pull requests, Actions, projects, releases, gists, codespaces, organizations, extensions, and all GitHub operations from the command line.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Git & GitHub",
"path": "skills/gh-cli",
"skillFile": "skills/gh-cli/SKILL.md",
"files": [
{
"path": "skills/gh-cli/SKILL.md",
"name": "SKILL.md",
"size": 40503
}
]
},
{
"id": "git-commit",
"name": "git-commit",
"title": "Git Commit",
"description": "Execute git commit with conventional commit message analysis, intelligent staging, and message generation. Use when user asks to commit changes, create a git commit, or mentions \"/commit\". Supports: (1) Auto-detecting type and scope from changes, (2) Generating conventional commit messages from diff, (3) Interactive commit with optional type/scope/description overrides, (4) Intelligent file staging for logical grouping",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Git & GitHub",
"path": "skills/git-commit",
"skillFile": "skills/git-commit/SKILL.md",
"files": [
{
"path": "skills/git-commit/SKILL.md",
"name": "SKILL.md",
"size": 3198
}
]
},
{
"id": "github-issues",
"name": "github-issues",
"title": "Github Issues",
"description": "Create, update, and manage GitHub issues using MCP tools. Use this skill when users want to create bug reports, feature requests, or task issues, update existing issues, add labels/assignees/milestones, or manage issue workflows. Triggers on requests like \"create an issue\", \"file a bug\", \"request a feature\", \"update issue X\", or any GitHub issue management task.",
"assets": [
"references/templates.md"
],
"hasAssets": true,
"assetCount": 1,
"category": "Git & GitHub",
"path": "skills/github-issues",
"skillFile": "skills/github-issues/SKILL.md",
"files": [
{
"path": "skills/github-issues/SKILL.md",
"name": "SKILL.md",
"size": 4783
},
{
"path": "skills/github-issues/references/templates.md",
"name": "references/templates.md",
"size": 1384
}
]
},
{
"id": "image-manipulation-image-magick",
"name": "image-manipulation-image-magick",
"title": "Image Manipulation Image Magick",
"description": "Process and manipulate images using ImageMagick. Supports resizing, format conversion, batch processing, and retrieving image metadata. Use when working with images, creating thumbnails, resizing wallpapers, or performing batch image operations.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Other",
"path": "skills/image-manipulation-image-magick",
"skillFile": "skills/image-manipulation-image-magick/SKILL.md",
"files": [
{
"path": "skills/image-manipulation-image-magick/SKILL.md",
"name": "SKILL.md",
"size": 6963
}
]
},
{
"id": "legacy-circuit-mockups",
"name": "legacy-circuit-mockups",
"title": "Legacy Circuit Mockups",
"description": "Generate breadboard circuit mockups and visual diagrams using HTML5 Canvas drawing techniques. Use when asked to create circuit layouts, visualize electronic component placements, draw breadboard diagrams, mockup 6502 builds, generate retro computer schematics, or design vintage electronics projects. Supports 555 timers, W65C02S microprocessors, 28C256 EEPROMs, W65C22 VIA chips, 7400-series logic gates, LEDs, resistors, capacitors, switches, buttons, crystals, and wires.",
"assets": [
"references/28256-eeprom.md",
"references/555.md",
"references/6502.md",
"references/6522.md",
"references/6C62256.md",
"references/7400-series.md",
"references/assembly-compiler.md",
"references/assembly-language.md",
"references/basic-electronic-components.md",
"references/breadboard.md",
"references/common-breadboard-components.md",
"references/connecting-electronic-components.md",
"references/emulator-28256-eeprom.md",
"references/emulator-6502.md",
"references/emulator-6522.md",
"references/emulator-6C62256.md",
"references/emulator-lcd.md",
"references/lcd.md",
"references/minipro.md",
"references/t48eeprom-programmer.md"
],
"hasAssets": true,
"assetCount": 20,
"category": "Diagrams",
"path": "skills/legacy-circuit-mockups",
"skillFile": "skills/legacy-circuit-mockups/SKILL.md",
"files": [
{
"path": "skills/legacy-circuit-mockups/SKILL.md",
"name": "SKILL.md",
"size": 9249
},
{
"path": "skills/legacy-circuit-mockups/references/28256-eeprom.md",
"name": "references/28256-eeprom.md",
"size": 4667
},
{
"path": "skills/legacy-circuit-mockups/references/555.md",
"name": "references/555.md",
"size": 33114
},
{
"path": "skills/legacy-circuit-mockups/references/6502.md",
"name": "references/6502.md",
"size": 5807
},
{
"path": "skills/legacy-circuit-mockups/references/6522.md",
"name": "references/6522.md",
"size": 5881
},
{
"path": "skills/legacy-circuit-mockups/references/6C62256.md",
"name": "references/6C62256.md",
"size": 4214
},
{
"path": "skills/legacy-circuit-mockups/references/7400-series.md",
"name": "references/7400-series.md",
"size": 4759
},
{
"path": "skills/legacy-circuit-mockups/references/assembly-compiler.md",
"name": "references/assembly-compiler.md",
"size": 4860
},
{
"path": "skills/legacy-circuit-mockups/references/assembly-language.md",
"name": "references/assembly-language.md",
"size": 5359
},
{
"path": "skills/legacy-circuit-mockups/references/basic-electronic-components.md",
"name": "references/basic-electronic-components.md",
"size": 2784
},
{
"path": "skills/legacy-circuit-mockups/references/breadboard.md",
"name": "references/breadboard.md",
"size": 5025
},
{
"path": "skills/legacy-circuit-mockups/references/common-breadboard-components.md",
"name": "references/common-breadboard-components.md",
"size": 6565
},
{
"path": "skills/legacy-circuit-mockups/references/connecting-electronic-components.md",
"name": "references/connecting-electronic-components.md",
"size": 15302
},
{
"path": "skills/legacy-circuit-mockups/references/emulator-28256-eeprom.md",
"name": "references/emulator-28256-eeprom.md",
"size": 5198
},
{
"path": "skills/legacy-circuit-mockups/references/emulator-6502.md",
"name": "references/emulator-6502.md",
"size": 5853
},
{
"path": "skills/legacy-circuit-mockups/references/emulator-6522.md",
"name": "references/emulator-6522.md",
"size": 6698
},
{
"path": "skills/legacy-circuit-mockups/references/emulator-6C62256.md",
"name": "references/emulator-6C62256.md",
"size": 4869
},
{
"path": "skills/legacy-circuit-mockups/references/emulator-lcd.md",
"name": "references/emulator-lcd.md",
"size": 5118
},
{
"path": "skills/legacy-circuit-mockups/references/lcd.md",
"name": "references/lcd.md",
"size": 5291
},
{
"path": "skills/legacy-circuit-mockups/references/minipro.md",
"name": "references/minipro.md",
"size": 4130
},
{
"path": "skills/legacy-circuit-mockups/references/t48eeprom-programmer.md",
"name": "references/t48eeprom-programmer.md",
"size": 4398
}
]
},
{
"id": "make-skill-template",
"name": "make-skill-template",
"title": "Make Skill Template",
"description": "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.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Git & GitHub",
"path": "skills/make-skill-template",
"skillFile": "skills/make-skill-template/SKILL.md",
"files": [
{
"path": "skills/make-skill-template/SKILL.md",
"name": "SKILL.md",
"size": 5368
}
]
},
{
"id": "mcp-cli",
"name": "mcp-cli",
"title": "Mcp Cli",
"description": "Interface for MCP (Model Context Protocol) servers via CLI. Use when you need to interact with external tools, APIs, or data sources through MCP servers, list available MCP servers/tools, or call MCP tools from command line.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "CLI Tools",
"path": "skills/mcp-cli",
"skillFile": "skills/mcp-cli/SKILL.md",
"files": [
{
"path": "skills/mcp-cli/SKILL.md",
"name": "SKILL.md",
"size": 2539
}
]
},
{
"id": "microsoft-code-reference",
"name": "microsoft-code-reference",
"title": "Microsoft Code Reference",
"description": "Look up Microsoft API references, find working code samples, and verify SDK code is correct. Use when working with Azure SDKs, .NET libraries, or Microsoft APIs—to find the right method, check parameters, get working examples, or troubleshoot errors. Catches hallucinated methods, wrong signatures, and deprecated patterns by querying official docs.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Azure",
"path": "skills/microsoft-code-reference",
"skillFile": "skills/microsoft-code-reference/SKILL.md",
"files": [
{
"path": "skills/microsoft-code-reference/SKILL.md",
"name": "SKILL.md",
"size": 3353
}
]
},
{
"id": "microsoft-docs",
"name": "microsoft-docs",
"title": "Microsoft Docs",
"description": "Query official Microsoft documentation to understand concepts, find tutorials, and learn how services work. Use for Azure, .NET, Microsoft 365, Windows, Power Platform, and all Microsoft technologies. Get accurate, current information from learn.microsoft.com and other official Microsoft websites—architecture overviews, quickstarts, configuration guides, limits, and best practices.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Azure",
"path": "skills/microsoft-docs",
"skillFile": "skills/microsoft-docs/SKILL.md",
"files": [
{
"path": "skills/microsoft-docs/SKILL.md",
"name": "SKILL.md",
"size": 2142
}
]
},
{
"id": "nuget-manager",
"name": "nuget-manager",
"title": "Nuget Manager",
"description": "Manage NuGet packages in .NET projects/solutions. Use this skill when adding, removing, or updating NuGet package versions. It enforces using `dotnet` CLI for package management and provides strict procedures for direct file edits only when updating versions.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "CLI Tools",
"path": "skills/nuget-manager",
"skillFile": "skills/nuget-manager/SKILL.md",
"files": [
{
"path": "skills/nuget-manager/SKILL.md",
"name": "SKILL.md",
"size": 3418
}
]
},
{
"id": "plantuml-ascii",
"name": "plantuml-ascii",
"title": "Plantuml Ascii",
"description": "Generate ASCII art diagrams using PlantUML text mode. Use when user asks to create ASCII diagrams, text-based diagrams, terminal-friendly diagrams, or mentions plantuml ascii, text diagram, ascii art diagram. Supports: Converting PlantUML diagrams to ASCII art, Creating sequence diagrams, class diagrams, flowcharts in ASCII format, Generating Unicode-enhanced ASCII art with -utxt flag",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Diagrams",
"path": "skills/plantuml-ascii",
"skillFile": "skills/plantuml-ascii/SKILL.md",
"files": [
{
"path": "skills/plantuml-ascii/SKILL.md",
"name": "SKILL.md",
"size": 6096
}
]
},
{
"id": "prd",
"name": "prd",
"title": "Prd",
"description": "Generate high-quality Product Requirements Documents (PRDs) for software systems and AI-powered features. Includes executive summaries, user stories, technical specifications, and risk analysis.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Other",
"path": "skills/prd",
"skillFile": "skills/prd/SKILL.md",
"files": [
{
"path": "skills/prd/SKILL.md",
"name": "SKILL.md",
"size": 4307
}
]
},
{
"id": "refactor",
"name": "refactor",
"title": "Refactor",
"description": "Surgical code refactoring to improve maintainability without changing behavior. Covers extracting functions, renaming variables, breaking down god functions, improving type safety, eliminating code smells, and applying design patterns. Less drastic than repo-rebuilder; use for gradual improvements.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Other",
"path": "skills/refactor",
"skillFile": "skills/refactor/SKILL.md",
"files": [
{
"path": "skills/refactor/SKILL.md",
"name": "SKILL.md",
"size": 16842
}
]
},
{
"id": "scoutqa-test",
"name": "scoutqa-test",
"title": "Scoutqa Test",
"description": "This skill should be used when the user asks to \"test this website\", \"run exploratory testing\", \"check for accessibility issues\", \"verify the login flow works\", \"find bugs on this page\", or requests automated QA testing. Triggers on web application testing scenarios including smoke tests, accessibility audits, e-commerce flows, and user flow validation using ScoutQA CLI. IMPORTANT: Use this skill proactively after implementing web application features to verify they work correctly - don't wait for the user to ask for testing.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Testing",
"path": "skills/scoutqa-test",
"skillFile": "skills/scoutqa-test/SKILL.md",
"files": [
{
"path": "skills/scoutqa-test/SKILL.md",
"name": "SKILL.md",
"size": 12001
}
]
},
{
"id": "snowflake-semanticview",
"name": "snowflake-semanticview",
"title": "Snowflake Semanticview",
"description": "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.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "CLI Tools",
"path": "skills/snowflake-semanticview",
"skillFile": "skills/snowflake-semanticview/SKILL.md",
"files": [
{
"path": "skills/snowflake-semanticview/SKILL.md",
"name": "SKILL.md",
"size": 4411
}
]
},
{
"id": "vscode-ext-commands",
"name": "vscode-ext-commands",
"title": "Vscode Ext Commands",
"description": "Guidelines for contributing commands in VS Code extensions. Indicates naming convention, visibility, localization and other relevant attributes, following VS Code extension development guidelines, libraries and good practices",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "VS Code",
"path": "skills/vscode-ext-commands",
"skillFile": "skills/vscode-ext-commands/SKILL.md",
"files": [
{
"path": "skills/vscode-ext-commands/SKILL.md",
"name": "SKILL.md",
"size": 1545
}
]
},
{
"id": "vscode-ext-localization",
"name": "vscode-ext-localization",
"title": "Vscode Ext Localization",
"description": "Guidelines for proper localization of VS Code extensions, following VS Code extension development guidelines, libraries and good practices",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "VS Code",
"path": "skills/vscode-ext-localization",
"skillFile": "skills/vscode-ext-localization/SKILL.md",
"files": [
{
"path": "skills/vscode-ext-localization/SKILL.md",
"name": "SKILL.md",
"size": 1473
}
]
},
{
"id": "web-design-reviewer",
"name": "web-design-reviewer",
"title": "Web Design Reviewer",
"description": "This skill enables visual inspection of websites running locally or remotely to identify and fix design issues. Triggers on requests like \"review website design\", \"check the UI\", \"fix the layout\", \"find design problems\". Detects issues with responsive design, accessibility, visual consistency, and layout breakage, then performs fixes at the source code level.",
"assets": [
"references/framework-fixes.md",
"references/visual-checklist.md"
],
"hasAssets": true,
"assetCount": 2,
"category": "Diagrams",
"path": "skills/web-design-reviewer",
"skillFile": "skills/web-design-reviewer/SKILL.md",
"files": [
{
"path": "skills/web-design-reviewer/SKILL.md",
"name": "SKILL.md",
"size": 10520
},
{
"path": "skills/web-design-reviewer/references/framework-fixes.md",
"name": "references/framework-fixes.md",
"size": 7437
},
{
"path": "skills/web-design-reviewer/references/visual-checklist.md",
"name": "references/visual-checklist.md",
"size": 5989
}
]
},
{
"id": "webapp-testing",
"name": "webapp-testing",
"title": "Webapp Testing",
"description": "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.",
"assets": [
"test-helper.js"
],
"hasAssets": true,
"assetCount": 1,
"category": "Testing",
"path": "skills/webapp-testing",
"skillFile": "skills/webapp-testing/SKILL.md",
"files": [
{
"path": "skills/webapp-testing/SKILL.md",
"name": "SKILL.md",
"size": 3311
},
{
"path": "skills/webapp-testing/test-helper.js",
"name": "test-helper.js",
"size": 1521
}
]
},
{
"id": "workiq-copilot",
"name": "workiq-copilot",
"title": "Workiq Copilot",
"description": "Guides the Copilot CLI on how to use the WorkIQ CLI/MCP server to query Microsoft 365 Copilot data (emails, meetings, docs, Teams, people) for live context, summaries, and recommendations.",
"assets": [],
"hasAssets": false,
"assetCount": 0,
"category": "Microsoft",
"path": "skills/workiq-copilot",
"skillFile": "skills/workiq-copilot/SKILL.md",
"files": [
{
"path": "skills/workiq-copilot/SKILL.md",
"name": "SKILL.md",
"size": 5539
}
]
}
],
"filters": {
"categories": [
"Azure",
"CLI Tools",
"Diagrams",
"Git & GitHub",
"Microsoft",
"Other",
"Testing",
"VS Code"
],
"hasAssets": [
"Yes",
"No"
]
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
---
// Modal component for viewing file contents
---
<div id="file-modal" class="modal hidden">
<div class="modal-content">
<div class="modal-header">
<h3 id="modal-title">File</h3>
<div class="modal-actions">
<button id="copy-btn" class="btn btn-secondary" title="Copy to clipboard">
<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor">
<path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"/>
<path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"/>
</svg>
Copy
</button>
<a id="install-btn" class="btn btn-primary" target="_blank" rel="noopener" title="Install to VS Code">
<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor">
<path d="M7.25 1a.75.75 0 0 1 .75.75V11h6.25a.75.75 0 0 1 0 1.5H8v6.25a.75.75 0 0 1-1.5 0V12.5H.25a.75.75 0 0 1 0-1.5H6.5V1.75A.75.75 0 0 1 7.25 1Z" transform="scale(0.8) translate(2, 2)"/>
</svg>
Install
</a>
<button id="close-modal" class="btn btn-icon" title="Close">
<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor">
<path d="M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z"></path>
</svg>
</button>
</div>
</div>
<div class="modal-body">
<pre id="modal-content"><code></code></pre>
</div>
</div>
</div>

View File

@@ -0,0 +1,82 @@
---
interface Props {
title: string;
description?: string;
activeNav?: string;
}
const { title, description = 'Community-driven collection of custom agents, prompts, and instructions for GitHub Copilot', activeNav = '' } = Astro.props;
const base = import.meta.env.BASE_URL;
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{title} - Awesome GitHub Copilot</title>
<meta name="description" content={description}>
<link rel="stylesheet" href={`${base}styles/global.css`}>
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🤖</text></svg>">
<script>
// Theme toggle - inline for immediate effect (prevent flash)
(function() {
const theme = localStorage.getItem('theme') ||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
})();
</script>
</head>
<body data-base-path={base}>
<header class="site-header">
<div class="container">
<div class="header-content">
<a href={base} class="logo">
<span class="logo-icon">🤖</span>
<span class="logo-text">Awesome Copilot</span>
</a>
<nav class="main-nav">
<a href={`${base}agents/`} class:list={[{ active: activeNav === 'agents' }]}>Agents</a>
<a href={`${base}prompts/`} class:list={[{ active: activeNav === 'prompts' }]}>Prompts</a>
<a href={`${base}instructions/`} class:list={[{ active: activeNav === 'instructions' }]}>Instructions</a>
<a href={`${base}skills/`} class:list={[{ active: activeNav === 'skills' }]}>Skills</a>
<a href={`${base}collections/`} class:list={[{ active: activeNav === 'collections' }]}>Collections</a>
<a href={`${base}tools/`} class:list={[{ active: activeNav === 'tools' }]}>Tools</a>
<a href={`${base}samples/`} class:list={[{ active: activeNav === 'samples' }]}>Samples</a>
</nav>
<div class="header-actions">
<button id="theme-toggle" class="theme-toggle" title="Toggle theme">
<svg class="icon-sun" viewBox="0 0 16 16" fill="currentColor">
<path d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0V.75A.75.75 0 0 1 8 0zm0 13a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 8 13zM2.343 2.343a.75.75 0 0 1 1.061 0l1.06 1.061a.75.75 0 0 1-1.06 1.06l-1.06-1.06a.75.75 0 0 1 0-1.06zm9.193 9.193a.75.75 0 0 1 1.06 0l1.061 1.06a.75.75 0 0 1-1.06 1.061l-1.061-1.06a.75.75 0 0 1 0-1.061zM0 8a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 0 1.5H.75A.75.75 0 0 1 0 8zm13 0a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 0 1.5h-1.5A.75.75 0 0 1 13 8zM2.343 13.657a.75.75 0 0 1 0-1.061l1.06-1.06a.75.75 0 0 1 1.061 1.06l-1.06 1.06a.75.75 0 0 1-1.061 0zm9.193-9.193a.75.75 0 0 1 0-1.06l1.061-1.061a.75.75 0 0 1 1.06 1.06l-1.06 1.061a.75.75 0 0 1-1.061 0z"/>
</svg>
<svg class="icon-moon" viewBox="0 0 16 16" fill="currentColor">
<path d="M9.598 1.591a.75.75 0 0 1 .785-.175 7 7 0 1 1-8.967 8.967.75.75 0 0 1 .961-.96 5.5 5.5 0 0 0 7.046-7.046.75.75 0 0 1 .175-.786zm1.616 1.945a7 7 0 0 1-7.678 7.678 5.5 5.5 0 1 0 7.678-7.678z"/>
</svg>
</button>
<a href="https://github.com/github/awesome-copilot" class="github-link" target="_blank" rel="noopener">
<svg viewBox="0 0 16 16" width="24" height="24" fill="currentColor">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path>
</svg>
</a>
</div>
</div>
</div>
</header>
<slot />
<footer class="site-footer">
<div class="container">
<p>
<a href="https://github.com/github/awesome-copilot" target="_blank" rel="noopener">GitHub</a> ·
<a href="https://github.com/github/awesome-copilot/blob/main/CONTRIBUTING.md" target="_blank" rel="noopener">Contribute</a> ·
<a href="https://github.com/github/awesome-copilot/blob/main/LICENSE" target="_blank" rel="noopener">MIT License</a>
</p>
</div>
</footer>
<script>
import '../scripts/theme';
</script>
</body>
</html>

View File

@@ -0,0 +1,53 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import Modal from '../components/Modal.astro';
---
<BaseLayout title="Agents" description="Specialized agents that enhance GitHub Copilot for specific technologies, workflows, and domains" activeNav="agents">
<main>
<div class="page-header">
<div class="container">
<h1>🤖 Custom Agents</h1>
<p>Specialized agents that enhance GitHub Copilot for specific technologies, workflows, and domains</p>
</div>
</div>
<div class="page-content">
<div class="container">
<div class="search-bar">
<input type="text" id="search-input" placeholder="Search agents..." autocomplete="off">
</div>
<!-- Filters -->
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-model">Model:</label>
<select id="filter-model" multiple></select>
</div>
<div class="filter-group">
<label for="filter-tool">Tool:</label>
<select id="filter-tool" multiple></select>
</div>
<div class="filter-group">
<label class="checkbox-label">
<input type="checkbox" id="filter-handoffs">
Has Handoffs
</label>
</div>
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
<div class="results-count" id="results-count"></div>
<div class="resource-list" id="resource-list">
<div class="loading">Loading agents...</div>
</div>
</div>
</div>
</main>
<Modal />
<script>
import '../scripts/pages/agents';
</script>
</BaseLayout>

View File

@@ -0,0 +1,48 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import Modal from '../components/Modal.astro';
---
<BaseLayout title="Collections" description="Curated collections of prompts, instructions, and agents for specific workflows" activeNav="collections">
<main>
<div class="page-header">
<div class="container">
<h1>📦 Collections</h1>
<p>Curated collections of prompts, instructions, and agents for specific workflows</p>
</div>
</div>
<div class="page-content">
<div class="container">
<div class="search-bar">
<input type="text" id="search-input" placeholder="Search collections..." autocomplete="off">
</div>
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-tag">Tag:</label>
<select id="filter-tag" multiple></select>
</div>
<div class="filter-group">
<label class="checkbox-label">
<input type="checkbox" id="filter-featured">
Featured Only
</label>
</div>
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
<div class="results-count" id="results-count"></div>
<div class="resource-list" id="resource-list">
<div class="loading">Loading collections...</div>
</div>
</div>
</div>
</main>
<Modal />
<script>
import '../scripts/pages/collections';
</script>
</BaseLayout>

View File

@@ -0,0 +1,103 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import Modal from '../components/Modal.astro';
const base = import.meta.env.BASE_URL;
---
<BaseLayout title="Home" activeNav="">
<main>
<!-- Hero Section -->
<section class="hero">
<div class="container">
<h1>Awesome GitHub Copilot</h1>
<p class="hero-subtitle">Community-contributed instructions, prompts, agents, and skills to enhance your GitHub Copilot experience</p>
<div class="hero-search">
<input type="text" id="global-search" placeholder="Search all resources..." autocomplete="off">
<div id="search-results" class="search-results hidden"></div>
</div>
<div class="hero-stats" id="stats">
<!-- Populated by JS -->
</div>
</div>
</section>
<!-- Quick Links -->
<section class="quick-links">
<div class="container">
<div class="cards-grid">
<a href={`${base}agents/`} class="card">
<div class="card-icon">🤖</div>
<h3>Agents</h3>
<p>Custom agents for specialized Copilot experiences</p>
</a>
<a href={`${base}prompts/`} class="card">
<div class="card-icon">🎯</div>
<h3>Prompts</h3>
<p>Ready-to-use prompt templates for development tasks</p>
</a>
<a href={`${base}instructions/`} class="card">
<div class="card-icon">📋</div>
<h3>Instructions</h3>
<p>Coding standards and best practices for Copilot</p>
</a>
<a href={`${base}skills/`} class="card">
<div class="card-icon">⚡</div>
<h3>Skills</h3>
<p>Self-contained folders with instructions and resources</p>
</a>
<a href={`${base}collections/`} class="card">
<div class="card-icon">📦</div>
<h3>Collections</h3>
<p>Curated collections organized by themes</p>
</a>
<a href={`${base}tools/`} class="card">
<div class="card-icon">🔧</div>
<h3>Tools</h3>
<p>MCP servers and developer tools</p>
</a>
</div>
</div>
</section>
<!-- Featured Collections -->
<section class="featured">
<div class="container">
<h2>Featured Collections</h2>
<div id="featured-collections" class="cards-grid">
<!-- Populated by JS -->
</div>
</div>
</section>
<!-- Getting Started -->
<section class="getting-started">
<div class="container">
<h2>Getting Started</h2>
<div class="steps">
<div class="step">
<div class="step-number">1</div>
<h3>Browse</h3>
<p>Explore agents, prompts, instructions, and skills</p>
</div>
<div class="step">
<div class="step-number">2</div>
<h3>Preview</h3>
<p>Click any item to view its full content</p>
</div>
<div class="step">
<div class="step-number">3</div>
<h3>Install</h3>
<p>One-click install to VS Code or copy to clipboard</p>
</div>
</div>
</div>
</section>
</main>
<Modal />
<script>
import '../scripts/pages/index';
</script>
</BaseLayout>

View File

@@ -0,0 +1,42 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import Modal from '../components/Modal.astro';
---
<BaseLayout title="Instructions" description="Coding standards and best practices for GitHub Copilot" activeNav="instructions">
<main>
<div class="page-header">
<div class="container">
<h1>📋 Instructions</h1>
<p>Coding standards and best practices for GitHub Copilot</p>
</div>
</div>
<div class="page-content">
<div class="container">
<div class="search-bar">
<input type="text" id="search-input" placeholder="Search instructions..." autocomplete="off">
</div>
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-extension">File Extension:</label>
<select id="filter-extension" multiple></select>
</div>
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
<div class="results-count" id="results-count"></div>
<div class="resource-list" id="resource-list">
<div class="loading">Loading instructions...</div>
</div>
</div>
</div>
</main>
<Modal />
<script>
import '../scripts/pages/instructions';
</script>
</BaseLayout>

View File

@@ -0,0 +1,42 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import Modal from '../components/Modal.astro';
---
<BaseLayout title="Prompts" description="Ready-to-use prompt templates for development tasks with GitHub Copilot" activeNav="prompts">
<main>
<div class="page-header">
<div class="container">
<h1>🎯 Prompts</h1>
<p>Ready-to-use prompt templates for development tasks with GitHub Copilot</p>
</div>
</div>
<div class="page-content">
<div class="container">
<div class="search-bar">
<input type="text" id="search-input" placeholder="Search prompts..." autocomplete="off">
</div>
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-tool">Tool:</label>
<select id="filter-tool" multiple></select>
</div>
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
<div class="results-count" id="results-count"></div>
<div class="resource-list" id="resource-list">
<div class="loading">Loading prompts...</div>
</div>
</div>
</div>
</main>
<Modal />
<script>
import '../scripts/pages/prompts';
</script>
</BaseLayout>

View File

@@ -0,0 +1,95 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
const base = import.meta.env.BASE_URL;
---
<BaseLayout title="Samples" description="Code samples and examples for building with GitHub Copilot" activeNav="samples">
<main>
<div class="page-header">
<div class="container">
<h1>📚 Samples</h1>
<p>Code samples and examples for building with GitHub Copilot</p>
</div>
</div>
<div class="page-content">
<div class="container">
<div class="coming-soon">
<div class="coming-soon-icon">🚧</div>
<h2>Coming Soon</h2>
<p>We're migrating code samples from the <a href="https://github.com/github/copilot-sdk/tree/main/cookbook" target="_blank" rel="noopener">Copilot SDK Cookbook</a> to this repository.</p>
<p>Check back soon for examples including:</p>
<ul class="sample-list">
<li>Building custom agents</li>
<li>Integrating with MCP servers</li>
<li>Creating prompt templates</li>
<li>Working with Copilot APIs</li>
</ul>
<div class="coming-soon-actions">
<a href="https://github.com/github/copilot-sdk/tree/main/cookbook" class="btn btn-primary" target="_blank" rel="noopener">
View Current Cookbook
</a>
<a href="https://github.com/github/awesome-copilot" class="btn btn-secondary" target="_blank" rel="noopener">
Watch Repository
</a>
</div>
</div>
</div>
</div>
</main>
<style>
.coming-soon {
text-align: center;
padding: 64px 32px;
background-color: var(--color-bg-secondary);
border: 1px dashed var(--color-border);
border-radius: var(--border-radius-lg);
}
.coming-soon-icon {
font-size: 64px;
margin-bottom: 24px;
}
.coming-soon h2 {
color: var(--color-text-emphasis);
margin-bottom: 16px;
font-size: 28px;
}
.coming-soon p {
color: var(--color-text-muted);
max-width: 500px;
margin: 0 auto 16px;
}
.sample-list {
list-style: none;
padding: 0;
margin: 24px auto;
max-width: 300px;
text-align: left;
}
.sample-list li {
padding: 8px 0;
color: var(--color-text);
border-bottom: 1px solid var(--color-border);
}
.sample-list li::before {
content: '→ ';
color: var(--color-link);
}
.coming-soon-actions {
margin-top: 32px;
display: flex;
gap: 12px;
justify-content: center;
flex-wrap: wrap;
}
</style>
</BaseLayout>

View File

@@ -0,0 +1,48 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import Modal from '../components/Modal.astro';
---
<BaseLayout title="Skills" description="Self-contained agent skills with instructions and bundled resources" activeNav="skills">
<main>
<div class="page-header">
<div class="container">
<h1>⚡ Skills</h1>
<p>Self-contained agent skills with instructions and bundled resources</p>
</div>
</div>
<div class="page-content">
<div class="container">
<div class="search-bar">
<input type="text" id="search-input" placeholder="Search skills..." autocomplete="off">
</div>
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-category">Category:</label>
<select id="filter-category" multiple></select>
</div>
<div class="filter-group">
<label class="checkbox-label">
<input type="checkbox" id="filter-has-assets">
Has Bundled Assets
</label>
</div>
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
<div class="results-count" id="results-count"></div>
<div class="resource-list" id="resource-list">
<div class="loading">Loading skills...</div>
</div>
</div>
</div>
</main>
<Modal />
<script>
import '../scripts/pages/skills';
</script>
</BaseLayout>

View File

@@ -0,0 +1,124 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
const base = import.meta.env.BASE_URL;
---
<BaseLayout title="Tools" description="MCP servers and developer tools for GitHub Copilot" activeNav="tools">
<main>
<div class="page-header">
<div class="container">
<h1>🔧 Tools</h1>
<p>MCP servers and developer tools for GitHub Copilot</p>
</div>
</div>
<div class="page-content">
<div class="container">
<div class="tool-card">
<div class="tool-header">
<h2>🖥️ Awesome Copilot MCP Server</h2>
<span class="badge">Official</span>
</div>
<p>A Model Context Protocol (MCP) server that provides prompts for searching and installing resources directly from this repository.</p>
<h3>Features</h3>
<ul>
<li>Search across all agents, prompts, instructions, skills, and collections</li>
<li>Install resources directly to your project</li>
<li>Browse featured and curated collections</li>
</ul>
<h3>Requirements</h3>
<ul>
<li>Docker (required to run the server)</li>
</ul>
<h3>Installation</h3>
<p>See the <a href="https://github.com/github/awesome-copilot#mcp-server" target="_blank" rel="noopener">README</a> for installation instructions.</p>
<div class="tool-actions">
<a href="https://github.com/github/awesome-copilot#mcp-server" class="btn btn-primary" target="_blank" rel="noopener">
View Documentation
</a>
</div>
</div>
<div class="coming-soon">
<h2>More Tools Coming Soon</h2>
<p>We're working on additional tools to enhance your GitHub Copilot experience. Check back soon!</p>
</div>
</div>
</div>
</main>
<style>
.tool-card {
background-color: var(--color-card-bg);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-lg);
padding: 32px;
margin-bottom: 32px;
}
.tool-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 16px;
}
.tool-header h2 {
margin: 0;
font-size: 24px;
color: var(--color-text-emphasis);
}
.badge {
background-color: var(--color-accent);
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
}
.tool-card h3 {
margin-top: 24px;
margin-bottom: 12px;
font-size: 16px;
color: var(--color-text-emphasis);
}
.tool-card ul {
margin: 0;
padding-left: 24px;
color: var(--color-text-muted);
}
.tool-card li {
margin-bottom: 8px;
}
.tool-actions {
margin-top: 24px;
}
.coming-soon {
text-align: center;
padding: 48px;
background-color: var(--color-bg-secondary);
border: 1px dashed var(--color-border);
border-radius: var(--border-radius-lg);
}
.coming-soon h2 {
color: var(--color-text-muted);
margin-bottom: 8px;
}
.coming-soon p {
color: var(--color-text-muted);
}
</style>
</BaseLayout>

View File

@@ -0,0 +1,34 @@
/**
* Choices.js wrapper with sensible defaults
*/
import Choices from 'choices.js';
import 'choices.js/public/assets/styles/choices.min.css';
export type { Choices };
/**
* Get selected values from a Choices instance
*/
export function getChoicesValues(choices: Choices): string[] {
const val = choices.getValue(true);
return Array.isArray(val) ? val : (val ? [val] : []);
}
/**
* Create a new Choices instance with sensible defaults
*/
export function createChoices(selector: string | HTMLSelectElement, options: Partial<Choices['config']> = {}): Choices {
return new Choices(selector, {
removeItemButton: true,
searchPlaceholderValue: 'Search...',
noResultsText: 'No results found',
noChoicesText: 'No options available',
itemSelectText: '',
shouldSort: false,
searchResultLimit: 100,
resetScrollPosition: false,
...options,
});
}
export { Choices };

View File

@@ -0,0 +1,7 @@
/**
* JSZip entry point for bundling
*/
import JSZip from 'jszip';
export { JSZip };
export default JSZip;

View File

@@ -0,0 +1,106 @@
/**
* Modal functionality for file viewing
*/
import { fetchFileContent, getVSCodeInstallUrl, copyToClipboard, showToast } from './utils';
// Modal state
let currentFilePath: string | null = null;
let currentFileContent: string | null = null;
let currentFileType: string | null = null;
/**
* Setup modal functionality
*/
export function setupModal(): void {
const modal = document.getElementById('file-modal');
const closeBtn = document.getElementById('close-modal');
const copyBtn = document.getElementById('copy-btn');
if (!modal) return;
closeBtn?.addEventListener('click', closeModal);
modal.addEventListener('click', (e) => {
if (e.target === modal) closeModal();
});
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && !modal.classList.contains('hidden')) {
closeModal();
}
});
copyBtn?.addEventListener('click', async () => {
if (currentFileContent) {
const success = await copyToClipboard(currentFileContent);
showToast(success ? 'Copied to clipboard!' : 'Failed to copy', success ? 'success' : 'error');
}
});
}
/**
* Open file viewer modal
*/
export async function openFileModal(filePath: string, type: string): Promise<void> {
const modal = document.getElementById('file-modal');
const title = document.getElementById('modal-title');
const contentEl = document.getElementById('modal-content')?.querySelector('code');
const installBtn = document.getElementById('install-vscode-btn') as HTMLAnchorElement | null;
if (!modal || !title || !contentEl) return;
currentFilePath = filePath;
currentFileType = type;
// Show modal with loading state
title.textContent = filePath.split('/').pop() || filePath;
contentEl.textContent = 'Loading...';
modal.classList.remove('hidden');
// Setup install button
const installUrl = getVSCodeInstallUrl(type, filePath);
if (installUrl && installBtn) {
installBtn.href = installUrl;
installBtn.style.display = 'inline-flex';
} else if (installBtn) {
installBtn.style.display = 'none';
}
// Fetch and display content
const fileContent = await fetchFileContent(filePath);
currentFileContent = fileContent;
if (fileContent) {
contentEl.textContent = fileContent;
} else {
contentEl.textContent = 'Failed to load file content. Click the button below to view on GitHub.';
}
}
/**
* Close modal
*/
export function closeModal(): void {
const modal = document.getElementById('file-modal');
if (modal) {
modal.classList.add('hidden');
}
currentFilePath = null;
currentFileContent = null;
currentFileType = null;
}
/**
* Get current file path (for external use)
*/
export function getCurrentFilePath(): string | null {
return currentFilePath;
}
/**
* Get current file content (for external use)
*/
export function getCurrentFileContent(): string | null {
return currentFileContent;
}

View File

@@ -0,0 +1,174 @@
/**
* Agents page functionality
*/
import { createChoices, getChoicesValues, type Choices } from '../choices';
import { FuzzySearch } from '../search';
import { fetchData, debounce, escapeHtml, getGitHubUrl } from '../utils';
import { setupModal, openFileModal } from '../modal';
interface Agent {
title: string;
description?: string;
path: string;
model?: string;
tools?: string[];
hasHandoffs?: boolean;
}
interface AgentsData {
items: Agent[];
filters: {
models: string[];
tools: string[];
};
}
const resourceType = 'agent';
let allItems: Agent[] = [];
let search = new FuzzySearch();
let modelSelect: Choices;
let toolSelect: Choices;
let currentFilters = {
models: [] as string[],
tools: [] as string[],
hasHandoffs: false,
};
function applyFiltersAndRender(): void {
const searchInput = document.getElementById('search-input') as HTMLInputElement;
const countEl = document.getElementById('results-count');
const query = searchInput?.value || '';
let results = query ? search.search(query) : [...allItems];
if (currentFilters.models.length > 0) {
results = results.filter(item => {
if (currentFilters.models.includes('(none)') && !item.model) {
return true;
}
return item.model && currentFilters.models.includes(item.model);
});
}
if (currentFilters.tools.length > 0) {
results = results.filter(item =>
item.tools?.some(tool => currentFilters.tools.includes(tool))
);
}
if (currentFilters.hasHandoffs) {
results = results.filter(item => item.hasHandoffs);
}
renderItems(results, query);
const activeFilters: string[] = [];
if (currentFilters.models.length > 0) activeFilters.push(`models: ${currentFilters.models.length}`);
if (currentFilters.tools.length > 0) activeFilters.push(`tools: ${currentFilters.tools.length}`);
if (currentFilters.hasHandoffs) activeFilters.push('has handoffs');
let countText = `${results.length} of ${allItems.length} agents`;
if (activeFilters.length > 0) {
countText += ` (filtered by ${activeFilters.join(', ')})`;
}
if (countEl) countEl.textContent = countText;
}
function renderItems(items: Agent[], query = ''): void {
const list = document.getElementById('resource-list');
if (!list) return;
if (items.length === 0) {
list.innerHTML = `
<div class="empty-state">
<h3>No agents found</h3>
<p>Try a different search term or adjust filters</p>
</div>
`;
return;
}
list.innerHTML = items.map(item => `
<div class="resource-item" data-path="${escapeHtml(item.path)}">
<div class="resource-info">
<div class="resource-title">${query ? search.highlight(item.title, query) : escapeHtml(item.title)}</div>
<div class="resource-description">${escapeHtml(item.description || 'No description')}</div>
<div class="resource-meta">
${item.model ? `<span class="resource-tag tag-model">${escapeHtml(item.model)}</span>` : ''}
${item.tools?.slice(0, 3).map(t => `<span class="resource-tag">${escapeHtml(t)}</span>`).join('') || ''}
${item.tools && item.tools.length > 3 ? `<span class="resource-tag">+${item.tools.length - 3} more</span>` : ''}
${item.hasHandoffs ? `<span class="resource-tag tag-handoffs">handoffs</span>` : ''}
</div>
</div>
<div class="resource-actions">
<a href="${getGitHubUrl(item.path)}" class="btn btn-secondary" target="_blank" onclick="event.stopPropagation()">
View on GitHub
</a>
</div>
</div>
`).join('');
// Add click handlers
list.querySelectorAll('.resource-item').forEach(el => {
el.addEventListener('click', () => {
const path = (el as HTMLElement).dataset.path;
if (path) openFileModal(path, resourceType);
});
});
}
export async function initAgentsPage(): Promise<void> {
const list = document.getElementById('resource-list');
const searchInput = document.getElementById('search-input') as HTMLInputElement;
const handoffsCheckbox = document.getElementById('filter-handoffs') as HTMLInputElement;
const clearFiltersBtn = document.getElementById('clear-filters');
const data = await fetchData<AgentsData>('agents.json');
if (!data || !data.items) {
if (list) list.innerHTML = '<div class="empty-state"><h3>Failed to load data</h3></div>';
return;
}
allItems = data.items;
search.setItems(allItems);
// Initialize Choices.js for model filter
modelSelect = createChoices('#filter-model', { placeholderValue: 'All Models' });
modelSelect.setChoices(data.filters.models.map(m => ({ value: m, label: m })), 'value', 'label', true);
document.getElementById('filter-model')?.addEventListener('change', () => {
currentFilters.models = getChoicesValues(modelSelect);
applyFiltersAndRender();
});
// Initialize Choices.js for tool filter
toolSelect = createChoices('#filter-tool', { placeholderValue: 'All Tools' });
toolSelect.setChoices(data.filters.tools.map(t => ({ value: t, label: t })), 'value', 'label', true);
document.getElementById('filter-tool')?.addEventListener('change', () => {
currentFilters.tools = getChoicesValues(toolSelect);
applyFiltersAndRender();
});
applyFiltersAndRender();
searchInput?.addEventListener('input', debounce(() => applyFiltersAndRender(), 200));
handoffsCheckbox?.addEventListener('change', () => {
currentFilters.hasHandoffs = handoffsCheckbox.checked;
applyFiltersAndRender();
});
clearFiltersBtn?.addEventListener('click', () => {
currentFilters = { models: [], tools: [], hasHandoffs: false };
modelSelect.removeActiveItems();
toolSelect.removeActiveItems();
if (handoffsCheckbox) handoffsCheckbox.checked = false;
if (searchInput) searchInput.value = '';
applyFiltersAndRender();
});
setupModal();
}
// Auto-initialize when DOM is ready
document.addEventListener('DOMContentLoaded', initAgentsPage);

View File

@@ -0,0 +1,144 @@
/**
* Collections page functionality
*/
import { createChoices, getChoicesValues, type Choices } from '../choices';
import { FuzzySearch, type SearchItem } from '../search';
import { fetchData, debounce, escapeHtml, getGitHubUrl } from '../utils';
import { setupModal, openFileModal } from '../modal';
interface Collection {
id: string;
name: string;
description?: string;
path: string;
tags?: string[];
featured?: boolean;
itemCount: number;
}
interface CollectionsData {
items: Collection[];
filters: {
tags: string[];
};
}
const resourceType = 'collection';
let allItems: Collection[] = [];
let search = new FuzzySearch();
let tagSelect: Choices;
let currentFilters = {
tags: [] as string[],
featured: false
};
function applyFiltersAndRender(): void {
const searchInput = document.getElementById('search-input') as HTMLInputElement;
const countEl = document.getElementById('results-count');
const query = searchInput?.value || '';
let results = query ? search.search(query) : [...allItems];
if (currentFilters.tags.length > 0) {
results = results.filter(item => item.tags?.some(tag => currentFilters.tags.includes(tag)));
}
if (currentFilters.featured) {
results = results.filter(item => item.featured);
}
renderItems(results, query);
const activeFilters: string[] = [];
if (currentFilters.tags.length > 0) activeFilters.push(`${currentFilters.tags.length} tag${currentFilters.tags.length > 1 ? 's' : ''}`);
if (currentFilters.featured) activeFilters.push('featured');
let countText = `${results.length} of ${allItems.length} collections`;
if (activeFilters.length > 0) {
countText += ` (filtered by ${activeFilters.join(', ')})`;
}
if (countEl) countEl.textContent = countText;
}
function renderItems(items: Collection[], query = ''): void {
const list = document.getElementById('resource-list');
if (!list) return;
if (items.length === 0) {
list.innerHTML = '<div class="empty-state"><h3>No collections found</h3><p>Try a different search term or adjust filters</p></div>';
return;
}
list.innerHTML = items.map(item => `
<div class="resource-item" data-path="${escapeHtml(item.path)}">
<div class="resource-info">
<div class="resource-title">${item.featured ? '⭐ ' : ''}${query ? search.highlight(item.name, query) : escapeHtml(item.name)}</div>
<div class="resource-description">${escapeHtml(item.description || 'No description')}</div>
<div class="resource-meta">
<span class="resource-tag">${item.itemCount} items</span>
${item.tags?.slice(0, 4).map(t => `<span class="resource-tag">${escapeHtml(t)}</span>`).join('') || ''}
${item.tags && item.tags.length > 4 ? `<span class="resource-tag">+${item.tags.length - 4} more</span>` : ''}
</div>
</div>
<div class="resource-actions">
<a href="${getGitHubUrl(item.path)}" class="btn btn-secondary" target="_blank" onclick="event.stopPropagation()">View on GitHub</a>
</div>
</div>
`).join('');
// Add click handlers
list.querySelectorAll('.resource-item').forEach(el => {
el.addEventListener('click', () => {
const path = (el as HTMLElement).dataset.path;
if (path) openFileModal(path, resourceType);
});
});
}
export async function initCollectionsPage(): Promise<void> {
const list = document.getElementById('resource-list');
const searchInput = document.getElementById('search-input') as HTMLInputElement;
const featuredCheckbox = document.getElementById('filter-featured') as HTMLInputElement;
const clearFiltersBtn = document.getElementById('clear-filters');
const data = await fetchData<CollectionsData>('collections.json');
if (!data || !data.items) {
if (list) list.innerHTML = '<div class="empty-state"><h3>Failed to load data</h3></div>';
return;
}
allItems = data.items;
// Map collection items to search items
const searchItems: SearchItem[] = allItems.map(item => ({
...item,
title: item.name,
searchText: `${item.name} ${item.description} ${item.tags?.join(' ') || ''}`.toLowerCase()
}));
search.setItems(searchItems);
tagSelect = createChoices('#filter-tag', { placeholderValue: 'All Tags' });
tagSelect.setChoices(data.filters.tags.map(t => ({ value: t, label: t })), 'value', 'label', true);
document.getElementById('filter-tag')?.addEventListener('change', () => {
currentFilters.tags = getChoicesValues(tagSelect);
applyFiltersAndRender();
});
applyFiltersAndRender();
searchInput?.addEventListener('input', debounce(() => applyFiltersAndRender(), 200));
featuredCheckbox?.addEventListener('change', () => {
currentFilters.featured = featuredCheckbox.checked;
applyFiltersAndRender();
});
clearFiltersBtn?.addEventListener('click', () => {
currentFilters = { tags: [], featured: false };
tagSelect.removeActiveItems();
if (featuredCheckbox) featuredCheckbox.checked = false;
if (searchInput) searchInput.value = '';
applyFiltersAndRender();
});
setupModal();
}
// Auto-initialize when DOM is ready
document.addEventListener('DOMContentLoaded', initCollectionsPage);

View File

@@ -0,0 +1,136 @@
/**
* Homepage functionality
*/
import { FuzzySearch, type SearchItem } from '../search';
import { fetchData, debounce, escapeHtml, truncate, getResourceIcon } from '../utils';
import { setupModal, openFileModal } from '../modal';
interface Manifest {
counts: {
agents: number;
prompts: number;
instructions: number;
skills: number;
collections: number;
};
}
interface Collection {
id: string;
name: string;
description?: string;
path: string;
tags?: string[];
featured?: boolean;
itemCount: number;
}
interface CollectionsData {
items: Collection[];
}
export async function initHomepage(): Promise<void> {
// Load manifest for stats
const manifest = await fetchData<Manifest>('manifest.json');
if (manifest && manifest.counts) {
const statsEl = document.getElementById('stats');
if (statsEl) {
statsEl.innerHTML = `
<div class="stat"><span class="stat-value">${manifest.counts.agents}</span><span class="stat-label">Agents</span></div>
<div class="stat"><span class="stat-value">${manifest.counts.prompts}</span><span class="stat-label">Prompts</span></div>
<div class="stat"><span class="stat-value">${manifest.counts.instructions}</span><span class="stat-label">Instructions</span></div>
<div class="stat"><span class="stat-value">${manifest.counts.skills}</span><span class="stat-label">Skills</span></div>
<div class="stat"><span class="stat-value">${manifest.counts.collections}</span><span class="stat-label">Collections</span></div>
`;
}
}
// Load search index
const searchIndex = await fetchData<SearchItem[]>('search-index.json');
if (searchIndex) {
const search = new FuzzySearch();
search.setItems(searchIndex);
const searchInput = document.getElementById('global-search') as HTMLInputElement;
const resultsDiv = document.getElementById('search-results');
if (searchInput && resultsDiv) {
searchInput.addEventListener('input', debounce(() => {
const query = searchInput.value.trim();
if (query.length < 2) {
resultsDiv.classList.add('hidden');
return;
}
const results = search.search(query).slice(0, 10);
if (results.length === 0) {
resultsDiv.innerHTML = '<div class="search-result-empty">No results found</div>';
} else {
resultsDiv.innerHTML = results.map(item => `
<div class="search-result" data-path="${escapeHtml(item.path)}" data-type="${escapeHtml(item.type)}">
<span class="search-result-type">${getResourceIcon(item.type)}</span>
<div>
<div class="search-result-title">${search.highlight(item.title, query)}</div>
<div class="search-result-description">${truncate(item.description, 60)}</div>
</div>
</div>
`).join('');
// Add click handlers
resultsDiv.querySelectorAll('.search-result').forEach(el => {
el.addEventListener('click', () => {
const path = (el as HTMLElement).dataset.path;
const type = (el as HTMLElement).dataset.type;
if (path && type) openFileModal(path, type);
});
});
}
resultsDiv.classList.remove('hidden');
}, 200));
// Close results when clicking outside
document.addEventListener('click', (e) => {
if (!searchInput.contains(e.target as Node) && !resultsDiv.contains(e.target as Node)) {
resultsDiv.classList.add('hidden');
}
});
}
}
// Load featured collections
const collectionsData = await fetchData<CollectionsData>('collections.json');
if (collectionsData && collectionsData.items) {
const featured = collectionsData.items.filter(c => c.featured).slice(0, 6);
const featuredEl = document.getElementById('featured-collections');
if (featuredEl) {
if (featured.length > 0) {
featuredEl.innerHTML = featured.map(c => `
<div class="card" data-path="${escapeHtml(c.path)}">
<h3>${escapeHtml(c.name)}</h3>
<p>${escapeHtml(truncate(c.description, 80))}</p>
<div class="resource-meta">
<span class="resource-tag">${c.itemCount} items</span>
${c.tags?.slice(0, 3).map(t => `<span class="resource-tag">${escapeHtml(t)}</span>`).join('') || ''}
</div>
</div>
`).join('');
// Add click handlers
featuredEl.querySelectorAll('.card').forEach(el => {
el.addEventListener('click', () => {
const path = (el as HTMLElement).dataset.path;
if (path) openFileModal(path, 'collection');
});
});
} else {
featuredEl.innerHTML = '<p style="text-align: center; color: var(--color-text-muted);">No featured collections yet</p>';
}
}
}
// Setup modal
setupModal();
}
// Auto-initialize when DOM is ready
document.addEventListener('DOMContentLoaded', initHomepage);

View File

@@ -0,0 +1,124 @@
/**
* Instructions page functionality
*/
import { createChoices, getChoicesValues, type Choices } from '../choices';
import { FuzzySearch } from '../search';
import { fetchData, debounce, escapeHtml, getGitHubUrl } from '../utils';
import { setupModal, openFileModal } from '../modal';
interface Instruction {
title: string;
description?: string;
path: string;
applyTo?: string;
extensions?: string[];
}
interface InstructionsData {
items: Instruction[];
filters: {
extensions: string[];
};
}
const resourceType = 'instruction';
let allItems: Instruction[] = [];
let search = new FuzzySearch();
let extensionSelect: Choices;
let currentFilters = { extensions: [] as string[] };
function applyFiltersAndRender(): void {
const searchInput = document.getElementById('search-input') as HTMLInputElement;
const countEl = document.getElementById('results-count');
const query = searchInput?.value || '';
let results = query ? search.search(query) : [...allItems];
if (currentFilters.extensions.length > 0) {
results = results.filter(item => {
if (currentFilters.extensions.includes('(none)') && (!item.extensions || item.extensions.length === 0)) {
return true;
}
return item.extensions?.some(ext => currentFilters.extensions.includes(ext));
});
}
renderItems(results, query);
let countText = `${results.length} of ${allItems.length} instructions`;
if (currentFilters.extensions.length > 0) {
countText += ` (filtered by ${currentFilters.extensions.length} extension${currentFilters.extensions.length > 1 ? 's' : ''})`;
}
if (countEl) countEl.textContent = countText;
}
function renderItems(items: Instruction[], query = ''): void {
const list = document.getElementById('resource-list');
if (!list) return;
if (items.length === 0) {
list.innerHTML = '<div class="empty-state"><h3>No instructions found</h3><p>Try a different search term or adjust filters</p></div>';
return;
}
list.innerHTML = items.map(item => `
<div class="resource-item" data-path="${escapeHtml(item.path)}">
<div class="resource-info">
<div class="resource-title">${query ? search.highlight(item.title, query) : escapeHtml(item.title)}</div>
<div class="resource-description">${escapeHtml(item.description || 'No description')}</div>
<div class="resource-meta">
${item.applyTo ? `<span class="resource-tag">applies to: ${escapeHtml(item.applyTo)}</span>` : ''}
${item.extensions?.slice(0, 4).map(e => `<span class="resource-tag tag-extension">${escapeHtml(e)}</span>`).join('') || ''}
${item.extensions && item.extensions.length > 4 ? `<span class="resource-tag">+${item.extensions.length - 4} more</span>` : ''}
</div>
</div>
<div class="resource-actions">
<a href="${getGitHubUrl(item.path)}" class="btn btn-secondary" target="_blank" onclick="event.stopPropagation()">View on GitHub</a>
</div>
</div>
`).join('');
// Add click handlers
list.querySelectorAll('.resource-item').forEach(el => {
el.addEventListener('click', () => {
const path = (el as HTMLElement).dataset.path;
if (path) openFileModal(path, resourceType);
});
});
}
export async function initInstructionsPage(): Promise<void> {
const list = document.getElementById('resource-list');
const searchInput = document.getElementById('search-input') as HTMLInputElement;
const clearFiltersBtn = document.getElementById('clear-filters');
const data = await fetchData<InstructionsData>('instructions.json');
if (!data || !data.items) {
if (list) list.innerHTML = '<div class="empty-state"><h3>Failed to load data</h3></div>';
return;
}
allItems = data.items;
search.setItems(allItems);
extensionSelect = createChoices('#filter-extension', { placeholderValue: 'All Extensions' });
extensionSelect.setChoices(data.filters.extensions.map(e => ({ value: e, label: e })), 'value', 'label', true);
document.getElementById('filter-extension')?.addEventListener('change', () => {
currentFilters.extensions = getChoicesValues(extensionSelect);
applyFiltersAndRender();
});
applyFiltersAndRender();
searchInput?.addEventListener('input', debounce(() => applyFiltersAndRender(), 200));
clearFiltersBtn?.addEventListener('click', () => {
currentFilters = { extensions: [] };
extensionSelect.removeActiveItems();
if (searchInput) searchInput.value = '';
applyFiltersAndRender();
});
setupModal();
}
// Auto-initialize when DOM is ready
document.addEventListener('DOMContentLoaded', initInstructionsPage);

View File

@@ -0,0 +1,119 @@
/**
* Prompts page functionality
*/
import { createChoices, getChoicesValues, type Choices } from '../choices';
import { FuzzySearch } from '../search';
import { fetchData, debounce, escapeHtml, getGitHubUrl } from '../utils';
import { setupModal, openFileModal } from '../modal';
interface Prompt {
title: string;
description?: string;
path: string;
tools?: string[];
}
interface PromptsData {
items: Prompt[];
filters: {
tools: string[];
};
}
const resourceType = 'prompt';
let allItems: Prompt[] = [];
let search = new FuzzySearch();
let toolSelect: Choices;
let currentFilters = { tools: [] as string[] };
function applyFiltersAndRender(): void {
const searchInput = document.getElementById('search-input') as HTMLInputElement;
const countEl = document.getElementById('results-count');
const query = searchInput?.value || '';
let results = query ? search.search(query) : [...allItems];
if (currentFilters.tools.length > 0) {
results = results.filter(item =>
item.tools?.some(tool => currentFilters.tools.includes(tool))
);
}
renderItems(results, query);
let countText = `${results.length} of ${allItems.length} prompts`;
if (currentFilters.tools.length > 0) {
countText += ` (filtered by ${currentFilters.tools.length} tool${currentFilters.tools.length > 1 ? 's' : ''})`;
}
if (countEl) countEl.textContent = countText;
}
function renderItems(items: Prompt[], query = ''): void {
const list = document.getElementById('resource-list');
if (!list) return;
if (items.length === 0) {
list.innerHTML = '<div class="empty-state"><h3>No prompts found</h3><p>Try a different search term or adjust filters</p></div>';
return;
}
list.innerHTML = items.map(item => `
<div class="resource-item" data-path="${escapeHtml(item.path)}">
<div class="resource-info">
<div class="resource-title">${query ? search.highlight(item.title, query) : escapeHtml(item.title)}</div>
<div class="resource-description">${escapeHtml(item.description || 'No description')}</div>
<div class="resource-meta">
${item.tools?.slice(0, 4).map(t => `<span class="resource-tag">${escapeHtml(t)}</span>`).join('') || ''}
${item.tools && item.tools.length > 4 ? `<span class="resource-tag">+${item.tools.length - 4} more</span>` : ''}
</div>
</div>
<div class="resource-actions">
<a href="${getGitHubUrl(item.path)}" class="btn btn-secondary" target="_blank" onclick="event.stopPropagation()">View on GitHub</a>
</div>
</div>
`).join('');
// Add click handlers
list.querySelectorAll('.resource-item').forEach(el => {
el.addEventListener('click', () => {
const path = (el as HTMLElement).dataset.path;
if (path) openFileModal(path, resourceType);
});
});
}
export async function initPromptsPage(): Promise<void> {
const list = document.getElementById('resource-list');
const searchInput = document.getElementById('search-input') as HTMLInputElement;
const clearFiltersBtn = document.getElementById('clear-filters');
const data = await fetchData<PromptsData>('prompts.json');
if (!data || !data.items) {
if (list) list.innerHTML = '<div class="empty-state"><h3>Failed to load data</h3></div>';
return;
}
allItems = data.items;
search.setItems(allItems);
toolSelect = createChoices('#filter-tool', { placeholderValue: 'All Tools' });
toolSelect.setChoices(data.filters.tools.map(t => ({ value: t, label: t })), 'value', 'label', true);
document.getElementById('filter-tool')?.addEventListener('change', () => {
currentFilters.tools = getChoicesValues(toolSelect);
applyFiltersAndRender();
});
applyFiltersAndRender();
searchInput?.addEventListener('input', debounce(() => applyFiltersAndRender(), 200));
clearFiltersBtn?.addEventListener('click', () => {
currentFilters = { tools: [] };
toolSelect.removeActiveItems();
if (searchInput) searchInput.value = '';
applyFiltersAndRender();
});
setupModal();
}
// Auto-initialize when DOM is ready
document.addEventListener('DOMContentLoaded', initPromptsPage);

View File

@@ -0,0 +1,219 @@
/**
* Skills page functionality
*/
import { createChoices, getChoicesValues, type Choices } from '../choices';
import { FuzzySearch } from '../search';
import { fetchData, debounce, escapeHtml, getGitHubUrl, getRawGitHubUrl } from '../utils';
import { setupModal, openFileModal } from '../modal';
import JSZip from '../jszip';
interface SkillFile {
name: string;
path: string;
}
interface Skill {
id: string;
title: string;
description?: string;
path: string;
skillFile: string;
category: string;
hasAssets: boolean;
assetCount: number;
files: SkillFile[];
}
interface SkillsData {
items: Skill[];
filters: {
categories: string[];
};
}
const resourceType = 'skill';
let allItems: Skill[] = [];
let search = new FuzzySearch();
let categorySelect: Choices;
let currentFilters = {
categories: [] as string[],
hasAssets: false
};
function applyFiltersAndRender(): void {
const searchInput = document.getElementById('search-input') as HTMLInputElement;
const countEl = document.getElementById('results-count');
const query = searchInput?.value || '';
let results = query ? search.search(query) : [...allItems];
if (currentFilters.categories.length > 0) {
results = results.filter(item => currentFilters.categories.includes(item.category));
}
if (currentFilters.hasAssets) {
results = results.filter(item => item.hasAssets);
}
renderItems(results, query);
const activeFilters: string[] = [];
if (currentFilters.categories.length > 0) activeFilters.push(`${currentFilters.categories.length} categor${currentFilters.categories.length > 1 ? 'ies' : 'y'}`);
if (currentFilters.hasAssets) activeFilters.push('has assets');
let countText = `${results.length} of ${allItems.length} skills`;
if (activeFilters.length > 0) {
countText += ` (filtered by ${activeFilters.join(', ')})`;
}
if (countEl) countEl.textContent = countText;
}
function renderItems(items: Skill[], query = ''): void {
const list = document.getElementById('resource-list');
if (!list) return;
if (items.length === 0) {
list.innerHTML = '<div class="empty-state"><h3>No skills found</h3><p>Try a different search term or adjust filters</p></div>';
return;
}
list.innerHTML = items.map(item => `
<div class="resource-item" data-path="${escapeHtml(item.skillFile)}" data-skill-id="${escapeHtml(item.id)}">
<div class="resource-info">
<div class="resource-title">${query ? search.highlight(item.title, query) : escapeHtml(item.title)}</div>
<div class="resource-description">${escapeHtml(item.description || 'No description')}</div>
<div class="resource-meta">
<span class="resource-tag tag-category">${escapeHtml(item.category)}</span>
${item.hasAssets ? `<span class="resource-tag tag-assets">${item.assetCount} asset${item.assetCount === 1 ? '' : 's'}</span>` : ''}
<span class="resource-tag">${item.files.length} file${item.files.length === 1 ? '' : 's'}</span>
</div>
</div>
<div class="resource-actions">
<button class="btn btn-primary download-skill-btn" data-skill-id="${escapeHtml(item.id)}" title="Download as ZIP">
<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor">
<path d="M2.75 14A1.75 1.75 0 0 1 1 12.25v-2.5a.75.75 0 0 1 1.5 0v2.5c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25v-2.5a.75.75 0 0 1 1.5 0v2.5A1.75 1.75 0 0 1 13.25 14Z"/>
<path d="M7.25 7.689V2a.75.75 0 0 1 1.5 0v5.689l1.97-1.969a.749.749 0 1 1 1.06 1.06l-3.25 3.25a.749.749 0 0 1-1.06 0L4.22 6.78a.749.749 0 1 1 1.06-1.06l1.97 1.969Z"/>
</svg>
Download
</button>
<a href="${getGitHubUrl(item.path)}" class="btn btn-secondary" target="_blank" onclick="event.stopPropagation()">View Folder</a>
</div>
</div>
`).join('');
// Add click handlers for opening modal
list.querySelectorAll('.resource-item').forEach(el => {
el.addEventListener('click', (e) => {
// Don't trigger modal if clicking download button or github link
if ((e.target as HTMLElement).closest('.resource-actions')) return;
const path = (el as HTMLElement).dataset.path;
if (path) openFileModal(path, resourceType);
});
});
// Add download handlers
list.querySelectorAll('.download-skill-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
const skillId = (btn as HTMLElement).dataset.skillId;
if (skillId) downloadSkill(skillId, btn as HTMLButtonElement);
});
});
}
async function downloadSkill(skillId: string, btn: HTMLButtonElement): Promise<void> {
const skill = allItems.find(item => item.id === skillId);
if (!skill || !skill.files || skill.files.length === 0) {
alert('No files found for this skill');
return;
}
const originalContent = btn.innerHTML;
btn.disabled = true;
btn.innerHTML = '<svg class="spinner" viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M8 0a8 8 0 1 0 8 8h-1.5A6.5 6.5 0 1 1 8 1.5V0z"/></svg> Preparing...';
try {
const zip = new JSZip();
const folder = zip.folder(skill.id);
const fetchPromises = skill.files.map(async (file) => {
const url = getRawGitHubUrl(file.path);
try {
const response = await fetch(url);
if (!response.ok) return null;
const content = await response.text();
return { name: file.name, content };
} catch {
return null;
}
});
const results = await Promise.all(fetchPromises);
let addedFiles = 0;
for (const result of results) {
if (result && folder) {
folder.file(result.name, result.content);
addedFiles++;
}
}
if (addedFiles === 0) throw new Error('Failed to fetch any files');
const blob = await zip.generateAsync({ type: 'blob' });
const downloadUrl = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = `${skill.id}.zip`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(downloadUrl);
btn.innerHTML = '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.75.75 0 0 1 1.06-1.06L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0z"/></svg> Downloaded!';
setTimeout(() => { btn.disabled = false; btn.innerHTML = originalContent; }, 2000);
} catch {
btn.innerHTML = '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.75.75 0 1 1 1.06 1.06L9.06 8l3.22 3.22a.75.75 0 0 1-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 0 1-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06z"/></svg> Failed';
setTimeout(() => { btn.disabled = false; btn.innerHTML = originalContent; }, 2000);
}
}
export async function initSkillsPage(): Promise<void> {
const list = document.getElementById('resource-list');
const searchInput = document.getElementById('search-input') as HTMLInputElement;
const hasAssetsCheckbox = document.getElementById('filter-has-assets') as HTMLInputElement;
const clearFiltersBtn = document.getElementById('clear-filters');
const data = await fetchData<SkillsData>('skills.json');
if (!data || !data.items) {
if (list) list.innerHTML = '<div class="empty-state"><h3>Failed to load data</h3></div>';
return;
}
allItems = data.items;
search.setItems(allItems);
categorySelect = createChoices('#filter-category', { placeholderValue: 'All Categories' });
categorySelect.setChoices(data.filters.categories.map(c => ({ value: c, label: c })), 'value', 'label', true);
document.getElementById('filter-category')?.addEventListener('change', () => {
currentFilters.categories = getChoicesValues(categorySelect);
applyFiltersAndRender();
});
applyFiltersAndRender();
searchInput?.addEventListener('input', debounce(() => applyFiltersAndRender(), 200));
hasAssetsCheckbox?.addEventListener('change', () => {
currentFilters.hasAssets = hasAssetsCheckbox.checked;
applyFiltersAndRender();
});
clearFiltersBtn?.addEventListener('click', () => {
currentFilters = { categories: [], hasAssets: false };
categorySelect.removeActiveItems();
if (hasAssetsCheckbox) hasAssetsCheckbox.checked = false;
if (searchInput) searchInput.value = '';
applyFiltersAndRender();
});
setupModal();
}
// Auto-initialize when DOM is ready
document.addEventListener('DOMContentLoaded', initSkillsPage);

View File

@@ -0,0 +1,155 @@
/**
* Fuzzy search implementation for the Awesome Copilot website
* Simple substring matching on title and description with scoring
*/
import { escapeHtml, fetchData } from './utils';
export interface SearchItem {
title: string;
description?: string;
searchText?: string;
path: string;
type: string;
[key: string]: unknown;
}
export interface SearchOptions {
fields?: string[];
limit?: number;
minScore?: number;
}
export class FuzzySearch {
private items: SearchItem[] = [];
constructor(items: SearchItem[] = []) {
this.items = items;
}
/**
* Update the items to search
*/
setItems(items: SearchItem[]): void {
this.items = items;
}
/**
* Search items with fuzzy matching
*/
search(query: string, options: SearchOptions = {}): SearchItem[] {
const {
fields = ['title', 'description', 'searchText'],
limit = 50,
minScore = 0,
} = options;
if (!query || query.trim().length === 0) {
return this.items.slice(0, limit);
}
const normalizedQuery = query.toLowerCase().trim();
const queryWords = normalizedQuery.split(/\s+/);
const results: Array<{ item: SearchItem; score: number }> = [];
for (const item of this.items) {
const score = this.calculateScore(item, queryWords, fields);
if (score > minScore) {
results.push({ item, score });
}
}
// Sort by score descending
results.sort((a, b) => b.score - a.score);
return results.slice(0, limit).map(r => r.item);
}
/**
* Calculate match score for an item
*/
private calculateScore(item: SearchItem, queryWords: string[], fields: string[]): number {
let totalScore = 0;
for (const word of queryWords) {
let wordScore = 0;
for (const field of fields) {
const value = item[field];
if (!value) continue;
const normalizedValue = String(value).toLowerCase();
// Exact match in title gets highest score
if (field === 'title' && normalizedValue === word) {
wordScore = Math.max(wordScore, 100);
}
// Title starts with word
else if (field === 'title' && normalizedValue.startsWith(word)) {
wordScore = Math.max(wordScore, 80);
}
// Title contains word
else if (field === 'title' && normalizedValue.includes(word)) {
wordScore = Math.max(wordScore, 60);
}
// Description contains word
else if (field === 'description' && normalizedValue.includes(word)) {
wordScore = Math.max(wordScore, 30);
}
// searchText (includes tags, tools, etc) contains word
else if (field === 'searchText' && normalizedValue.includes(word)) {
wordScore = Math.max(wordScore, 20);
}
}
totalScore += wordScore;
}
// Bonus for matching all words
const matchesAllWords = queryWords.every(word =>
fields.some(field => {
const value = item[field];
return value && String(value).toLowerCase().includes(word);
})
);
if (matchesAllWords && queryWords.length > 1) {
totalScore *= 1.5;
}
return totalScore;
}
/**
* Highlight matching text in a string
*/
highlight(text: string, query: string): string {
if (!query || !text) return escapeHtml(text || '');
const normalizedQuery = query.toLowerCase().trim();
const words = normalizedQuery.split(/\s+/);
let result = escapeHtml(text);
for (const word of words) {
if (word.length < 2) continue;
const regex = new RegExp(`(${word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
result = result.replace(regex, '<mark>$1</mark>');
}
return result;
}
}
// Global search instance
export const globalSearch = new FuzzySearch();
/**
* Initialize global search with search index
*/
export async function initGlobalSearch(): Promise<FuzzySearch> {
const searchIndex = await fetchData<SearchItem[]>('search-index.json');
if (searchIndex) {
globalSearch.setItems(searchIndex);
}
return globalSearch;
}

View File

@@ -0,0 +1,62 @@
/**
* Theme management for the Awesome Copilot website
* Supports light/dark mode with user preference storage
*/
const THEME_KEY = 'theme';
/**
* Get the current theme preference
*/
function getThemePreference(): 'light' | 'dark' {
const stored = localStorage.getItem(THEME_KEY);
if (stored === 'light' || stored === 'dark') {
return stored;
}
// Check system preference
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) {
return 'light';
}
return 'dark';
}
/**
* Apply theme to the document
*/
function applyTheme(theme: 'light' | 'dark'): void {
document.documentElement.setAttribute('data-theme', theme);
}
/**
* Toggle between light and dark theme
*/
export function toggleTheme(): void {
const current = document.documentElement.getAttribute('data-theme') as 'light' | 'dark';
const newTheme = current === 'light' ? 'dark' : 'light';
applyTheme(newTheme);
localStorage.setItem(THEME_KEY, newTheme);
}
/**
* Initialize theme toggle button
*/
export function initThemeToggle(): void {
const toggleBtn = document.getElementById('theme-toggle');
if (toggleBtn) {
toggleBtn.addEventListener('click', toggleTheme);
}
// Listen for system theme changes
if (window.matchMedia) {
window.matchMedia('(prefers-color-scheme: light)').addEventListener('change', (e) => {
// Only auto-switch if user hasn't set a preference
const stored = localStorage.getItem(THEME_KEY);
if (!stored) {
applyTheme(e.matches ? 'light' : 'dark');
}
});
}
}
// Auto-initialize when DOM is ready
document.addEventListener('DOMContentLoaded', initThemeToggle);

View File

@@ -0,0 +1,190 @@
/**
* Utility functions for the Awesome Copilot website
*/
const REPO_BASE_URL = 'https://raw.githubusercontent.com/github/awesome-copilot/main';
const REPO_GITHUB_URL = 'https://github.com/github/awesome-copilot/blob/main';
// VS Code install URL template
const VSCODE_INSTALL_URLS: Record<string, string> = {
instructions: 'https://aka.ms/awesome-copilot/install/instructions',
prompt: 'https://aka.ms/awesome-copilot/install/prompt',
agent: 'https://aka.ms/awesome-copilot/install/agent',
};
/**
* Get the base path for the site
*/
export function getBasePath(): string {
// In Astro, import.meta.env.BASE_URL is available at build time
// At runtime, we use a data attribute on the body
if (typeof document !== 'undefined') {
return document.body.dataset.basePath || '/';
}
return '/';
}
/**
* Fetch JSON data from the data directory
*/
export async function fetchData<T = unknown>(filename: string): Promise<T | null> {
try {
const basePath = getBasePath();
const response = await fetch(`${basePath}data/${filename}`);
if (!response.ok) throw new Error(`Failed to fetch ${filename}`);
return await response.json();
} catch (error) {
console.error(`Error fetching ${filename}:`, error);
return null;
}
}
/**
* Fetch raw file content from GitHub
*/
export async function fetchFileContent(filePath: string): Promise<string | null> {
try {
const response = await fetch(`${REPO_BASE_URL}/${filePath}`);
if (!response.ok) throw new Error(`Failed to fetch ${filePath}`);
return await response.text();
} catch (error) {
console.error(`Error fetching file content:`, error);
return null;
}
}
/**
* Copy text to clipboard
*/
export async function copyToClipboard(text: string): Promise<boolean> {
try {
await navigator.clipboard.writeText(text);
return true;
} catch {
// Fallback for older browsers
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'fixed';
textarea.style.opacity = '0';
document.body.appendChild(textarea);
textarea.select();
const success = document.execCommand('copy');
document.body.removeChild(textarea);
return success;
}
}
/**
* Generate VS Code install URL
*/
export function getVSCodeInstallUrl(type: string, filePath: string): string | null {
const baseUrl = VSCODE_INSTALL_URLS[type];
if (!baseUrl) return null;
return `${baseUrl}?url=${encodeURIComponent(`${REPO_BASE_URL}/${filePath}`)}`;
}
/**
* Get GitHub URL for a file
*/
export function getGitHubUrl(filePath: string): string {
return `${REPO_GITHUB_URL}/${filePath}`;
}
/**
* Get raw GitHub URL for a file (for fetching content)
*/
export function getRawGitHubUrl(filePath: string): string {
return `${REPO_BASE_URL}/${filePath}`;
}
/**
* Show a toast notification
*/
export function showToast(message: string, type: 'success' | 'error' = 'success'): void {
const existing = document.querySelector('.toast');
if (existing) existing.remove();
const toast = document.createElement('div');
toast.className = `toast ${type}`;
toast.textContent = message;
document.body.appendChild(toast);
setTimeout(() => {
toast.remove();
}, 3000);
}
/**
* Debounce function for search input
*/
export function debounce<T extends (...args: unknown[]) => void>(
func: T,
wait: number
): (...args: Parameters<T>) => void {
let timeout: ReturnType<typeof setTimeout>;
return function executedFunction(...args: Parameters<T>) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
/**
* Escape HTML to prevent XSS
*/
export function escapeHtml(text: string): string {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
/**
* Truncate text with ellipsis
*/
export function truncate(text: string | undefined, maxLength: number): string {
if (!text || text.length <= maxLength) return text || '';
return text.slice(0, maxLength).trim() + '...';
}
/**
* Get resource type from file path
*/
export function getResourceType(filePath: string): string {
if (filePath.endsWith('.agent.md')) return 'agent';
if (filePath.endsWith('.prompt.md')) return 'prompt';
if (filePath.endsWith('.instructions.md')) return 'instruction';
if (filePath.includes('/skills/') && filePath.endsWith('SKILL.md')) return 'skill';
if (filePath.endsWith('.collection.yml')) return 'collection';
return 'unknown';
}
/**
* Format a resource type for display
*/
export function formatResourceType(type: string): string {
const labels: Record<string, string> = {
agent: '🤖 Agent',
prompt: '🎯 Prompt',
instruction: '📋 Instruction',
skill: '⚡ Skill',
collection: '📦 Collection',
};
return labels[type] || type;
}
/**
* Get icon for resource type
*/
export function getResourceIcon(type: string): string {
const icons: Record<string, string> = {
agent: '🤖',
prompt: '🎯',
instruction: '📋',
skill: '⚡',
collection: '📦',
};
return icons[type] || '📄';
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
{
"generated": "2026-01-28T03:53:29.513Z",
"generated": "2026-01-28T04:53:00.935Z",
"counts": {
"agents": 140,
"prompts": 134,