From fdfd27a97ee24059ef8fd6a1355a6143991b874d Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 5 Jun 2026 09:03:31 +0000 Subject: [PATCH 1/9] =?UTF-8?q?feat(website):=20Phase=201=20=E2=80=94=20da?= =?UTF-8?q?ta=20layer=20+=20learn/glossary/cookbook=20pages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ports all catalogue data from the prototype into typed TypeScript modules, wires up the resources.ts stub with real items, and builds out all the missing Awesome GitHub pages from scratch. Data layer: - src/lib/catalogue.ts — 110+ ITEMS across 8 categories, URL builders, type info - src/lib/learn.ts — 4 LEARN_TRACKS with 10 lessons, 3 COOKBOOK_RECIPES - src/lib/glossary.ts — 5 GLOSSARY_GROUPS (37 terms), 6 REFERENCE_GROUPS - src/lib/resources.ts — now returns real data via catalogue New pages: - /awesome-github/getting-started — 6-step onboarding with copy-to-clipboard - /awesome-github/learn/ — 4-track learning centre - /awesome-github/learn/[track]/ — per-track overview with lesson list - /awesome-github/learn/[track]/[lesson] — lesson reader with prev/next nav - /awesome-github/glossary/ — grouped term index with sidebar - /awesome-github/glossary/[term] — term detail with related terms - /awesome-github/cookbook/ — recipe index with kind badges - /awesome-github/cookbook/[slug] — recipe detail with GitHub link Updated: - index.astro — uses real catalogue counts (was hardcoded) - AwesomeGithubNav — adds Learn, Cookbook, Glossary links Build: 251 pages, 0 errors https://claude.ai/code/session_01VaY86RbnELdWvFyBdEMwLH --- .../AwesomeGithub/AwesomeGithubNav.astro | 7 +- website/src/lib/catalogue.ts | 441 ++++++++++++++++++ website/src/lib/glossary.ts | 193 ++++++++ website/src/lib/learn.ts | 152 ++++++ website/src/lib/resources.ts | 121 ++--- .../awesome-github/cookbook/[slug].astro | 255 ++++++++++ .../pages/awesome-github/cookbook/index.astro | 192 ++++++++ .../awesome-github/getting-started.astro | 399 ++++++++++++++++ .../awesome-github/glossary/[term].astro | 315 +++++++++++++ .../pages/awesome-github/glossary/index.astro | 293 ++++++++++++ website/src/pages/awesome-github/index.astro | 39 +- .../learn/[track]/[lesson].astro | 365 +++++++++++++++ .../awesome-github/learn/[track]/index.astro | 329 +++++++++++++ .../pages/awesome-github/learn/index.astro | 291 ++++++++++++ 14 files changed, 3299 insertions(+), 93 deletions(-) create mode 100644 website/src/lib/catalogue.ts create mode 100644 website/src/lib/glossary.ts create mode 100644 website/src/lib/learn.ts create mode 100644 website/src/pages/awesome-github/cookbook/[slug].astro create mode 100644 website/src/pages/awesome-github/cookbook/index.astro create mode 100644 website/src/pages/awesome-github/getting-started.astro create mode 100644 website/src/pages/awesome-github/glossary/[term].astro create mode 100644 website/src/pages/awesome-github/glossary/index.astro create mode 100644 website/src/pages/awesome-github/learn/[track]/[lesson].astro create mode 100644 website/src/pages/awesome-github/learn/[track]/index.astro create mode 100644 website/src/pages/awesome-github/learn/index.astro diff --git a/website/src/components/AwesomeGithub/AwesomeGithubNav.astro b/website/src/components/AwesomeGithub/AwesomeGithubNav.astro index 7744cbe1..e4b710c5 100644 --- a/website/src/components/AwesomeGithub/AwesomeGithubNav.astro +++ b/website/src/components/AwesomeGithub/AwesomeGithubNav.astro @@ -8,9 +8,10 @@ const { base, pathname } = Astro.props; const navLinks = [ { href: `${base}awesome-github/`, path: "/awesome-github/", label: "Home", exact: true }, - { href: `${base}awesome-github/c/agents`, path: "/awesome-github/c/", label: "Catalogue", exact: false }, - { href: `${base}awesome-github/getting-started`, path: "/awesome-github/getting-started", label: "Getting Started", exact: true }, - { href: `${base}awesome-github/learn`, path: "/awesome-github/learn", label: "Learning", exact: false }, + { href: `${base}awesome-github/c/agents/`, path: "/awesome-github/c/", label: "Catalogue", exact: false }, + { href: `${base}awesome-github/learn/`, path: "/awesome-github/learn", label: "Learn", exact: false }, + { href: `${base}awesome-github/cookbook/`, path: "/awesome-github/cookbook", label: "Cookbook", exact: false }, + { href: `${base}awesome-github/glossary/`, path: "/awesome-github/glossary", label: "Glossary", exact: false }, ]; const isActive = (linkPath: string, exact: boolean): boolean => { diff --git a/website/src/lib/catalogue.ts b/website/src/lib/catalogue.ts new file mode 100644 index 00000000..39365c3b --- /dev/null +++ b/website/src/lib/catalogue.ts @@ -0,0 +1,441 @@ +/* ────────────────────────────────────────────────────────────────── + Catalogue data — ported from design_source/data.js + All paths are real files/folders in lightspeedwp/.github + ────────────────────────────────────────────────────────────────── */ + +export const REPO = "lightspeedwp/.github"; + +export type ItemType = "install" | "aiDefault" | "workflow" | "guardrail" | "pack" | "script" | "schema" | "recipe" | "mixed"; + +export interface TypeInfo { + label: string; + badge: string; + note: string; +} + +export interface Category { + id: string; + label: string; + type: ItemType | "mixed"; + blurb: string; + icon: string; +} + +export interface CatalogueItem { + id: string; + cat: string; + slug: string; + name: string; + description: string; + type: ItemType; + tags: string[]; + version: string; + updated: string; + applyTo?: string; + path?: string; + tree: boolean; + body?: string | null; + run?: string | null; + validates?: string | null; + dest?: string | null; + duration?: string | null; + action?: string | null; +} + +export interface UrlSet { + blob: string; + raw: string; + vscode: string; +} + +export const TYPES: Record = { + install: { + label: "Installable file", + badge: "Single-file", + note: "A single-file Copilot customisation — copy the raw file or install it straight into VS Code.", + }, + aiDefault: { + label: "AI default file", + badge: "AI default", + note: "A default AI configuration file. Copy or download it into your repository root — it isn't a VS Code customisation.", + }, + workflow: { + label: "Installable workflow", + badge: "Workflow", + note: "A portable spec paired with a runnable GitHub Action. Copy the spec, or reference the Action with uses:.", + }, + guardrail: { + label: "Guardrail config", + badge: "Guardrail", + note: "A pre-commit or lint guardrail. Copy the config into place — there's no VS Code install for these.", + }, + pack: { + label: "Plugin pack", + badge: "Pack", + note: "A versioned, installable bundle of governance and AI-ops. Install the pack or open the folder.", + }, + script: { + label: "Script", + badge: "Reference", + note: "Run it from the repo. Many scripts are paired with a schema that validates their inputs.", + }, + schema: { + label: "Schema", + badge: "Validates", + note: "A JSON schema that validates a specific resource type. Goes hand-in-hand with the scripts that read it.", + }, + recipe: { + label: "Recipe", + badge: "Recipe", + note: "A step-by-step playbook — read it, follow it, copy what you need.", + }, +}; + +export const CATEGORIES: Category[] = [ + { id: "agents", label: "Agents", type: "install", blurb: "Specialised AI agents with defined behaviour, scope, and escalation rules.", icon: "robot" }, + { id: "instructions", label: "Instructions", type: "install", blurb: "Canonical coding, accessibility, and WordPress standards Copilot must follow.", icon: "book" }, + { id: "prompts", label: "Prompts", type: "install", blurb: "Reusable prompt templates you can grab and run for common engineering tasks.", icon: "chat" }, + { id: "skills", label: "Skills", type: "install", blurb: "Portable, self-contained skill packages the team can run on demand.", icon: "sparkles" }, + { id: "hooks", label: "Hooks", type: "guardrail", blurb: "Pre-commit and lint guardrails that enforce quality before code lands.", icon: "shield" }, + { id: "workflows", label: "Workflows", type: "workflow", blurb: "Portable agentic workflow specs, each paired with a runnable GitHub Action.", icon: "workflow" }, + { id: "plugins", label: "Plugins", type: "pack", blurb: "Installable, versioned plugin packs bundling governance and AI-ops.", icon: "puzzle" }, + { id: "tools", label: "Tools", type: "mixed", blurb: "The toolchain layer — AI defaults, scripts, schemas, and editor config.", icon: "wrench" }, +]; + +export const NAV_GROUPS = { + browse: ["agents", "instructions", "prompts", "skills", "hooks", "workflows", "plugins", "tools"], +}; + +export function urlsFor(item: CatalogueItem, branch: string = "main"): UrlSet { + const b = branch; + const p = item.path || ""; + const kind = item.tree ? "tree" : "blob"; + const blob = `https://github.com/${REPO}/${kind}/${b}/${p}`; + const raw = `https://raw.githubusercontent.com/${REPO}/${b}/${p}`; + const route: Record = { instructions: "chat-instructions", prompts: "chat-prompt", agents: "chat-mode", skills: "chat-prompt" }; + const vsRoute = route[item.cat] || "chat-instructions"; + const vscode = `vscode:${vsRoute}/install?url=${encodeURIComponent(raw)}`; + return { blob, raw, vscode }; +} + +export function installable(item: CatalogueItem): boolean { + return !item.tree && item.type === "install"; +} + +export function cloneCmd(branch: string): string { + return branch === "develop" + ? `git clone -b develop https://github.com/${REPO}.git` + : `git clone https://github.com/${REPO}.git`; +} + +/* ── Markdown bodies for representative items ── */ +const MD: Record = {}; + +MD["reviewer"] = `--- +description: Diff-aware code review focused on standards, a11y, security, and performance. +applyTo: "**" +--- + +# Code reviewer agent + +Given a diff, return a **✅ / ⚠️ summary**, then inline comments +(\`file:line\`) focusing on: + +- **Standards** — WordPress Coding Standards (PHP, JS, CSS), naming, structure. +- **Accessibility** — semantic markup, ARIA only where needed, focus order, contrast. +- **Security** — sanitise on input, escape on output, nonces, capability checks. +- **Performance** — block-scoped asset loading, avoid N+1 queries, cache where safe. + +Every comment must include a **concrete fix**, not just a flag. + +> Pairs with \`instructions/coding-standards.instructions.md\` and \`instructions/a11y.instructions.md\`.`; + +MD["plugin-structure"] = `--- +description: WordPress block plugin structure conventions — layout, block.json, enqueueing, security, i18n. +applyTo: "**" +tags: [wordpress, plugin, blocks, block-json, php, i18n] +--- + +# WordPress block plugin structure + +You are a WordPress block plugin architect. Follow our block-first +conventions to scaffold and maintain LightSpeed plugins. + +## General rules + +- Scaffold new blocks with \`@wordpress/create-block\`. +- Use \`block.json\` as the canonical source of block metadata. +- Separate editor assets from front-end assets. +- Register blocks via \`register_block_type()\` pointing at \`block.json\`. +- Apply \`sanitize_*\`, \`esc_*\`, and \`wp_kses_post()\` at all boundaries. +- Use a plugin-specific text domain; run \`wp-scripts i18n make-pot\`. + +## Security + +\`\`\`php +// Validate, then escape on output +$title = sanitize_text_field( $attributes['title'] ?? '' ); +echo '

' . esc_html( $title ) . '

'; +\`\`\``; + +MD["custom-instructions"] = `--- +description: Organisation-wide Copilot behaviour for every LightSpeed repository. +applyTo: "**" +--- + +# LightSpeed Copilot custom instructions + +These are the default instructions surfaced to Copilot across **every** +repo in the \`lightspeedwp\` organisation via the \`.github\` control plane. + +## Always + +- British English in prose; \`text-domain\` in code stays lowercase-hyphen. +- WordPress Coding Standards for PHP, JS, CSS, HTML. +- Accessibility is non-negotiable: semantic HTML, AA contrast, keyboard paths. +- Sanitise on input, escape on output, nonce every state-changing request. + +## Never + +- Suggest page-builder shortcodes where a block exists. +- Enqueue editor assets on the front end. +- Invent APIs — cite the WordPress handbook when unsure.`; + +MD["a11y"] = `--- +description: Accessibility standards for WordPress themes, blocks, and patterns (WCAG 2.2 AA). +applyTo: "**/*.{php,js,jsx,html,css}" +--- + +# Accessibility instructions + +Target **WCAG 2.2 AA** on every surface we ship. + +- Use semantic landmarks; one \`

\` per view, no skipped heading levels. +- All interactive controls reachable and operable by keyboard. +- Visible focus styles — never \`outline: none\` without a replacement. +- Colour contrast ≥ 4.5:1 for text, ≥ 3:1 for UI and large text. +- Respect \`prefers-reduced-motion\`; gate non-essential animation. +- Label every input; associate errors with \`aria-describedby\`.`; + +MD["release"] = `--- +description: Agent that prepares Keep-a-Changelog releases and version bumps. +--- + +# Release agent + +You own the release ritual for LightSpeed packages. + +1. Read \`CHANGELOG.md\` (Keep-a-Changelog format). +2. Group merged PRs since the last tag into Added / Changed / Fixed / Removed. +3. Propose the next SemVer version; never bump major without sign-off. +4. Open a release PR; never push tags directly to \`main\`. + +Escalate to a maintainer for any breaking change or licence-affecting edit.`; + +function item(cat: string, slug: string, name: string, description: string, opts: Partial = {}): CatalogueItem { + return { + id: `${cat}/${slug}`, + cat, + slug, + name, + description, + type: (opts.type as ItemType) || "install", + tags: opts.tags || [], + version: opts.version || "v1.0", + updated: opts.updated || "2026-06", + applyTo: opts.applyTo, + path: opts.path, + tree: !!opts.tree, + body: opts.body || null, + run: opts.run || null, + validates: opts.validates || null, + dest: opts.dest || null, + duration: opts.duration || null, + action: opts.action || null, + }; +} + +/* ── PROMPTS ── */ +const PROMPT_DEFS: [string, string, string, string[]][] = [ + ["agent-setup", "Agent setup", "Initial agent context, instructions, and configuration to bootstrap a new agent.", ["agents", "setup"]], + ["code-generation", "Code generation", "Code implementation, scaffolding, and generation against project conventions.", ["code", "scaffold"]], + ["code-review", "Code review", "Code review, quality feedback, and standards enforcement on a diff.", ["review", "quality"]], + ["debugging", "Debugging", "Problem diagnosis, root-cause analysis, and resolution of a failing case.", ["debug", "diagnosis"]], + ["documentation", "Documentation", "Documentation creation, updates, and refinement for a feature or module.", ["docs"]], + ["testing", "Testing", "Test suite creation, debugging, and coverage improvements.", ["testing", "qa"]], + ["refactoring", "Refactoring", "Code refactoring, optimisation, and modernisation without behaviour change.", ["refactor", "quality"]], + ["review-and-refactor", "Review & refactor", "A combined pass: review the code, then refactor against the findings.", ["review", "refactor"]], + ["create-specification", "Create specification", "Turn a feature idea into a formal, testable specification.", ["specs", "planning"]], + ["create-implementation-plan", "Create implementation plan", "Produce a phased, testable implementation plan from a spec.", ["planning", "specs"]], + ["update-implementation-plan", "Update implementation plan", "Revise an existing implementation plan as scope or status changes.", ["planning"]], + ["plan-breakdown", "Plan breakdown", "Break a plan into actionable, ordered steps.", ["planning"]], + ["create-adr", "Create ADR", "Capture an architecture decision, its context, and consequences as a numbered record.", ["adr", "architecture"]], + ["architecture-blueprint", "Architecture blueprint", "Generate an architecture blueprint describing a codebase's structure.", ["architecture", "docs"]], + ["technology-stack-blueprint", "Tech stack blueprint", "Document a project's technology stack and the reasons behind it.", ["architecture", "docs"]], + ["folder-structure-blueprint", "Folder structure blueprint", "Document and explain a project's folder structure.", ["architecture", "docs"]], + ["readme-blueprint", "README blueprint", "Blueprint the structure of a project README before writing it.", ["docs", "readme"]], + ["create-readme", "Create README", "Draft a complete, structured README for a project.", ["docs", "readme"]], + ["create-agentsmd", "Create AGENTS.md", "Generate an AGENTS.md describing how AI agents should work in a repo.", ["agents", "docs"]], + ["create-llms", "Create llms.txt", "Generate an llms.txt summary so AI tools understand the project.", ["ai", "docs"]], + ["add-frontmatter", "Add frontmatter", "Add or fix YAML frontmatter on a file against the canonical schema.", ["frontmatter", "schema"]], + ["documentation-writer", "Documentation writer", "Write or refine end-user-facing documentation in our house style.", ["docs"]], + ["docs-from-comments", "Docs from comments", "Generate documentation from inline code comments and signatures.", ["docs", "code"]], + ["conventional-commit", "Conventional commit", "Write a Conventional Commits-formatted commit message for a change.", ["git", "commits"]], + ["git-branch-creator", "Git branch creator", "Suggest a branch name that follows the org branching strategy.", ["git", "branching"]], + ["epic-breakdown-product", "Epic breakdown — product", "Break an epic into product-facing features and outcomes.", ["planning", "product"]], + ["epic-breakdown-architecture", "Epic breakdown — architecture", "Break an epic into architectural and technical work.", ["planning", "architecture"]], + ["feature-breakdown-prd", "Feature breakdown — PRD", "Break a feature down from a product requirements document.", ["planning", "product"]], + ["feature-breakdown-implementation", "Feature breakdown — implementation", "Break a feature into concrete implementation tasks.", ["planning"]], + ["test-breakdown", "Test breakdown", "Break testing work into a structured set of tasks and cases.", ["testing", "planning"]], + ["prompt-builder", "Prompt builder", "Build and refine a reusable prompt, step by step.", ["prompts", "ai"]], + ["model-recommendation", "Model recommendation", "Recommend the right AI model for a given task and budget.", ["ai", "models"]], + ["reporting", "Reporting", "Generate a metrics or status report from project data.", ["reporting", "metrics"]], + ["repo-story-time", "Repo story time", "Narrate a repository's history, structure, and decisions.", ["docs", "history"]], + ["project-workflow-analysis-blueprint", "Workflow analysis blueprint", "Analyse and document a project's end-to-end workflow.", ["analysis", "workflow"]], + ["generate-custom-instructions-from-codebase", "Custom instructions from codebase", "Derive Copilot custom instructions by reading an existing codebase.", ["copilot", "instructions"]], + ["python-mcp-server-generator", "Python MCP server generator", "Scaffold a Python MCP server with the right structure and tooling.", ["mcp", "python"]], + ["dockerfile-multi-stage", "Multi-stage Dockerfile", "Author an optimised multi-stage Dockerfile for a service.", ["docker", "devops"]], + ["shuffle-json-data", "Shuffle JSON data", "Shuffle or transform JSON test fixtures while keeping them valid.", ["json", "fixtures"]], +]; + +const PROMPTS = PROMPT_DEFS.map(([slug, name, desc, tags]) => + item("prompts", slug, name, desc, { type: "install", tags, path: `prompts/${slug}.prompt` }) +); + +/* ── AI DEFAULTS ── */ +const AI_DEFAULT_DEFS: [string, string, string, string][] = [ + ["claude", "Claude.md", "Authoritative Claude-specific guidance and pointers for LightSpeed repositories.", "ai/Claude.md"], + ["gemini", "Gemini.md", "Authoritative Google Gemini configuration and integration guidelines.", "ai/Gemini.md"], + ["agents", "agents.md", "Authoritative index for LightSpeed AI agent governance and implementation sources.", "ai/agents.md"], + ["runners", "RUNNERS.md", "Canonical inventory of JavaScript and Bash runners plus telemetry hooks.", "ai/RUNNERS.md"], +]; + +const AI_DEFAULTS = AI_DEFAULT_DEFS.map(([slug, name, desc, path]) => + item("tools", "ai-" + slug, name, desc, { type: "aiDefault", tags: ["ai", "default", "repo-root"], path, dest: "repository root" }) +); + +/* ── SCRIPTS ── */ +const SCRIPTS_ITEMS: CatalogueItem[] = [ + item("tools", "labeling-agent", "Labeling agent runner", "Applies the canonical label taxonomy to issues and PRs from content and file paths.", { type: "script", path: "scripts/agents/labeling.agent.js", run: "node scripts/agents/labeling.agent.js", validates: "labels", tags: ["agents", "labels"] }), + item("tools", "reviewer-agent", "Reviewer agent runner", "Posts a ✅/⚠️ PR review summary, categorising changed files by risk and flagging blockers.", { type: "script", path: "scripts/agents/reviewer.agent.js", run: "node scripts/agents/reviewer.agent.js", tags: ["agents", "review"] }), + item("tools", "planner-agent", "Planner agent runner", "Posts merge-readiness checklists and exit criteria to pull requests.", { type: "script", path: "scripts/agents/planner.agent.js", run: "node scripts/agents/planner.agent.js", tags: ["agents", "planning"] }), + item("tools", "audit-frontmatter", "Audit frontmatter", "Validates instruction, prompt, and agent frontmatter against the canonical schema.", { type: "script", path: "scripts/audit-frontmatter.js", run: "node scripts/audit-frontmatter.js", validates: "frontmatter", tags: ["validation", "frontmatter"] }), + item("tools", "validate-coderabbit", "Validate CodeRabbit config", "Validates the CodeRabbit configuration against its overrides schema.", { type: "script", path: "scripts/validation/validate-coderabbit-yml.cjs", run: "node scripts/validation/validate-coderabbit-yml.cjs", validates: "coderabbit", tags: ["validation", "yaml"] }), + item("tools", "verify-docs-commands", "Verify docs commands", "Checks that commands referenced in the docs actually exist and run.", { type: "script", path: "scripts/verify-docs-commands.js", run: "node scripts/verify-docs-commands.js", tags: ["validation", "docs"] }), + item("tools", "audit-branding", "Audit branding patterns", "Audits assets and patterns for brand conformance and reports gaps.", { type: "script", path: "scripts/audit-branding-patterns.js", run: "node scripts/audit-branding-patterns.js", validates: "branding", tags: ["audit", "branding"] }), + item("tools", "bump-file-version", "Bump file version", "Increments the version field on a file's frontmatter following SemVer.", { type: "script", path: "scripts/bump-file-version.cjs", run: "node scripts/bump-file-version.cjs ", validates: "version", tags: ["versioning"] }), + item("tools", "consolidate-issue-types", "Consolidate issue types", "Reconciles issue types against the canonical issue-types taxonomy.", { type: "script", path: "scripts/consolidate-issue-types.js", run: "node scripts/consolidate-issue-types.js", tags: ["issues", "governance"] }), + item("tools", "fix-staleness-dates", "Fix staleness dates", "Refreshes last_updated dates across docs to keep staleness honest.", { type: "script", path: "scripts/fix-staleness-dates.js", run: "node scripts/fix-staleness-dates.js", tags: ["docs", "maintenance"] }), + item("tools", "fix-mermaid", "Fix Mermaid diagrams", "Repairs malformed Mermaid diagram blocks in markdown.", { type: "script", path: "scripts/fix-mermaid-diagrams.js", run: "node scripts/fix-mermaid-diagrams.js", tags: ["docs", "mermaid"] }), + item("tools", "gather-metrics", "Gather metrics", "Collects repository metrics for the reporting pipeline.", { type: "script", path: "scripts/gather-metrics.js", run: "node scripts/gather-metrics.js", tags: ["metrics", "reporting"] }), +]; + +/* ── SCHEMAS ── */ +const SCHEMAS_ITEMS: CatalogueItem[] = [ + item("tools", "frontmatter-schema", "Frontmatter schema", "The master schema every instruction, prompt, and agent's frontmatter is validated against.", { type: "schema", path: "schema/frontmatter.schema.json", validates: "Instructions · Prompts · Agents", tags: ["frontmatter", "json"] }), + item("tools", "agent-config-schema", "Agent config schema", "Validates an agent's configuration — name, scope, model, and escalation rules.", { type: "schema", path: "schema/agent-config.schema.json", validates: "Agents", tags: ["agents", "json"] }), + item("tools", "skill-metadata-schema", "Skill metadata schema", "Validates the metadata block that describes a portable skill package.", { type: "schema", path: "schema/skill-metadata.schema.json", validates: "Skills", tags: ["skills", "json"] }), + item("tools", "skill-agent-config-schema", "Skill agent config schema", "Validates the agent configuration embedded inside a skill.", { type: "schema", path: "schema/skill-agent-config.schema.json", validates: "Skills", tags: ["skills", "json"] }), + item("tools", "plugin-manifest-schema", "Plugin manifest schema", "Validates a plugin pack's manifest — contents, dependencies, and version.", { type: "schema", path: "schema/plugin-manifest.schema.json", validates: "Plugins", tags: ["plugins", "json"] }), + item("tools", "changelog-schema", "Changelog schema", "Validates Keep-a-Changelog entries used by the release process.", { type: "schema", path: "schema/changelog.schema.json", validates: "Releases", tags: ["changelog", "json"] }), + item("tools", "version-schema", "Version schema", "Validates SemVer version strings across resources and packs.", { type: "schema", path: "schema/version.schema.json", validates: "Versioning", tags: ["versioning", "json"] }), + item("tools", "branding-schema", "Branding schema", "Validates branding assets and patterns against the brand definition.", { type: "schema", path: "schema/branding-schema.json", validates: "Branding audit", tags: ["branding", "json"] }), + item("tools", "project-fields-schema", "Project fields schema", "Validates GitHub Project field definitions used by automation.", { type: "schema", path: "schema/project-fields.schema.json", validates: "Project boards", tags: ["projects", "json"] }), + item("tools", "footer-config-schema", "Footer config schema", "Validates the footer configuration block shared across repos.", { type: "schema", path: "schema/footer-config.schema.json", validates: "Footer config", tags: ["config", "json"] }), + item("tools", "coderabbit-schema", "CodeRabbit overrides", "Validates CodeRabbit review configuration overrides.", { type: "schema", path: "schema/coderabbit-overrides.v2.json", validates: "CodeRabbit config", tags: ["coderabbit", "json"] }), + item("tools", "schema-registry", "Schema registry", "The index of every portable schema and what it owns.", { type: "schema", path: "schema/schema-registry.json", validates: "All schemas", tags: ["registry", "json"] }), +]; + +/* ── CONFIG TOOLS ── */ +const CONFIG_TOOLS_ITEMS: CatalogueItem[] = [ + item("tools", "vscode", "VS Code workspace", "Recommended extensions, settings, and tasks for a consistent dev environment.", { type: "script", path: ".vscode", tree: true, tags: ["vscode", "setup"] }), + item("tools", "editorconfig", "EditorConfig", "Cross-editor indentation and whitespace rules.", { type: "script", path: ".editorconfig", tags: ["editorconfig", "format"] }), + item("tools", "env-template", "Env template", "Annotated .env.example covering every variable our tooling expects.", { type: "script", path: ".env.example", tags: ["env", "setup"] }), + item("tools", "labels", "Labels manifest", "The canonical labels.yml every member repo inherits.", { type: "script", path: ".github/labels.yml", tags: ["labels", "yaml"] }), +]; + +export const ITEMS: CatalogueItem[] = [ + /* ── AGENTS ── */ + item("agents", "reviewer", "Code reviewer", "Diff-aware reviewer enforcing standards, a11y, security and performance with concrete fixes.", { type: "install", tags: ["review", "quality", "a11y"], path: "agents/reviewer.agent.md", body: MD["reviewer"] }), + item("agents", "release", "Release", "Prepares Keep-a-Changelog releases, groups merged PRs, and proposes SemVer bumps.", { type: "install", tags: ["release", "changelog", "git"], path: "agents/release.agent.md", body: MD["release"] }), + item("agents", "adr", "ADR author", "Captures architecture decisions, context, and consequences as numbered records.", { type: "install", tags: ["adr", "architecture", "docs"], path: "agents/adr.agent.md" }), + item("agents", "labeling", "Labeling", "Applies the canonical label taxonomy to issues and PRs from content and paths.", { type: "install", tags: ["labels", "triage", "automation"], path: "agents/labeling.agent.md" }), + item("agents", "task-planner", "Task planner", "Decomposes an epic into phased, testable implementation tasks.", { type: "install", tags: ["planning", "epics"], path: "agents/task-planner.agent.md" }), + item("agents", "reporting", "Reporting", "Generates metrics and status reports across the organisation's repositories.", { type: "install", tags: ["reporting", "metrics"], path: "agents/reporting.agent.md" }), + item("agents", "prompt-engineer", "Prompt engineer", "Drafts and refines reusable prompts and agent system messages.", { type: "install", tags: ["prompts", "ai"], path: "agents/prompt-engineer.agent.md" }), + item("agents", "testing", "Testing", "Plans and reviews test coverage against our quality-assurance standard.", { type: "install", tags: ["testing", "qa"], path: "agents/testing.agent.md" }), + item("agents", "linting", "Linting", "Runs and explains lint failures across PHP, JS, YAML, and Markdown.", { type: "install", tags: ["lint", "quality"], path: "agents/linting.agent.md" }), + + /* ── INSTRUCTIONS ── */ + item("instructions", "custom-instructions", "Org Copilot instructions", "The default org-wide Copilot behaviour surfaced across every LightSpeed repository.", { type: "install", tags: ["copilot", "org-wide", "governance"], version: "v3.1", applyTo: "**", path: ".github/custom-instructions.md", body: MD["custom-instructions"] }), + item("instructions", "coding-standards", "Coding standards", "Unified WordPress Coding Standards for PHP, JS, CSS, and HTML across all repos.", { type: "install", tags: ["wpcs", "php", "javascript"], applyTo: "**", path: "instructions/coding-standards.instructions.md" }), + item("instructions", "a11y", "Accessibility", "WCAG 2.2 AA standards for themes, blocks, and patterns — semantics, focus, contrast.", { type: "install", tags: ["a11y", "wcag", "keyboard"], version: "v2.0", applyTo: "**/*.{php,js,html,css}", path: "instructions/a11y.instructions.md", body: MD["a11y"] }), + item("instructions", "plugin-structure", "Plugin structure", "Block-first plugin layout, block.json conventions, asset enqueueing, security and i18n.", { type: "install", tags: ["wordpress", "plugin", "block-json"], applyTo: "**", path: ".github/instructions/plugin-structure.instructions.md", body: MD["plugin-structure"] }), + item("instructions", "languages", "Languages", "JS/TS, JSON, YAML, and JSDoc conventions in one consolidated standard.", { type: "install", tags: ["javascript", "typescript", "yaml"], applyTo: "**", path: "instructions/languages.instructions.md" }), + item("instructions", "linting", "Linting", "ESLint, Prettier, PHPCS, markdownlint, and YAML lint rules and config.", { type: "install", tags: ["eslint", "phpcs", "prettier"], applyTo: "**", path: "instructions/linting.instructions.md" }), + item("instructions", "labeling", "Labeling", "How labels are named, coloured, and applied across the organisation.", { type: "install", tags: ["labels", "triage"], applyTo: "**", path: "instructions/labeling.instructions.md" }), + item("instructions", "quality-assurance", "Quality assurance", "Testing, Jest, coverage, and CI gates consolidated into one standard.", { type: "install", tags: ["testing", "jest", "ci"], applyTo: "**", path: "instructions/quality-assurance.instructions.md" }), + item("instructions", "spec-driven-workflow", "Spec-driven workflow", "Spec-first delivery: specification, plan, implementation, validation.", { type: "install", tags: ["specs", "workflow", "planning"], applyTo: "**", path: "instructions/spec-driven-workflow.instructions.md" }), + item("instructions", "file-organisation", "File organisation", "Where files live and how they're named across LightSpeed repositories.", { type: "install", tags: ["structure", "naming"], applyTo: "**", path: "instructions/file-organisation.instructions.md" }), + item("instructions", "documentation-formats", "Documentation formats", "Markdown, frontmatter, and Mermaid conventions for all docs.", { type: "install", tags: ["markdown", "frontmatter", "mermaid"], applyTo: "**", path: "instructions/documentation-formats.instructions.md" }), + item("instructions", "community-standards", "Community standards", "File org, naming, README, and saved-reply conventions for community health.", { type: "install", tags: ["community", "readme"], applyTo: "**", path: "instructions/community-standards.instructions.md" }), + + /* ── PROMPTS ── */ + ...PROMPTS, + + /* ── SKILLS ── */ + item("skills", "pr-review", "PR review", "Portable skill that reviews a pull request against LightSpeed standards.", { type: "install", tags: ["review", "pr", "quality"], path: "skills/lightspeed-pr-review", tree: true }), + item("skills", "frontmatter-audit", "Frontmatter audit", "Validates instruction, prompt, and agent frontmatter against the schema.", { type: "install", tags: ["frontmatter", "schema", "audit"], path: "skills/lightspeed-frontmatter-audit", tree: true }), + item("skills", "label-governance", "Label governance", "Audits and reconciles labels against the canonical taxonomy.", { type: "install", tags: ["labels", "governance"], path: "skills/lightspeed-label-governance", tree: true }), + item("skills", "agent-creator", "Agent creator", "Scaffolds a new agent package — system prompt, references, and checks.", { type: "install", tags: ["agents", "scaffold"], path: "skills/design-md-agent/agent-creator", tree: true }), + item("skills", "apply-design-system", "Apply design system", "Applies a design system's tokens and components to a target surface.", { type: "install", tags: ["design-system", "tokens"], path: "skills/design-md-agent/apply-design-system", tree: true }), + item("skills", "audit-design-system", "Audit design system", "Audits a surface for design-system conformance and reports gaps.", { type: "install", tags: ["design-system", "audit"], path: "skills/design-md-agent/audit-design-system", tree: true }), + item("skills", "ai-governance-documentor", "AI governance documentor", "Generates an AI governance guide from a minimal set of client inputs.", { type: "install", tags: ["governance", "docs", "ai"], path: "skills/design-md-agent/ai-governance-documentor", tree: true }), + + /* ── HOOKS ── */ + item("hooks", "husky", "Husky pre-commit", "The pre-commit hook chain that runs lint and format checks before code lands.", { type: "guardrail", tags: ["pre-commit", "husky", "git"], path: ".husky", tree: true }), + item("hooks", "markdownlint", "Markdown lint", "Enforce heading style, spacing, and list formatting on every markdown change.", { type: "guardrail", tags: ["markdown", "lint"], path: ".markdownlint.config.cjs" }), + item("hooks", "eslint", "ESLint config", "Shared ESLint flat config for JS and TS across the organisation.", { type: "guardrail", tags: ["eslint", "javascript"], path: ".eslint.config.cjs" }), + item("hooks", "spectral", "Spectral lint", "Lint reusable Actions and workflow YAML for syntax integrity and policy.", { type: "guardrail", tags: ["spectral", "workflows", "yaml"], path: ".spectral.yaml" }), + item("hooks", "yamllint", "YAML lint", "Validate YAML indentation and structure before it reaches CI.", { type: "guardrail", tags: ["yaml", "lint"], path: ".yamllint.config.cjs" }), + item("hooks", "prettier", "Prettier config", "Shared formatting rules so every repo writes code the same way.", { type: "guardrail", tags: ["prettier", "format"], path: ".prettier.config.cjs" }), + + /* ── PLUGINS ── */ + item("plugins", "github-ops", "LightSpeed GitHub Ops", "The flagship installable pack: governance, automation, and AI-ops in one bundle.", { type: "pack", tags: ["pack", "governance", "ai-ops"], path: "plugins/lightspeed-github-ops", tree: true }), + item("plugins", "plugins-readme", "Plugin packs overview", "How plugin packs are structured, versioned, and installed.", { type: "pack", tags: ["pack", "docs"], path: "plugins/README.md" }), + + /* ── WORKFLOWS ── */ + item("workflows", "wordpress-project-onboarding", "WordPress project onboarding", "Stands up a new WordPress project with every LightSpeed standard, template, and guardrail in place.", { type: "workflow", duration: "2–3 hours", tags: ["onboarding", "wordpress", "setup"], path: "workflows/wordpress-project-onboarding.md", action: ".github/workflows/labeling.yml" }), + item("workflows", "wordpress-spec-to-implementation", "WordPress spec → implementation", "Turns a WordPress PRD into working, tested code through a phased agentic workflow.", { type: "workflow", duration: "4–8 hours", tags: ["specs", "implementation", "testing"], path: "workflows/wordpress-spec-to-implementation.md", action: ".github/workflows/testing.yml" }), + item("workflows", "portable-ai-plugin-restructure", "Portable AI plugin restructure", "Reorganises and ports AI plugins to the portable, manifest-driven structure.", { type: "workflow", duration: "6–10 hours", tags: ["plugins", "restructure", "ai-ops"], path: "workflows/portable-ai-plugin-restructure.md", action: ".github/workflows/linting.yml" }), + item("workflows", "release-readiness-validation", "Release readiness validation", "Validates that a project meets every exit criterion before a release is cut.", { type: "workflow", duration: "1–2 hours", tags: ["release", "validation", "ci"], path: "workflows/release-readiness-validation.md", action: ".github/workflows/release.yml" }), + item("workflows", "weekly-governance-sync", "Weekly governance sync", "Synchronises labels, templates, and standards across every repo on a weekly cadence.", { type: "workflow", duration: "~1 hour", tags: ["governance", "sync", "scheduled"], path: "workflows/weekly-governance-sync.md", action: ".github/workflows/project-meta-sync.yml" }), + + /* ── TOOLS ── */ + ...SCRIPTS_ITEMS, + ...SCHEMAS_ITEMS, + ...CONFIG_TOOLS_ITEMS, + ...AI_DEFAULTS, +]; + +/* ── Helpers ── */ + +export function getItemsByCategory(cat: string): CatalogueItem[] { + return ITEMS.filter((i) => i.cat === cat); +} + +export function getItemBySlug(cat: string, slug: string): CatalogueItem | undefined { + return ITEMS.find((i) => i.cat === cat && i.slug === slug); +} + +export function getCategoryInfo(id: string): Category | undefined { + return CATEGORIES.find((c) => c.id === id); +} + +export function getCategoryCounts(): Record { + const counts: Record = {}; + for (const item of ITEMS) { + counts[item.cat] = (counts[item.cat] || 0) + 1; + } + return counts; +} diff --git a/website/src/lib/glossary.ts b/website/src/lib/glossary.ts new file mode 100644 index 00000000..efa7c687 --- /dev/null +++ b/website/src/lib/glossary.ts @@ -0,0 +1,193 @@ +/* ────────────────────────────────────────────────────────────────── + Glossary data — ported from glossary-data.js + ────────────────────────────────────────────────────────────────── */ + +import { REPO } from "./catalogue"; + +export interface GlossaryEntry { + slug: string; + term: string; + def: string; + why: string; + related: string[]; +} + +export interface GlossaryGroup { + id: string; + label: string; + blurb: string; + entries: GlossaryEntry[]; +} + +export interface ReferenceItem { + p: string; + d: string; + tree?: boolean; +} + +export interface ReferenceGroup { + id: string; + label: string; + blurb: string; + items: ReferenceItem[]; +} + +export function refUrl(path: string, branch: string = "main", tree: boolean = false): string { + const kind = tree ? "tree" : "blob"; + return `https://github.com/${REPO}/${kind}/${branch}/${path}`; +} + +export const GLOSSARY_GROUPS: GlossaryGroup[] = [ + { + id: "lightspeed", + label: "LightSpeed terms", + blurb: "The vocabulary specific to how LightSpeed runs the .github control plane.", + entries: [ + { slug: "control-plane", term: "Control plane", def: "A single repository — here, .github — that governs configuration, automation, and standards across an entire organisation or fleet of repositories.", why: "It's the whole idea of the site: one place to change a standard, and every repo moves with it.", related: ["single-source-of-truth", "hub-and-spoke", "repository-inheritance"] }, + { slug: "canonical-assets", term: "Canonical assets", def: "Source-of-truth files — instructions, schemas, workflows, prompts — maintained in one place and inherited or distributed everywhere else.", why: "Stops the same instruction file from drifting into five slightly different copies.", related: ["single-source-of-truth", "portable-assets"] }, + { slug: "hooks-layer", term: "Hooks layer", def: "A semantic abstraction over automation. A hook describes what should happen (\"label new issues\") without saying where or how it runs.", why: "Lets us talk about intent separately from GitHub Actions plumbing — the same hook can target different runners.", related: ["workflow-layer", "decoupling"] }, + { slug: "workflow-layer", term: "Workflow layer", def: "The GitHub Actions implementation that turns hook declarations into executable CI/CD jobs.", why: "The mechanics live here, so hooks stay portable and the engine can change underneath them.", related: ["hooks-layer", "github-actions", "decoupling"] }, + { slug: "plugin-pack", term: "Plugin pack", def: "A curated, versioned bundle of capabilities — governance, automation, and AI-ops — distributed as a reusable collection.", why: "It's the pivot of the whole model — the repo stops being only a governance hub and becomes something you install.", related: ["manifest", "plugin-distribution", "portable-assets"] }, + { slug: "manifest", term: "Manifest", def: "A structured JSON or YAML file that declares what a plugin pack contains, its dependencies, and its configuration.", why: "Makes a pack discoverable and validatable by machines — adoption without manual copying.", related: ["plugin-pack", "schema-validation"] }, + { slug: "plugin-distribution", term: "Plugin distribution", def: "Packaging and delivering reusable plugins from the .github control plane out to consuming repositories.", why: "Teams adopt capabilities without forking or hand-copying files.", related: ["plugin-pack", "portable-assets"] }, + { slug: "portable-assets", term: "Portable assets", def: "Agents, instructions, hooks, and workflows designed to work outside the repo they were born in — no hard-coded paths or local assumptions.", why: "Portability is what makes the plugin-pack model possible.", related: ["canonical-assets", "portability"] }, + { slug: "repository-inheritance", term: "Repository inheritance", def: "A repo automatically picking up configuration, workflows, and templates from a parent .github repo.", why: "New projects get the standards for free on day one.", related: ["control-plane", "inheritance-boundaries"] }, + { slug: "template-system", term: "Template system", def: "A framework for generating consistent files — issue templates, PR templates, docs — across repos using frontmatter and placeholders.", why: "Every repo asks for the same structured information without anyone re-writing the forms.", related: ["frontmatter", "issue-template", "pull-request-template"] }, + { slug: "frontmatter", term: "Frontmatter", def: "A block of YAML metadata at the top of a Markdown file, fenced by ---. Declares properties, schemas, and automation rules.", why: "It's how every catalogue item carries its description, version, tags, and apply-to scope.", related: ["schema-validation", "canonical-assets"] }, + ], + }, + { + id: "github", + label: "GitHub basics", + blurb: "The GitHub primitives the control plane is built on.", + entries: [ + { slug: "github-actions", term: "GitHub Actions", def: "GitHub's built-in CI/CD platform for running scripts, tests, and deployments triggered by repository events.", why: "It's the engine the workflow layer compiles down to.", related: ["workflow", "workflow-layer"] }, + { slug: "workflow", term: "Workflow", def: "A YAML automation file in .github/workflows/ describing jobs triggered by GitHub events.", why: "The reusable building block we publish in the Workflows catalogue.", related: ["github-actions", "workflow-layer"] }, + { slug: "issue-template", term: "Issue template", def: "A pre-formatted Markdown file that populates the New Issue form to capture structured information.", why: "Surfaced org-wide from the control plane so every repo triages the same way.", related: ["template-system", "label"] }, + { slug: "pull-request-template", term: "Pull request template", def: "A pre-formatted file that guides contributors through a PR, often with testing, docs, and accessibility checklists.", why: "Keeps review quality consistent across every repo.", related: ["template-system"] }, + { slug: "label", term: "Label", def: "A tag on issues and PRs used to categorise, prioritise, and filter work.", why: "Canonical labels live in the control plane so triage means the same thing everywhere.", related: ["automation-rule"] }, + { slug: "automation-rule", term: "Automation rule", def: "A condition-and-action spec that auto-applies labels, assigns reviewers, or closes issues based on metadata or content.", why: "Powers governance that runs itself instead of relying on memory.", related: ["label", "ai-driven-governance"] }, + { slug: "semantic-versioning", term: "Semantic versioning", def: "A MAJOR.MINOR.PATCH scheme that signals the nature of a change.", why: "Every resource and plugin pack is versioned so teams can adopt updates predictably.", related: ["plugin-pack", "manifest"] }, + ], + }, + { + id: "aiops", + label: "AI-ops concepts", + blurb: "How AI gets governed, not just used.", + entries: [ + { slug: "agent", term: "Agent", def: "An AI-powered system that autonomously performs tasks — labelling issues, drafting release notes, reviewing code — given instructions and context.", why: "The Agents catalogue is exactly these, scoped and versioned.", related: ["skill", "copilot", "task-delegation"] }, + { slug: "skill", term: "Skill", def: "A self-contained, reusable automation capability bundling logic, docs, and examples so it travels across projects.", why: "Skills are the portable recipes in the Skills catalogue.", related: ["agent", "portable-assets"] }, + { slug: "ai-driven-governance", term: "AI-driven governance", def: "Using AI agents to enforce standards, policies, and conventions across repositories.", why: "The point of the whole repo — consistency at a scale humans can't review by hand.", related: ["agent", "automation-rule", "control-plane"] }, + { slug: "copilot", term: "Copilot", def: "GitHub Copilot, an AI assistant that generates code, docs, and automation, and can be steered by custom instructions.", why: "Our instructions install straight into Copilot so it follows LightSpeed standards.", related: ["prompt-engineering", "agent"] }, + { slug: "prompt-engineering", term: "Prompt engineering", def: "Crafting instructions and context to guide an AI agent toward consistent, high-quality behaviour.", why: "Why our prompts and instructions are versioned, reviewed assets — not throwaway text.", related: ["copilot", "llm"] }, + { slug: "schema-validation", term: "Schema validation", def: "Automated checking that data — frontmatter, issue metadata, config — matches a declared structure.", why: "Keeps every catalogue item valid before it ships.", related: ["frontmatter", "manifest"] }, + { slug: "task-delegation", term: "Task delegation", def: "Handing a well-scoped task — with context, constraints, and exit criteria — to an AI agent to complete.", why: "The whole workflow layer is built on this model.", related: ["agent", "skill"] }, + { slug: "llm", term: "LLM", def: "Large Language Model — the generative AI foundation underlying Copilot, Claude, and other agents.", why: "Understanding the model helps you write instructions that work reliably.", related: ["copilot", "prompt-engineering"] }, + ], + }, + { + id: "architecture", + label: "Architecture patterns", + blurb: "The structural patterns that make the control plane composable.", + entries: [ + { slug: "single-source-of-truth", term: "Single source of truth", def: "One canonical location for each piece of configuration or content — no copies that can drift.", why: "Why the .github repo exists: one place to update, every dependent picks it up.", related: ["canonical-assets", "control-plane"] }, + { slug: "hub-and-spoke", term: "Hub-and-spoke", def: "A topology where one central repo (the hub) distributes standards and configuration to many satellite repos (the spokes).", why: "The architectural pattern behind org-wide inheritance.", related: ["control-plane", "repository-inheritance"] }, + { slug: "inheritance-boundaries", term: "Inheritance boundaries", def: "The explicit rules about which configurations flow automatically from the hub versus which must be opted into.", why: "Prevents accidental override of org-level standards by repo-level config.", related: ["repository-inheritance", "single-source-of-truth"] }, + { slug: "modular-architecture", term: "Modular architecture", def: "Designing systems as independent, composable units that can be combined without tight coupling.", why: "What lets skills, hooks, and workflows be portable across repos.", related: ["decoupling", "portability"] }, + { slug: "decoupling", term: "Decoupling", def: "Separating the intent of an action (the hook) from its implementation (the workflow) so each can change independently.", why: "The hooks-layer / workflow-layer split is a direct application of this.", related: ["hooks-layer", "workflow-layer", "modular-architecture"] }, + { slug: "portability", term: "Portability", def: "The property of a component that lets it run in multiple environments without modification.", why: "Portable assets are the whole point of the Skills and Workflows catalogues.", related: ["portable-assets", "modular-architecture"] }, + { slug: "scalability", term: "Scalability", def: "The ability of the control plane to govern more repos without proportionally more effort.", why: "Automation and AI-driven governance are how we scale standards across a growing organisation.", related: ["ai-driven-governance", "single-source-of-truth"] }, + ], + }, + { + id: "wordpress", + label: "WordPress context", + blurb: "WordPress-specific terms that shape how we build plugins and agents.", + entries: [ + { slug: "wp-agent-skills", term: "WP agent skills", def: "Agent skills tuned to WordPress conventions — block.json, WPCS, i18n, and the wp-scripts toolchain.", why: "Our Skills catalogue includes WordPress-specific automation so agents follow platform conventions.", related: ["skill", "agent"] }, + { slug: "gpl", term: "GPL", def: "The GNU General Public Licence — the open-source licence WordPress and most of its ecosystem use.", why: "All code we ship for WordPress must be GPL-compatible.", related: [] }, + { slug: "wp-plugin", term: "WordPress plugin", def: "A PHP package that extends WordPress using its hooks and APIs, registered via the main plugin file header.", why: "Our plugin-structure instruction governs how LightSpeed plugins are built.", related: ["gpl"] }, + { slug: "block-editor", term: "Block editor", def: "The Gutenberg-based editor that replaced the classic editor in WordPress 5.0, powered by React and block.json.", why: "Block-first development is our default — agents and instructions enforce it.", related: ["wp-plugin"] }, + ], + }, +]; + +export const REFERENCE_GROUPS: ReferenceGroup[] = [ + { + id: "positioning", + label: "Positioning & strategy", + blurb: "The high-level docs that explain why the repo exists and how it's structured.", + items: [ + { p: "README.md", d: "Repo overview and entry point" }, + { p: "docs/ARCHITECTURE.md", d: "How the repo layers are organised" }, + { p: "AGENTS.md", d: "Global AI rules for every agent" }, + ], + }, + { + id: "governance", + label: "Governance & labelling", + blurb: "The standards that make issues and PRs legible across every repo.", + items: [ + { p: ".github/labels.yml", d: "Canonical label taxonomy" }, + { p: "docs/LABELING.md", d: "Labelling strategy and one-hot rule" }, + { p: "docs/ISSUE_TYPES.md", d: "32-type issue taxonomy" }, + { p: "docs/AUTOMATION.md", d: "Which workflows run where" }, + ], + }, + { + id: "triage", + label: "Triage & templates", + blurb: "Templates and forms that capture structured data from contributors.", + items: [ + { p: ".github/ISSUE_TEMPLATE", d: "Issue template directory", tree: true }, + { p: ".github/PULL_REQUEST_TEMPLATE.md", d: "PR template" }, + { p: ".github/DISCUSSION_TEMPLATE", d: "Discussion templates", tree: true }, + ], + }, + { + id: "ai", + label: "AI defaults & agents", + blurb: "The canonical AI configuration files and agent sources.", + items: [ + { p: "ai/Claude.md", d: "Claude-specific guidance" }, + { p: "ai/Gemini.md", d: "Gemini configuration" }, + { p: "ai/agents.md", d: "Agent governance index" }, + { p: "agents", d: "All agent source files", tree: true }, + ], + }, + { + id: "quality", + label: "Quality & release", + blurb: "The gates a change passes through and the release ritual.", + items: [ + { p: "docs/LINTING.md", d: "Linting strategy" }, + { p: "docs/TESTING.md", d: "Testing approach and CI gates" }, + { p: "docs/RELEASE_PROCESS.md", d: "Release ritual" }, + { p: "docs/BRANCHING_STRATEGY.md", d: "Branch naming and protection" }, + ], + }, + { + id: "pivot", + label: "Plugin-pack pivot", + blurb: "The docs describing the plugin-distribution model.", + items: [ + { p: "plugins", d: "Plugin packs directory", tree: true }, + { p: "plugins/README.md", d: "Plugin packs overview" }, + { p: "docs/PLUGIN_INSTALLATION_GUIDE.md", d: "Installation guide" }, + ], + }, +]; + +/* ── Helpers ── */ + +export function getAllEntries(): GlossaryEntry[] { + return GLOSSARY_GROUPS.flatMap((g) => g.entries); +} + +export function getEntry(slug: string): GlossaryEntry | undefined { + return getAllEntries().find((e) => e.slug === slug); +} + +export function getRelatedEntries(entry: GlossaryEntry): GlossaryEntry[] { + return entry.related.map((slug) => getEntry(slug)).filter(Boolean) as GlossaryEntry[]; +} diff --git a/website/src/lib/learn.ts b/website/src/lib/learn.ts new file mode 100644 index 00000000..0cf0147c --- /dev/null +++ b/website/src/lib/learn.ts @@ -0,0 +1,152 @@ +/* ────────────────────────────────────────────────────────────────── + Learning Centre + Cookbook metadata — ported from learn-data.js + ────────────────────────────────────────────────────────────────── */ + +export interface Lesson { + slug: string; + doc: string; + src: string; + learn: string; +} + +export interface FurtherLink { + p: string; + d: string; +} + +export interface LearnTrack { + id: string; + label: string; + icon: string; + blurb: string; + lessons: Lesson[]; + further: FurtherLink[]; +} + +export interface CookbookRecipe { + slug: string; + doc: string; + kind: "Playbook" | "Example" | "Checklist"; + src: string; + title: string; + when: string; +} + +export const LEARN_TRACKS: LearnTrack[] = [ + { + id: "oriented", + label: "Getting oriented", + icon: "layers", + blurb: "Start here. How the control plane is put together and how change flows to stable.", + lessons: [ + { slug: "architecture", doc: "ARCHITECTURE", src: "docs/ARCHITECTURE.md", learn: "How the .github repo is layered — GitHub-native, portable assets, and docs — and how data flows through it." }, + { slug: "branching", doc: "BRANCHING_STRATEGY", src: "docs/BRANCHING_STRATEGY.md", learn: "How main and develop relate, how branches are named, and how a change reaches stable." }, + ], + further: [ + { p: "docs/WORKFLOW_COORDINATION.md", d: "How workflows coordinate across the org" }, + { p: "docs/FRONTMATTER_SCHEMA.md", d: "The frontmatter schema in depth" }, + ], + }, + { + id: "governance", + label: "Governance & labelling", + icon: "shield", + blurb: "The taxonomy and automation that keep work legible across every repository.", + lessons: [ + { slug: "labelling", doc: "LABELING", src: "docs/LABELING.md", learn: "The canonical label families, the one-hot rule, and how labelling drives automation." }, + { slug: "issue-types", doc: "ISSUE_TYPES", src: "docs/ISSUE_TYPES.md", learn: "The issue-type taxonomy and how 32 types map to a handful of project fields." }, + { slug: "automation", doc: "AUTOMATION", src: "docs/AUTOMATION.md", learn: "Which workflows run on which branch, the agents behind them, and the configs they read." }, + ], + further: [ + { p: "docs/LABEL_STRATEGY.md", d: "Label strategy rationale" }, + { p: "docs/LABEL_COLOR_STRATEGY.md", d: "Label colour strategy" }, + { p: "docs/LABEL_INVENTORY.md", d: "Full label inventory" }, + { p: "docs/ISSUE_FIELDS.md", d: "Project field definitions" }, + { p: "docs/ISSUE_CREATION_GUIDE.md", d: "Issue creation guide" }, + { p: "docs/METRICS.md", d: "Metrics and reporting" }, + ], + }, + { + id: "quality", + label: "Quality & release", + icon: "check", + blurb: "The gates a change passes through — linting, testing — and the ritual of shipping it.", + lessons: [ + { slug: "linting", doc: "LINTING", src: "docs/LINTING.md", learn: "The linting strategy across PHP, JS, YAML, and Markdown, and how it's enforced." }, + { slug: "testing", doc: "TESTING", src: "docs/TESTING.md", learn: "The testing approach, coverage expectations, and the CI gates that protect main." }, + { slug: "release-process", doc: "RELEASE_PROCESS", src: "docs/RELEASE_PROCESS.md", learn: "The end-to-end release ritual — changelog, versioning, tagging, and release notes." }, + ], + further: [ + { p: "docs/VERSIONING.md", d: "Versioning policy" }, + { p: "docs/HUSKY_PRECOMMITS.md", d: "Husky pre-commit hooks" }, + { p: "docs/PR_CREATION_PROCESS.md", d: "Pull-request creation process" }, + ], + }, + { + id: "agents", + label: "Working with agents", + icon: "robot", + blurb: "How the planner and reviewer agents are built, configured, and run in practice.", + lessons: [ + { slug: "agent-architecture", doc: "AGENT_ARCHITECTURE", src: "docs/agents/AGENT_ARCHITECTURE.md", learn: "The module system, interfaces, and logging shared by the planner and reviewer agents." }, + { slug: "reviewer-runbook", doc: "REVIEWER_RUNBOOK", src: "docs/agents/REVIEWER_RUNBOOK.md", learn: "Deploying, configuring, and troubleshooting the Reviewer agent — env vars and all." }, + ], + further: [ + { p: "docs/AGENT_CREATION.md", d: "Creating a new agent" }, + { p: "docs/PLUGIN_INSTALLATION_GUIDE.md", d: "Installing plugin packs" }, + ], + }, +]; + +export const COOKBOOK_RECIPES: CookbookRecipe[] = [ + { + slug: "project-planning-and-prd-playbook", + doc: "project-planning-and-prd-playbook", + kind: "Playbook", + src: "cookbook/project-planning-and-prd-playbook.md", + title: "Project planning & PRD playbook", + when: "Use at intake — when a project is a brief, not yet a scoped plan.", + }, + { + slug: "spec-driven-workflow-example", + doc: "spec-driven-workflow-example", + kind: "Example", + src: "cookbook/spec-driven-workflow-example.md", + title: "Spec-driven workflow example", + when: "Use when you want a worked example of turning a spec into working code.", + }, + { + slug: "wordpress-plugin-checklist", + doc: "wordpress-plugin-checklist", + kind: "Checklist", + src: "cookbook/wordpress-plugin-checklist.md", + title: "WordPress plugin checklist", + when: "Use before shipping a plugin — a final pass over structure, security, and i18n.", + }, +]; + +export function readingTime(body: string | undefined | null): number { + if (!body) return 1; + const words = body.trim().split(/\s+/).length; + return Math.max(1, Math.round(words / 200)); +} + +export function getTrack(id: string): LearnTrack | undefined { + return LEARN_TRACKS.find((t) => t.id === id); +} + +export function getLesson(trackId: string, lessonSlug: string): Lesson | undefined { + const track = getTrack(trackId); + return track?.lessons.find((l) => l.slug === lessonSlug); +} + +export function getAdjacentLessons(trackId: string, lessonSlug: string): { prev?: Lesson; next?: Lesson } { + const track = getTrack(trackId); + if (!track) return {}; + const idx = track.lessons.findIndex((l) => l.slug === lessonSlug); + return { prev: idx > 0 ? track.lessons[idx - 1] : undefined, next: idx < track.lessons.length - 1 ? track.lessons[idx + 1] : undefined }; +} + +export function getRecipe(slug: string): CookbookRecipe | undefined { + return COOKBOOK_RECIPES.find((r) => r.slug === slug); +} diff --git a/website/src/lib/resources.ts b/website/src/lib/resources.ts index 86f3bb0c..d71d2020 100644 --- a/website/src/lib/resources.ts +++ b/website/src/lib/resources.ts @@ -1,4 +1,5 @@ // Resource utilities for the Awesome GitHub website +import { ITEMS, CATEGORIES, getItemsByCategory, getItemBySlug } from "./catalogue"; export const REPO_INFO = { owner: "lightspeedwp", @@ -40,92 +41,60 @@ export interface ResourceTypeInfo { label: string; icon: string; description: string; + blurb?: string; + count?: number; } -// Available resource types with metadata -// Icons are Phosphor icon names (https://github.com/phosphor-icons/web) const RESOURCE_TYPES: Record = { - agents: { - type: "agents", - label: "Agents", - icon: "robot", - description: "AI agent specifications and configurations", - }, - instructions: { - type: "instructions", - label: "Instructions", - icon: "clipboard", - description: "Organization-wide instructions and standards", - }, - skills: { - type: "skills", - label: "Skills", - icon: "lightning-bold", - description: "Self-contained reusable skills", - }, - cookbook: { - type: "cookbook", - label: "Cookbook", - icon: "chef-hat", - description: "Recipes, playbooks, and implementation guides", - }, - learn: { - type: "learn", - label: "Learning Centre", - icon: "book", - description: "Learning tracks and courses", - }, - hooks: { - type: "hooks", - label: "Hooks", - icon: "hook", - description: "Portable hooks and guardrails", - }, - workflows: { - type: "workflows", - label: "Workflows", - icon: "gear", - description: "Portable agentic workflows", - }, - prompts: { - type: "prompts", - label: "Prompts", - icon: "chat-circle", - description: "Prompt library and templates", - }, - tools: { - type: "tools", - label: "Tools", - icon: "wrench", - description: "Utility scripts and tools", - }, + agents: { type: "agents", label: "Agents", icon: "🤖", description: "AI agent specifications and configurations", blurb: "Specialised AI agents with defined behaviour, scope, and escalation rules." }, + instructions: { type: "instructions", label: "Instructions", icon: "📖", description: "Organization-wide instructions and standards", blurb: "Canonical coding, accessibility, and WordPress standards Copilot must follow." }, + prompts: { type: "prompts", label: "Prompts", icon: "💬", description: "Prompt library and templates", blurb: "Reusable prompt templates you can grab and run for common engineering tasks." }, + skills: { type: "skills", label: "Skills", icon: "✨", description: "Self-contained reusable skills", blurb: "Portable, self-contained skill packages the team can run on demand." }, + hooks: { type: "hooks", label: "Hooks", icon: "🛡️", description: "Portable hooks and guardrails", blurb: "Pre-commit and lint guardrails that enforce quality before code lands." }, + workflows: { type: "workflows", label: "Workflows", icon: "⚙️", description: "Portable agentic workflows", blurb: "Portable agentic workflow specs, each paired with a runnable GitHub Action." }, + plugins: { type: "plugins", label: "Plugins", icon: "🧩", description: "Installable plugin packs", blurb: "Installable, versioned plugin packs bundling governance and AI-ops." }, + tools: { type: "tools", label: "Tools", icon: "🔧", description: "Utility scripts and tools", blurb: "The toolchain layer — AI defaults, scripts, schemas, and editor config." }, }; -/** - * Get all available resource types - */ export function getAvailableResourceTypes(): ResourceTypeInfo[] { - return Object.values(RESOURCE_TYPES); + return Object.values(RESOURCE_TYPES).map((rt) => ({ + ...rt, + count: getItemsByCategory(rt.type).length, + })); } -/** - * Get a specific resource by type and slug - * Note: This is a stub implementation. In production, this would load from content collections. - */ -export function getResource(_type: string, _slug: string): Resource | null { - // Stub implementation - returns null for now - // In production, this would load from Astro content collections - return null; +function catalogueItemToResource(catalogueItem: { id: string; cat: string; slug: string; name: string; description: string; type: string; tags: string[]; version: string; updated: string; applyTo?: string; path?: string; tree: boolean; body?: string | null; run?: string | null; validates?: string | null; dest?: string | null; duration?: string | null; action?: string | null }): Resource { + return { + slug: catalogueItem.slug, + title: catalogueItem.name, + description: catalogueItem.description, + frontmatter: { + title: catalogueItem.name, + description: catalogueItem.description, + version: catalogueItem.version, + tags: catalogueItem.tags, + type: catalogueItem.type, + applyTo: catalogueItem.applyTo, + path: catalogueItem.path, + tree: catalogueItem.tree, + validates: catalogueItem.validates, + dest: catalogueItem.dest, + duration: catalogueItem.duration, + action: catalogueItem.action, + run: catalogueItem.run, + }, + content: catalogueItem.body || undefined, + }; } -/** - * Get all resources of a specific type - * Note: This is a stub implementation. In production, this would load from content collections. - */ -export function getResourcesByType(_type: string): Resource[] { - // Stub implementation - returns empty array for now - // In production, this would load from Astro content collections - return []; +export function getResource(type: string, slug: string): Resource | null { + const item = getItemBySlug(type, slug); + if (!item) return null; + return catalogueItemToResource(item); +} + +export function getResourcesByType(type: string): Resource[] { + return getItemsByCategory(type).map(catalogueItemToResource); } /** diff --git a/website/src/pages/awesome-github/cookbook/[slug].astro b/website/src/pages/awesome-github/cookbook/[slug].astro new file mode 100644 index 00000000..0ab5ca34 --- /dev/null +++ b/website/src/pages/awesome-github/cookbook/[slug].astro @@ -0,0 +1,255 @@ +--- +import AwesomeGithubLayout from "../../../layouts/AwesomeGithubLayout.astro"; +import AwesomeGithubButton from "../../../components/AwesomeGithub/AwesomeGithubButton.astro"; +import { COOKBOOK_RECIPES, getRecipe } from "../../../lib/learn"; + +const base = import.meta.env.BASE_URL; +const { slug } = Astro.params; + +export async function getStaticPaths() { + return COOKBOOK_RECIPES.map((r) => ({ params: { slug: r.slug } })); +} + +const recipe = getRecipe(slug!); +if (!recipe) return Astro.redirect(`${base}awesome-github/cookbook/`); + +const githubUrl = `https://github.com/lightspeedwp/.github/blob/develop/${recipe.src}`; +--- + + + + +
+
+
{recipe.kind}
+

{recipe.title}

+

{recipe.when}

+
+ + Read on GitHub ↗ + + ← All recipes +
+
+
+ +
+
+
+ +

Recipe lives on GitHub

+

+ This recipe is maintained as a real Markdown file in the control plane repository at + {recipe.src}. +

+

Click below to read it on GitHub with full Markdown rendering.

+ + Open recipe on GitHub ↗ + +
+ + +
+
+
+ + diff --git a/website/src/pages/awesome-github/cookbook/index.astro b/website/src/pages/awesome-github/cookbook/index.astro new file mode 100644 index 00000000..89ed0a46 --- /dev/null +++ b/website/src/pages/awesome-github/cookbook/index.astro @@ -0,0 +1,192 @@ +--- +import AwesomeGithubLayout from "../../../layouts/AwesomeGithubLayout.astro"; +import AwesomeGithubButton from "../../../components/AwesomeGithub/AwesomeGithubButton.astro"; +import { COOKBOOK_RECIPES } from "../../../lib/learn"; + +const base = import.meta.env.BASE_URL; + +const kindBadgeColours: Record = { + Playbook: "kind--playbook", + Example: "kind--example", + Checklist: "kind--checklist", +}; +--- + + +
+
+
Cookbook
+

Recipes for real work

+

+ Step-by-step playbooks, worked examples, and checklists for the most common engineering scenarios. + Pick a recipe, follow it, ship something. +

+
+
+ +
+
+
+ {COOKBOOK_RECIPES.map((recipe) => ( +
+
+ {recipe.kind} +
+

{recipe.title}

+

{recipe.when}

+ +
+ ))} +
+
+
+
+ + diff --git a/website/src/pages/awesome-github/getting-started.astro b/website/src/pages/awesome-github/getting-started.astro new file mode 100644 index 00000000..ee51a111 --- /dev/null +++ b/website/src/pages/awesome-github/getting-started.astro @@ -0,0 +1,399 @@ +--- +import AwesomeGithubLayout from "../../layouts/AwesomeGithubLayout.astro"; +import AwesomeGithubButton from "../../components/AwesomeGithub/AwesomeGithubButton.astro"; +import { cloneCmd } from "../../lib/catalogue"; + +const base = import.meta.env.BASE_URL; + +const steps = [ + { + number: "01", + title: "Clone the repository", + body: "Get the control plane on your machine. The develop branch has the latest assets.", + code: cloneCmd("develop"), + codeLabel: "Clone command", + }, + { + number: "02", + title: "Browse the catalogue", + body: "Every resource is catalogued by type — agents, instructions, prompts, skills, hooks, workflows, plugins, and tools. Pick what you need.", + cta: { label: "Browse catalogue", href: `${base}awesome-github/c/agents/` }, + }, + { + number: "03", + title: "Install into VS Code", + body: "Instructions and agents can be installed directly into GitHub Copilot with one click — no manual copying.", + note: "Look for the \"Install in VS Code\" button on any single-file resource.", + }, + { + number: "04", + title: "Copy raw files", + body: "Need the raw file? Every resource has a raw URL for curl or wget. Paste it straight into your repo.", + note: "Switch between main (stable) and develop (latest) using the branch toggle.", + }, + { + number: "05", + title: "Learn the system", + body: "The Learning Centre walks you through the architecture, governance model, and agent setup — four short tracks.", + cta: { label: "Go to Learning Centre", href: `${base}awesome-github/learn/` }, + }, + { + number: "06", + title: "Run the cookbook", + body: "Need a walkthrough? The cookbook has step-by-step playbooks for common engineering scenarios.", + cta: { label: "Browse recipes", href: `${base}awesome-github/cookbook/` }, + }, +]; +--- + + +
+
+
Getting Started
+

Up and running in ten minutes

+

+ The LightSpeed control plane delivers agents, instructions, prompts, and guardrails straight into your repository. Here's how to get started. +

+
+
+ +
+
+
+ {steps.map((step) => ( +
+ +
+

{step.title}

+

{step.body}

+ {step.code && ( +
+ {step.codeLabel &&
{step.codeLabel}
} +
+ {step.code} + +
+
+ )} + {step.note && ( +

{step.note}

+ )} + {step.cta && ( +
+ + {step.cta.label} + +
+ )} +
+
+ ))} +
+
+
+ +
+ +
+
+ + + + diff --git a/website/src/pages/awesome-github/glossary/[term].astro b/website/src/pages/awesome-github/glossary/[term].astro new file mode 100644 index 00000000..6fed94ed --- /dev/null +++ b/website/src/pages/awesome-github/glossary/[term].astro @@ -0,0 +1,315 @@ +--- +import AwesomeGithubLayout from "../../../layouts/AwesomeGithubLayout.astro"; +import { GLOSSARY_GROUPS, getEntry, getRelatedEntries, getAllEntries } from "../../../lib/glossary"; + +const base = import.meta.env.BASE_URL; +const { term: termSlug } = Astro.params; + +export async function getStaticPaths() { + return getAllEntries().map((e) => ({ params: { term: e.slug } })); +} + +const entry = getEntry(termSlug!); +if (!entry) return Astro.redirect(`${base}awesome-github/glossary/`); + +const related = getRelatedEntries(entry); +const group = GLOSSARY_GROUPS.find((g) => g.entries.some((e) => e.slug === entry.slug)); +--- + + + + +
+
+ {group &&
{group.label}
} +

{entry.term}

+
+
+ +
+
+
+
+
+

{entry.def}

+
+ +
+

Why it matters

+

{entry.why}

+
+ + {related.length > 0 && ( + + )} +
+ + +
+
+
+
+ + diff --git a/website/src/pages/awesome-github/glossary/index.astro b/website/src/pages/awesome-github/glossary/index.astro new file mode 100644 index 00000000..18b91d13 --- /dev/null +++ b/website/src/pages/awesome-github/glossary/index.astro @@ -0,0 +1,293 @@ +--- +import AwesomeGithubLayout from "../../../layouts/AwesomeGithubLayout.astro"; +import { GLOSSARY_GROUPS, getAllEntries } from "../../../lib/glossary"; + +const base = import.meta.env.BASE_URL; +const allEntries = getAllEntries(); +--- + + +
+
+
Glossary
+

Every term, explained

+

+ {allEntries.length} terms across {GLOSSARY_GROUPS.length} groups. Plain-language definitions with context for why each term matters in the control plane. +

+
+
+ +
+
+
+ + +
+ {GLOSSARY_GROUPS.map((group) => ( +
+
+

{group.label}

+

{group.blurb}

+
+
+ {group.entries.map((entry) => ( +
+

+ {entry.term} +

+

{entry.def}

+

Why it matters: {entry.why}

+ {entry.related.length > 0 && ( + + )} +
+ ))} +
+
+ ))} +
+
+
+
+
+ + diff --git a/website/src/pages/awesome-github/index.astro b/website/src/pages/awesome-github/index.astro index d7347ec0..7329725b 100644 --- a/website/src/pages/awesome-github/index.astro +++ b/website/src/pages/awesome-github/index.astro @@ -2,23 +2,24 @@ import AwesomeGithubLayout from "../../layouts/AwesomeGithubLayout.astro"; import AwesomeGithubButton from "../../components/AwesomeGithub/AwesomeGithubButton.astro"; import AwesomeGithubCard from "../../components/AwesomeGithub/AwesomeGithubCard.astro"; -import AwesomeGithubChip from "../../components/AwesomeGithub/AwesomeGithubChip.astro"; +import { CATEGORIES, ITEMS, getCategoryCounts } from "../../lib/catalogue"; const base = import.meta.env.BASE_URL; -const catalogues = [ - { name: "Agents", href: `${base}awesome-github/c/agents`, count: 12 }, - { name: "Instructions", href: `${base}awesome-github/c/instructions`, count: 8 }, - { name: "Prompts", href: `${base}awesome-github/c/prompts`, count: 24 }, - { name: "Skills", href: `${base}awesome-github/c/skills`, count: 15 }, - { name: "Hooks", href: `${base}awesome-github/c/hooks`, count: 6 }, - { name: "Workflows", href: `${base}awesome-github/c/workflows`, count: 11 }, - { name: "Plugins", href: `${base}awesome-github/c/plugins`, count: 4 }, - { name: "Tools", href: `${base}awesome-github/c/tools`, count: 7 }, -]; +const counts = getCategoryCounts(); +const catalogues = CATEGORIES.map((cat) => ({ + id: cat.id, + name: cat.label, + blurb: cat.blurb, + icon: cat.icon, + href: `${base}awesome-github/c/${cat.id}`, + count: counts[cat.id] || 0, +})); + +const totalItems = ITEMS.length; const stats = [ - { label: "Resources", value: "87" }, + { label: "Resources", value: String(totalItems) }, { label: "Categories", value: "8" }, { label: "Ready to use", value: "100%" }, ]; @@ -76,7 +77,8 @@ const stats = [ {catalogues.map((cat) => (

{cat.name}

-

{cat.count} resources

+

{cat.blurb}

+

{cat.count} resource{cat.count !== 1 ? 's' : ''}

))} @@ -212,10 +214,19 @@ const stats = [ margin: 0 0 var(--space-2) 0; } - .ag-small { + .ag-cat-blurb { font-size: var(--fs-body-sm); color: var(--fg-2); + margin: 0 0 var(--space-3) 0; + line-height: var(--lh-snug); + flex: 1; + } + + .ag-small { + font-size: var(--fs-body-sm); + color: var(--accent); margin: 0; + font-weight: var(--weight-semibold); } .ag-catalogue-grid { diff --git a/website/src/pages/awesome-github/learn/[track]/[lesson].astro b/website/src/pages/awesome-github/learn/[track]/[lesson].astro new file mode 100644 index 00000000..dbab65a9 --- /dev/null +++ b/website/src/pages/awesome-github/learn/[track]/[lesson].astro @@ -0,0 +1,365 @@ +--- +import AwesomeGithubLayout from "../../../../layouts/AwesomeGithubLayout.astro"; +import AwesomeGithubButton from "../../../../components/AwesomeGithub/AwesomeGithubButton.astro"; +import { LEARN_TRACKS, getTrack, getLesson, getAdjacentLessons } from "../../../../lib/learn"; + +const base = import.meta.env.BASE_URL; +const { track: trackId, lesson: lessonSlug } = Astro.params; + +export async function getStaticPaths() { + const paths: { params: { track: string; lesson: string } }[] = []; + for (const track of LEARN_TRACKS) { + for (const lesson of track.lessons) { + paths.push({ params: { track: track.id, lesson: lesson.slug } }); + } + } + return paths; +} + +const track = getTrack(trackId!); +const lesson = getLesson(trackId!, lessonSlug!); + +if (!track || !lesson) { + return Astro.redirect(`${base}awesome-github/learn/`); +} + +const { prev, next } = getAdjacentLessons(trackId!, lessonSlug!); +const lessonIndex = track.lessons.findIndex((l) => l.slug === lessonSlug) + 1; +const githubUrl = `https://github.com/lightspeedwp/.github/blob/develop/${lesson.src}`; +--- + + + + +
+
+
{track.label} · Lesson {lessonIndex} of {track.lessons.length}
+

{lesson.slug.replace(/-/g, " ")}

+

+ What you'll learn: {lesson.learn} +

+ + View source on GitHub ↗ + +
+
+ +
+
+
+
+ +

Read this lesson on GitHub

+

+ The full lesson content lives in the control plane repository at + {lesson.src}. +

+

+ Click the button below to read it directly on GitHub, where it renders with full Markdown support. +

+ + Open on GitHub ↗ + +
+ + {track.further.length > 0 && ( +
+

Further reading

+
    + {track.further.map((link) => ( +
  • + + {link.d} + + {link.p} +
  • + ))} +
+
+ )} +
+
+
+ + +
+ + diff --git a/website/src/pages/awesome-github/learn/[track]/index.astro b/website/src/pages/awesome-github/learn/[track]/index.astro new file mode 100644 index 00000000..bb746836 --- /dev/null +++ b/website/src/pages/awesome-github/learn/[track]/index.astro @@ -0,0 +1,329 @@ +--- +import AwesomeGithubLayout from "../../../../layouts/AwesomeGithubLayout.astro"; +import AwesomeGithubButton from "../../../../components/AwesomeGithub/AwesomeGithubButton.astro"; +import { LEARN_TRACKS, getTrack } from "../../../../lib/learn"; + +const base = import.meta.env.BASE_URL; +const { track: trackId } = Astro.params; + +export async function getStaticPaths() { + return LEARN_TRACKS.map((t) => ({ params: { track: t.id } })); +} + +const track = getTrack(trackId!); +if (!track) return Astro.redirect(`${base}awesome-github/learn/`); + +const trackIcons: Record = { + oriented: "🗺️", + governance: "🛡️", + quality: "✅", + agents: "🤖", +}; +--- + + + + +
+
+ +
Learning track
+

{track.label}

+

{track.blurb}

+
+ {track.lessons.length} lesson{track.lessons.length !== 1 ? "s" : ""} + + {track.further.length} further reading{track.further.length !== 1 ? "s" : ""} +
+
+
+ +
+
+

Lessons

+
    + {track.lessons.map((lesson, i) => ( +
  1. + +
    {i + 1}
    +
    + + +
  2. + ))} +
+ +
+ + Start first lesson + +
+
+
+ + {track.further.length > 0 && ( +
+
+

Further reading

+

Explore these related docs once you've completed the track.

+
+ {track.further.map((link) => ( + + {link.p} + {link.d} + + ))} +
+
+
+ )} +
+ + diff --git a/website/src/pages/awesome-github/learn/index.astro b/website/src/pages/awesome-github/learn/index.astro new file mode 100644 index 00000000..d742a0e2 --- /dev/null +++ b/website/src/pages/awesome-github/learn/index.astro @@ -0,0 +1,291 @@ +--- +import AwesomeGithubLayout from "../../../layouts/AwesomeGithubLayout.astro"; +import AwesomeGithubButton from "../../../components/AwesomeGithub/AwesomeGithubButton.astro"; +import { LEARN_TRACKS } from "../../../lib/learn"; + +const base = import.meta.env.BASE_URL; + +const trackIcons: Record = { + oriented: "🗺️", + governance: "🛡️", + quality: "✅", + agents: "🤖", +}; +--- + + +
+
+
Learning Centre
+

Learn how it works

+

+ Four short learning tracks walk you through everything that makes the LightSpeed control plane tick — from architecture to running agents in production. +

+
+ {LEARN_TRACKS.length} tracks + · + {LEARN_TRACKS.reduce((n, t) => n + t.lessons.length, 0)} lessons + · + Free +
+
+
+ +
+
+
+ {LEARN_TRACKS.map((track, idx) => ( + + ))} +
+
+
+
+ + From 43e532318f51624462e6cbd955722ca818015695 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 5 Jun 2026 09:10:22 +0000 Subject: [PATCH 2/9] =?UTF-8?q?feat(website):=20Phase=202=20=E2=80=94=20se?= =?UTF-8?q?arch=20palette,=20nav=20+=20detail=20page=20action=20buttons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Svelte SearchPalette component (Cmd/Ctrl+K, custom DOM event, keyboard nav) - Mount palette with client:only="svelte" in AwesomeGithubLayout to avoid SSR window errors - Update nav: add Learn, Cookbook, Glossary links + data-search-open on search button - Rewrite [slug].astro detail page: action buttons (Install VS Code, copy URL, copy file, View on GitHub), applyTo/run/validates/duration metadata rows, pre-formatted body block, fallback no-body section, related items grid - Add all missing CSS classes: ag-actions, ag-action-btn variants, ag-apply-to, ag-body-pre, ag-no-body, ag-gh-link, ag-path-code, ag-resource-version, ag-type-note https://claude.ai/code/session_01VaY86RbnELdWvFyBdEMwLH --- .../AwesomeGithub/AwesomeGithubNav.astro | 3 +- .../AwesomeGithub/SearchPalette.svelte | 295 +++++++++++++ website/src/layouts/AwesomeGithubLayout.astro | 21 + .../awesome-github/c/[type]/[slug].astro | 406 +++++++++++++----- 4 files changed, 613 insertions(+), 112 deletions(-) create mode 100644 website/src/components/AwesomeGithub/SearchPalette.svelte diff --git a/website/src/components/AwesomeGithub/AwesomeGithubNav.astro b/website/src/components/AwesomeGithub/AwesomeGithubNav.astro index e4b710c5..34f79115 100644 --- a/website/src/components/AwesomeGithub/AwesomeGithubNav.astro +++ b/website/src/components/AwesomeGithub/AwesomeGithubNav.astro @@ -46,8 +46,9 @@ const isActive = (linkPath: string, exact: boolean): boolean => { diff --git a/website/src/components/AwesomeGithub/SearchPalette.svelte b/website/src/components/AwesomeGithub/SearchPalette.svelte new file mode 100644 index 00000000..bc57b8ee --- /dev/null +++ b/website/src/components/AwesomeGithub/SearchPalette.svelte @@ -0,0 +1,295 @@ + + +{#if open} + + + +{/if} + + diff --git a/website/src/layouts/AwesomeGithubLayout.astro b/website/src/layouts/AwesomeGithubLayout.astro index 050aea3c..0aaec95b 100644 --- a/website/src/layouts/AwesomeGithubLayout.astro +++ b/website/src/layouts/AwesomeGithubLayout.astro @@ -3,10 +3,22 @@ import "../styles/global.css"; import "../styles/awesome-github.css"; import AwesomeGithubNav from "../components/AwesomeGithub/AwesomeGithubNav.astro"; import AwesomeGithubFooter from "../components/AwesomeGithub/AwesomeGithubFooter.astro"; +import SearchPalette from "../components/AwesomeGithub/SearchPalette.svelte"; +import { ITEMS } from "../lib/catalogue"; const base = import.meta.env.BASE_URL; const pathname = Astro.url.pathname.replace(base, "/"); +// Pass minimal search data (no large body content) +const searchItems = ITEMS.map((i) => ({ + id: i.id, + slug: i.slug, + cat: i.cat, + name: i.name, + description: i.description, + tags: i.tags, +})); + const { title = "Awesome GitHub", description = "Governance, not opinions.", @@ -45,6 +57,7 @@ const themeInitScript = ` +
@@ -67,6 +80,14 @@ const themeInitScript = ` button.setAttribute("aria-pressed", String(next === "light")); }); } + + // Wire nav search button to open search palette + const searchBtn = document.querySelector("[data-search-open]"); + if (searchBtn) { + searchBtn.addEventListener("click", () => { + document.dispatchEvent(new CustomEvent("search-palette-open")); + }); + } diff --git a/website/src/pages/awesome-github/c/[type]/[slug].astro b/website/src/pages/awesome-github/c/[type]/[slug].astro index bf137663..65011855 100644 --- a/website/src/pages/awesome-github/c/[type]/[slug].astro +++ b/website/src/pages/awesome-github/c/[type]/[slug].astro @@ -1,70 +1,39 @@ --- import AwesomeGithubLayout from "../../../../layouts/AwesomeGithubLayout.astro"; import AwesomeGithubButton from "../../../../components/AwesomeGithub/AwesomeGithubButton.astro"; -import { getResource, getResourcesByType, getAvailableResourceTypes } from "../../../../lib/resources"; +import { getItemBySlug, getItemsByCategory, getCategoryInfo, urlsFor, installable, TYPES, ITEMS } from "../../../../lib/catalogue"; const base = import.meta.env.BASE_URL; -// Get the type and slug from URL params const { type, slug } = Astro.params; -if (!type || !slug) { - throw new Error('Resource type and slug are required'); -} - -// Get the resource -const resource = getResource(type, slug); - -if (!resource) { - throw new Error(`Resource not found: ${type}/${slug}`); +export async function getStaticPaths() { + return ITEMS.map((item) => ({ params: { type: item.cat, slug: item.slug } })); } -// Get resource type info -const allTypes = getAvailableResourceTypes(); -const resourceTypeInfo = allTypes.find(t => t.type === type); +const item = getItemBySlug(type!, slug!); +if (!item) return Astro.redirect(`${base}awesome-github/`); -// Get related resources -const relatedResources = getResourcesByType(type) - .filter(r => r.slug !== slug) - .slice(0, 3); - -// Generate paths for dynamic routes -export async function getStaticPaths() { - const paths: any[] = []; - const types = getAvailableResourceTypes(); - - for (const typeInfo of types) { - const resources = getResourcesByType(typeInfo.type); - resources.forEach(resource => { - paths.push({ - params: { type: typeInfo.type, slug: resource.slug }, - }); - }); - } +const category = getCategoryInfo(type!); +const typeInfo = TYPES[item.type]; +const relatedItems = getItemsByCategory(type!).filter((i) => i.slug !== slug).slice(0, 3); - return paths; -} - -// Format date -function formatDate(dateStr: string | undefined): string { - if (!dateStr) return ''; - const date = new Date(dateStr); - return date.toLocaleDateString('en-GB', { year: 'numeric', month: 'short', day: 'numeric' }); -} +const urls = urlsFor(item, "main"); +const canInstall = installable(item); ---
@@ -73,43 +42,72 @@ function formatDate(dateStr: string | undefined): string {
- {resourceTypeInfo?.icon} {resourceTypeInfo?.label} - {resource.frontmatter.status && ( - - {resource.frontmatter.status} - - )} + {typeInfo?.badge || category?.label} + {item.version} + {item.updated}
-

{resource.title}

-

{resource.description}

+

{item.name}

+

{item.description}

+ {typeInfo &&

{typeInfo.note}

}
- @@ -117,71 +115,55 @@ function formatDate(dateStr: string | undefined): string {
- {resource.content ? ( -
+ {item.body ? ( +
{item.body}
) : ( -

No additional content available for this resource.

+
+

This resource is stored at {item.path} in the repository.

+ + View on GitHub ↗ + +
)}
- {relatedResources.length > 0 && ( + {relatedItems.length > 0 && (
-

Related {resourceTypeInfo?.label}

+

More {category?.label}

+ + diff --git a/website/src/pages/awesome-github/why.astro b/website/src/pages/awesome-github/why.astro new file mode 100644 index 00000000..2a3c8f79 --- /dev/null +++ b/website/src/pages/awesome-github/why.astro @@ -0,0 +1,256 @@ +--- +import AwesomeGithubLayout from "../../layouts/AwesomeGithubLayout.astro"; +import AwesomeGithubButton from "../../components/AwesomeGithub/AwesomeGithubButton.astro"; + +const base = import.meta.env.BASE_URL; +--- + + + + +
+
+
Governance, not opinions.
+

Why This Exists

+

+ AI coding assistants are most useful when they understand your codebase, your team's conventions, + and your quality bar — not just the language. This control plane is how we encode that context. +

+
+
+ +
+
+
+

The problem with "just wing it"

+

+ Out of the box, every AI assistant starts from scratch on every session. It doesn't know + your naming conventions, your accessibility requirements, your branching strategy, or which + patterns your team has decided to avoid. So it guesses — and the guesses are sometimes good, + often generic, and occasionally harmful. +

+

+ Multiply that across a team of engineers using Copilot, Cursor, Claude Code, or Gemini CLI, + and you get a different implicit rulebook for every developer. Code review becomes a game of + catching AI-generated patterns that don't match your standards. Onboarding stays slow because + the AI doesn't reinforce your conventions — it introduces its own. +

+ +

The fix: explicit, versioned governance

+

+ The Awesome GitHub control plane makes AI behaviour predictable by shipping structured + governance files alongside your code. Instead of hoping the model infers your standards from + examples, you write them down once in machine-readable formats and let every tool consume them. +

+

+ Instructions tell the model what standards to follow. Agents narrow the scope to a specific + role. Hooks catch violations before they land in a PR. Workflows orchestrate multi-step tasks + that would otherwise require manual coordination. Prompts give the team reusable starting points + that skip the "how do I ask for this?" overhead. +

+ +

Why not just use a linter?

+

+ Linters are mechanical — they check syntax and pattern matches. AI governance is semantic — + it shapes reasoning before code is written. A linter can't tell the model "prefer + wp_safe_redirect() over wp_redirect() and always check the return + value." An instruction can. They're complementary, not competing. +

+

+ The hooks in this catalogue bridge the two: they use the linter as a guardrail but give the + AI enough context to avoid the violation in the first place, rather than just flagging it after + the fact. +

+ +

Awesome GitHub vs. awesome lists

+

+ The "Awesome" naming is intentional but ironic. Traditional awesome lists are curated links to + third-party resources. This project is different: everything here lives in the repository, is + versioned with the codebase, and is immediately usable — not a reading list. +

+

+ The catalogue is the repository. The instructions are deployed. The agents are running. The + workflows are wired into CI. If it's in this catalogue, it's production. +

+ +

Designed for every AI tool

+

+ The assets here are deliberately tool-agnostic. Instructions follow the + .github/instructions/ convention that GitHub Copilot reads natively. + Agents are specified in a portable YAML-like format that Claude Code, Gemini CLI, and + custom runners all understand. Skills have SKILL.md entrypoints that any + model can follow. +

+

+ We maintain canonical configurations for Claude (ai/Claude.md), Gemini + (ai/Gemini.md), and GitHub Actions runners (ai/RUNNERS.md) so + you can adopt whichever tool fits the task. +

+ +

A living system

+

+ The control plane is not documentation you write once and forget. It evolves with the team. + When a new pattern emerges in code review, someone writes an instruction. When a workflow + saves three hours of manual work, it goes in the catalogue. When an agent proves its value, + it gets a version bump and a changelog entry. +

+

+ The goal is a feedback loop: better governance → better AI output → faster development → + time to improve governance. That's the flywheel. +

+
+ +
+

Ready to explore?

+

Browse the catalogue or start with the learning tracks to understand the system.

+
+ + Browse the Catalogue + + + Start Learning + +
+
+
+
+ + + From 7b2ba6e969990ff11f08e38862179f5d6e7ba2ae Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 5 Jun 2026 09:15:17 +0000 Subject: [PATCH 4/9] chore(changelog): add Awesome GitHub Astro rebuild entry to unreleased https://claude.ai/code/session_01VaY86RbnELdWvFyBdEMwLH --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3e48cac..a5c30980 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- **Awesome GitHub Site: Complete Astro Rebuild** — Rebuilt the Awesome GitHub site from a React/Babel prototype into a production-ready Astro 5 static site. Includes: a fully-typed TypeScript data layer (`catalogue.ts`, `learn.ts`, `glossary.ts`) porting 110+ catalogue items across 8 categories; Svelte `SearchPalette` component with Cmd/Ctrl+K activation; 252 statically-generated pages (catalogue, learn tracks, glossary, cookbook, getting-started, why); detail pages with Install-in-VS-Code, copy-URL, copy-file, and View-on-GitHub action buttons; mobile hamburger navigation with animated X icon and keyboard Escape support; expanded footer with brand and navigation columns; and a `why.astro` editorial page. + - **LightSpeedWP Agency Homepage: Complete Component System** — Built a production-ready homepage for the LightSpeedWP Agency website with 9 modular Astro components (Nav, HeroPlanner, TrustStrip, SolutionPaths, WhyLightSpeed, FAQ, FinalCTA, Footer, ContactOverlay). Features include sticky navigation with scroll detection, mobile drawer with theme toggle, AI project planner with form validation, responsive stats grid, 4 solution path cards with highlighting, single-open accordion FAQ with 7 questions, contact modal with success state, and comprehensive design system with light/dark mode support across 9 responsive breakpoints. All components include WCAG 2.2 AA accessibility attributes, semantic HTML5, and CSS variable theming for consistent branding. - **Awesome GitHub Navigation Redesign: Mega Menu & Accessibility Enhancements** — Redesigned header navigation with single "Browse" mega menu organizing 22 resources across 4 logical sections (Catalogues, More, Cook & Learn, Resources). Implemented comprehensive accessibility improvements including keyboard navigation (Tab+Enter/Space activation), proper ARIA attributes, semantic button elements replacing non-focusable anchors, centered menu positioning to prevent viewport clipping at 1025-1180px widths, and fixed drawer overflow for smooth scrolling. All changes comply with WCAG 2.2 AA+ contrast ratios in both light and dark modes. - **Awesome GitHub Site Phase 2a: Three-Pillar Governance Framework** — Integrated PR #809's three-pillar design approach on top of Phase 2a's dynamic foundation by adding comprehensive CSS styling for the pillar section (`.pillar-grid`, `.pillar`, `.pillar-links`). Features 3-column responsive grid layout with hover effects, accent color styling, light/dark theme variants, and mobile collapse to single column. Completes visual integration of Automation, Governance, and AI Integration framework while preserving dynamic catalogue loading and conference messaging. From 95a389010aeff0ab6a7fbe3f1d812ed7fb014122 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 5 Jun 2026 09:18:22 +0000 Subject: [PATCH 5/9] =?UTF-8?q?fix(website):=20address=20Gemini=20review?= =?UTF-8?q?=20=E2=80=94=20a11y,=20logic=20bug,=20copy=20UX?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fix(learn): guard getAdjacentLessons against idx === -1 (findIndex miss returned track.lessons[0] as next when lesson not found) - fix(search-palette): add aria-activedescendant on input and id="sp-option-{i}" on each listbox option so screen readers announce keyboard selection - fix(nav): add visibility:hidden/visible to mobile drawer so off-screen links are not tab-reachable or screen-reader-readable when closed - fix(detail): add loading ("⏳ Copying…"), error ("❌ Failed"), and disabled state to copy-file button while fetch is in progress https://claude.ai/code/session_01VaY86RbnELdWvFyBdEMwLH --- .../components/AwesomeGithub/AwesomeGithubNav.astro | 4 +++- .../components/AwesomeGithub/SearchPalette.svelte | 2 ++ website/src/lib/learn.ts | 1 + .../src/pages/awesome-github/c/[type]/[slug].astro | 12 +++++++++--- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/website/src/components/AwesomeGithub/AwesomeGithubNav.astro b/website/src/components/AwesomeGithub/AwesomeGithubNav.astro index 8ce1954c..cf747e4e 100644 --- a/website/src/components/AwesomeGithub/AwesomeGithubNav.astro +++ b/website/src/components/AwesomeGithub/AwesomeGithubNav.astro @@ -315,7 +315,8 @@ const isActive = (linkPath: string, exact: boolean): boolean => { border-top: 1px solid var(--border); padding: var(--space-4) var(--gutter); transform: translateX(-100%); - transition: transform var(--dur) var(--ease-out); + visibility: hidden; + transition: transform var(--dur) var(--ease-out), visibility var(--dur) var(--ease-out); overflow-y: auto; } @@ -325,6 +326,7 @@ const isActive = (linkPath: string, exact: boolean): boolean => { .ag-nav-menu.ag-nav-menu--open { transform: translateX(0); + visibility: visible; } .ag-nav-link { diff --git a/website/src/components/AwesomeGithub/SearchPalette.svelte b/website/src/components/AwesomeGithub/SearchPalette.svelte index bc57b8ee..43121c83 100644 --- a/website/src/components/AwesomeGithub/SearchPalette.svelte +++ b/website/src/components/AwesomeGithub/SearchPalette.svelte @@ -113,6 +113,7 @@ aria-label="Search catalogue" aria-controls="sp-results" aria-autocomplete="list" + aria-activedescendant={filtered.length > 0 ? "sp-option-" + selected : undefined} /> + {!item.tree && ( + + )} {!item.tree && (
diff --git a/website/src/components/AwesomeGithub/SearchPalette.svelte b/website/src/components/AwesomeGithub/SearchPalette.svelte index 43121c83..8ca00809 100644 --- a/website/src/components/AwesomeGithub/SearchPalette.svelte +++ b/website/src/components/AwesomeGithub/SearchPalette.svelte @@ -100,7 +100,7 @@ bind:this={dialogEl} on:click={handleBackdropClick} > -
+
= { agents: { type: "agents", label: "Agents", icon: "🤖", description: "AI agent specifications and configurations", blurb: "Specialised AI agents with defined behaviour, scope, and escalation rules." }, - instructions: { type: "instructions", label: "Instructions", icon: "📖", description: "Organization-wide instructions and standards", blurb: "Canonical coding, accessibility, and WordPress standards Copilot must follow." }, + instructions: { type: "instructions", label: "Instructions", icon: "📖", description: "Organisation-wide instructions and standards", blurb: "Canonical coding, accessibility, and WordPress standards Copilot must follow." }, prompts: { type: "prompts", label: "Prompts", icon: "💬", description: "Prompt library and templates", blurb: "Reusable prompt templates you can grab and run for common engineering tasks." }, skills: { type: "skills", label: "Skills", icon: "✨", description: "Self-contained reusable skills", blurb: "Portable, self-contained skill packages the team can run on demand." }, hooks: { type: "hooks", label: "Hooks", icon: "🛡️", description: "Portable hooks and guardrails", blurb: "Pre-commit and lint guardrails that enforce quality before code lands." }, diff --git a/website/src/pages/awesome-github/c/[type]/[slug].astro b/website/src/pages/awesome-github/c/[type]/[slug].astro index 6788b847..49d679e3 100644 --- a/website/src/pages/awesome-github/c/[type]/[slug].astro +++ b/website/src/pages/awesome-github/c/[type]/[slug].astro @@ -1,6 +1,5 @@ --- import AwesomeGithubLayout from "../../../../layouts/AwesomeGithubLayout.astro"; -import AwesomeGithubButton from "../../../../components/AwesomeGithub/AwesomeGithubButton.astro"; import { getItemBySlug, getItemsByCategory, getCategoryInfo, urlsFor, installable, TYPES, ITEMS } from "../../../../lib/catalogue"; const base = import.meta.env.BASE_URL; @@ -54,7 +53,7 @@ const canInstall = installable(item);
{canInstall && ( - + Install in VS Code )} @@ -79,11 +78,25 @@ const canInstall = installable(item); View on GitHub +
{item.applyTo && ( @@ -122,7 +135,7 @@ const canInstall = installable(item); ) : (

This resource is stored at {item.path} in the repository.

- + View on GitHub ↗
@@ -176,8 +189,6 @@ const canInstall = installable(item); + + diff --git a/website/src/pages/awesome-github/learn/[track]/index.astro b/website/src/pages/awesome-github/learn/[track]/index.astro index 6ec6a63c..fb099db9 100644 --- a/website/src/pages/awesome-github/learn/[track]/index.astro +++ b/website/src/pages/awesome-github/learn/[track]/index.astro @@ -45,6 +45,8 @@ const trackIcons: Record = { {track.lessons.length} lesson{track.lessons.length !== 1 ? "s" : ""} {track.further.length} further reading{track.further.length !== 1 ? "s" : ""} + +
@@ -54,7 +56,7 @@ const trackIcons: Record = {

Lessons

    {track.lessons.map((lesson, i) => ( -
  1. +
  2. {i + 1}
    @@ -330,9 +332,46 @@ const trackIcons: Record = { color: var(--fg-2); } + .track-progress-badge { + font-size: var(--fs-body-sm); + color: #22c55e; + font-weight: var(--weight-semibold); + } + + .track-lesson-item.track-lesson--completed .track-lesson-number { + background: rgba(34, 197, 94, 0.15); + color: #22c55e; + } + @media (max-width: 768px) { .track-hero { padding: var(--space-16) var(--gutter); margin-top: 72px; } .track-h1 { font-size: var(--fs-h3); } .track-further-grid { grid-template-columns: 1fr; } } + + diff --git a/website/src/pages/awesome-github/references.astro b/website/src/pages/awesome-github/references.astro new file mode 100644 index 00000000..8c79881a --- /dev/null +++ b/website/src/pages/awesome-github/references.astro @@ -0,0 +1,410 @@ +--- +import AwesomeGithubLayout from "../../layouts/AwesomeGithubLayout.astro"; +import AwesomeGithubButton from "../../components/AwesomeGithub/AwesomeGithubButton.astro"; + +const base = import.meta.env.BASE_URL; + +const externalSources = [ + { + name: "GitHub Docs", + url: "https://docs.github.com", + description: "Official GitHub documentation — the authoritative reference for all GitHub platform features, APIs, and workflows.", + }, + { + name: "GitHub Copilot Extensions", + url: "https://docs.github.com/en/copilot/building-copilot-extensions", + description: "Copilot agent, agent mode, and extension reference — the basis for agent specs, skill files, and instruction formatting in this control plane.", + }, + { + name: "sindresorhus/awesome", + url: "https://github.com/sindresorhus/awesome", + description: "The original awesome list standard and manifesto; the naming and curation philosophy behind Awesome GitHub.", + }, + { + name: "Conventional Commits", + url: "https://www.conventionalcommits.org/", + description: "The commit message convention used across all LightSpeed repositories and enforced by hooks in this control plane.", + }, + { + name: "WordPress Coding Standards", + url: "https://developer.wordpress.org/coding-standards/", + description: "PHP and JavaScript coding standards applied to all LightSpeed WordPress plugin and theme work, referenced in instructions.", + }, + { + name: "WCAG 2.2", + url: "https://www.w3.org/TR/WCAG22/", + description: "Web Content Accessibility Guidelines — the AA conformance level required by all LightSpeed front-end work and verified by accessibility hooks.", + }, + { + name: "OpenAI Model Spec", + url: "https://model-spec.openai.com/", + description: "Model behaviour specification format that influenced the structure of AGENTS.md and the agent instruction files.", + }, + { + name: "Astro", + url: "https://astro.build", + description: "The static site framework powering this website. Built with Astro 5 and Svelte for interactive components.", + }, +]; +--- + + + + +
    +
    +
    Attribution
    +

    References & Attribution

    +

    + The tools, specifications, and communities that shaped this control plane. + Everything listed here is either directly referenced in the assets or informed + the design of the governance system. +

    +
    +
    + +
    +
    +

    External sources

    +

    + These external resources are cited in instruction files, agent specs, or hooks + within the control plane. +

    + +
    +
    + +
    +
    +

    Acknowledgments

    +
    +

    + This control plane was designed and built by the + LightSpeed WP Agency team. + Special thanks to the open-source maintainers of every tool and specification + cited above — their work makes structured AI governance possible. +

    +

    + The Awesome GitHub site you are reading was rebuilt as a production + Astro 5 static site from an earlier prototype. + All catalogue data, learning tracks, and governance assets live in the + lightspeedwp/.github + repository on the develop branch and are available for reuse + under the terms of the GPL v3 Licence. +

    +

    + If you spot an error or would like to contribute a resource, please + open an issue. +

    +
    +
    +
    + +
    +
    +

    Licence

    +
    +
    GPL v3
    +
    +

    + The assets in this repository are open source under the + GNU General Public Licence v3. You are free to use, + copy, modify, and distribute the software, provided any derivative + works are also distributed under the same licence. +

    +

    + The software is provided "as is", without warranty of any kind. See the + full licence text for details. +

    + + Read the full GPL v3 Licence ↗ + +
    +
    +
    +
    + +
    +
    +

    Ready to explore?

    +

    Browse the full catalogue or start a learning track.

    +
    + + Browse Catalogue + + + Start Learning + +
    +
    +
    + + + From 8d5862aaed6ecffec1c8a69b9522cd9be5c66d91 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 5 Jun 2026 09:54:02 +0000 Subject: [PATCH 9/9] refactor(website): lift awesome-github pages to site root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All Awesome GitHub pages previously nested under /awesome-github/ are now at the root of the site, matching the github.lightspeedwp.agency domain structure: /awesome-github/c/agents/ → /c/agents/ /awesome-github/learn/ → /learn/ /awesome-github/references/ → /references/ /awesome-github/why/ → /why/ /awesome-github/ → / Updated all internal route references, nav/footer links, and SearchPalette navigation URLs. Fixed relative import paths for each depth level after the directory move. Removed superseded old pages (references/, getting-started/, legacy cookbook index). Build: 244 pages, 0 errors. https://claude.ai/code/session_01VaY86RbnELdWvFyBdEMwLH --- .../AwesomeGithub/AwesomeGithubFooter.astro | 32 +- .../AwesomeGithub/AwesomeGithubNav.astro | 12 +- .../AwesomeGithub/SearchPalette.svelte | 2 +- .../pages/awesome-github/cookbook/index.astro | 192 ------- website/src/pages/awesome-github/index.astro | 261 --------- .../c/[type]/[slug].astro | 14 +- .../{awesome-github => }/c/[type]/index.astro | 12 +- .../cookbook/[slug].astro | 16 +- website/src/pages/cookbook/index.astro | 313 ++++------- .../getting-started.astro | 20 +- .../implementation-roadmap/index.astro | 385 ------------- website/src/pages/getting-started/index.astro | 503 ----------------- .../why-github-matters/index.astro | 165 ------ .../glossary/[term].astro | 16 +- .../{awesome-github => }/glossary/index.astro | 8 +- website/src/pages/index.astro | 280 +++++++++- .../learn/[track]/[lesson].astro | 20 +- .../learn/[track]/index.astro | 16 +- .../{awesome-github => }/learn/index.astro | 10 +- .../{awesome-github => }/references.astro | 10 +- .../src/pages/references/evidence/index.astro | 512 ------------------ .../src/pages/references/glossary/index.astro | 280 ---------- website/src/pages/references/index.astro | 161 ------ .../src/pages/references/sources/index.astro | 351 ------------ .../src/pages/{awesome-github => }/why.astro | 10 +- 25 files changed, 457 insertions(+), 3144 deletions(-) delete mode 100644 website/src/pages/awesome-github/cookbook/index.astro delete mode 100644 website/src/pages/awesome-github/index.astro rename website/src/pages/{awesome-github => }/c/[type]/[slug].astro (97%) rename website/src/pages/{awesome-github => }/c/[type]/index.astro (95%) rename website/src/pages/{awesome-github => }/cookbook/[slug].astro (91%) rename website/src/pages/{awesome-github => }/getting-started.astro (93%) delete mode 100644 website/src/pages/getting-started/implementation-roadmap/index.astro delete mode 100644 website/src/pages/getting-started/index.astro delete mode 100644 website/src/pages/getting-started/why-github-matters/index.astro rename website/src/pages/{awesome-github => }/glossary/[term].astro (93%) rename website/src/pages/{awesome-github => }/glossary/index.astro (95%) rename website/src/pages/{awesome-github => }/learn/[track]/[lesson].astro (92%) rename website/src/pages/{awesome-github => }/learn/[track]/index.astro (94%) rename website/src/pages/{awesome-github => }/learn/index.astro (94%) rename website/src/pages/{awesome-github => }/references.astro (96%) delete mode 100644 website/src/pages/references/evidence/index.astro delete mode 100644 website/src/pages/references/glossary/index.astro delete mode 100644 website/src/pages/references/index.astro delete mode 100644 website/src/pages/references/sources/index.astro rename website/src/pages/{awesome-github => }/why.astro (95%) diff --git a/website/src/components/AwesomeGithub/AwesomeGithubFooter.astro b/website/src/components/AwesomeGithub/AwesomeGithubFooter.astro index 3027e892..dfda4197 100644 --- a/website/src/components/AwesomeGithub/AwesomeGithubFooter.astro +++ b/website/src/components/AwesomeGithub/AwesomeGithubFooter.astro @@ -5,7 +5,7 @@ const base = import.meta.env.BASE_URL;