diff --git a/CHANGELOG.md b/CHANGELOG.md index c3e48cacb..a5c309809 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. diff --git a/website/src/components/AwesomeGithub/AwesomeGithubFooter.astro b/website/src/components/AwesomeGithub/AwesomeGithubFooter.astro index 6e10de7aa..dfda41975 100644 --- a/website/src/components/AwesomeGithub/AwesomeGithubFooter.astro +++ b/website/src/components/AwesomeGithub/AwesomeGithubFooter.astro @@ -1,13 +1,74 @@ --- -// Footer component for Awesome GitHub site +const base = import.meta.env.BASE_URL; --- @@ -15,49 +76,129 @@ .ag-footer { background: var(--c-black); color: var(--c-white); - padding: var(--space-16) var(--gutter); - text-align: center; + padding: var(--space-16) var(--gutter) 0; } .ag-footer-container { max-width: var(--container-max); margin: 0 auto; + display: grid; + grid-template-columns: 1fr 2fr; + gap: var(--space-16); + padding-bottom: var(--space-16); + border-bottom: 1px solid rgba(255, 255, 255, 0.08); + } + + .ag-footer-brand { display: flex; flex-direction: column; + gap: var(--space-3); + } + + .ag-footer-logo-link { + display: inline-flex; align-items: center; - gap: var(--space-4); + gap: var(--space-2); + text-decoration: none; + color: var(--c-white); } .ag-footer-logo { - display: inline-block; - font-size: 24px; - margin-bottom: var(--space-4); - animation: gentle-glow 3s ease-in-out infinite; + font-size: 20px; + } + + .ag-footer-brand-text { + font-size: 16px; + font-weight: var(--weight-bold); + font-family: var(--font-display); + display: flex; + gap: var(--space-1); + } + + .ag-footer-brand-em { + color: var(--c-light-blue); + } + + .ag-footer-tagline { + font-size: var(--fs-body-sm); + color: var(--c-slate-400); + margin: 0; + font-style: italic; + } + + .ag-footer-nav { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--space-8); + } + + .ag-footer-col-title { + font-size: var(--fs-eyebrow); + font-weight: var(--weight-semibold); + text-transform: uppercase; + letter-spacing: var(--tracking-eyebrow); + color: var(--c-slate-300); + margin: 0 0 var(--space-4) 0; } - .ag-footer-copy { + .ag-footer-links { + list-style: none; margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: var(--space-3); + } + + .ag-footer-links a { font-size: var(--fs-body-sm); color: var(--c-slate-400); - font-weight: var(--weight-regular); + text-decoration: none; + transition: color var(--dur) var(--ease-out); } - @keyframes gentle-glow { - 0%, 100% { - opacity: 0.8; - } - 50% { - opacity: 1; + .ag-footer-links a:hover { + color: var(--c-white); + } + + .ag-footer-bottom { + max-width: var(--container-max); + margin: 0 auto; + padding: var(--space-6) 0; + } + + .ag-footer-bottom p { + font-size: var(--fs-body-sm); + color: var(--c-slate-500); + margin: 0; + } + + .ag-footer-bottom a { + color: var(--c-slate-400); + text-decoration: none; + transition: color var(--dur) var(--ease-out); + } + + .ag-footer-bottom a:hover { + color: var(--c-white); + } + + @media (max-width: 900px) { + .ag-footer-container { + grid-template-columns: 1fr; + gap: var(--space-10); } } - @media (max-width: 768px) { - .ag-footer { - padding: var(--space-10) var(--gutter); + @media (max-width: 640px) { + .ag-footer-nav { + grid-template-columns: repeat(2, 1fr); } + } - .ag-footer-copy { - font-size: var(--fs-body-sm); + @media (max-width: 480px) { + .ag-footer-nav { + grid-template-columns: 1fr; } } diff --git a/website/src/components/AwesomeGithub/AwesomeGithubNav.astro b/website/src/components/AwesomeGithub/AwesomeGithubNav.astro index 7744cbe1c..3c13e5348 100644 --- a/website/src/components/AwesomeGithub/AwesomeGithubNav.astro +++ b/website/src/components/AwesomeGithub/AwesomeGithubNav.astro @@ -7,10 +7,11 @@ interface Props { 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}`, path: "/", label: "Home", exact: true }, + { href: `${base}c/agents/`, path: "/c/", label: "Catalogue", exact: false }, + { href: `${base}learn/`, path: "/learn", label: "Learn", exact: false }, + { href: `${base}cookbook/`, path: "/cookbook", label: "Cookbook", exact: false }, + { href: `${base}glossary/`, path: "/glossary", label: "Glossary", exact: false }, ]; const isActive = (linkPath: string, exact: boolean): boolean => { @@ -21,7 +22,7 @@ const isActive = (linkPath: string, exact: boolean): boolean => { ---
- + Awesome @@ -29,7 +30,7 @@ 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 000000000..45790bb23 --- /dev/null +++ b/website/src/components/AwesomeGithub/SearchPalette.svelte @@ -0,0 +1,300 @@ + + +{#if open} + + + +{/if} + + diff --git a/website/src/layouts/AwesomeGithubLayout.astro b/website/src/layouts/AwesomeGithubLayout.astro index 050aea3cb..0aaec95b7 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/lib/catalogue.ts b/website/src/lib/catalogue.ts new file mode 100644 index 000000000..d5af89667 --- /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: "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: "docs/LABELING.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 000000000..efa7c687f --- /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 000000000..22aaed875 --- /dev/null +++ b/website/src/lib/learn.ts @@ -0,0 +1,153 @@ +/* ────────────────────────────────────────────────────────────────── + 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); + if (idx === -1) return {}; + 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 86f3bb0c5..cbdb74e53 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 { 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: "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." }, + 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/c/[type]/[slug].astro b/website/src/pages/awesome-github/c/[type]/[slug].astro deleted file mode 100644 index bf137663e..000000000 --- a/website/src/pages/awesome-github/c/[type]/[slug].astro +++ /dev/null @@ -1,546 +0,0 @@ ---- -import AwesomeGithubLayout from "../../../../layouts/AwesomeGithubLayout.astro"; -import AwesomeGithubButton from "../../../../components/AwesomeGithub/AwesomeGithubButton.astro"; -import { getResource, getResourcesByType, getAvailableResourceTypes } from "../../../../lib/resources"; - -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}`); -} - -// Get resource type info -const allTypes = getAvailableResourceTypes(); -const resourceTypeInfo = allTypes.find(t => t.type === type); - -// 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 }, - }); - }); - } - - 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' }); -} ---- - - -
-
- -
-
- -
-
-
-
- {resourceTypeInfo?.icon} {resourceTypeInfo?.label} - {resource.frontmatter.status && ( - - {resource.frontmatter.status} - - )} -
-

{resource.title}

-

{resource.description}

-
- - -
-
- -
-
-
-
- {resource.content ? ( -
- ) : ( -

No additional content available for this resource.

- )} -
-
- - -
-
- - {relatedResources.length > 0 && ( -
-
-

Related {resourceTypeInfo?.label}

- -
-
- )} - - - diff --git a/website/src/pages/awesome-github/index.astro b/website/src/pages/awesome-github/index.astro deleted file mode 100644 index d7347ec04..000000000 --- a/website/src/pages/awesome-github/index.astro +++ /dev/null @@ -1,250 +0,0 @@ ---- -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"; - -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 stats = [ - { label: "Resources", value: "87" }, - { label: "Categories", value: "8" }, - { label: "Ready to use", value: "100%" }, -]; ---- - - -
-
-
- - github.com/lightspeedwp/.github -
-

- Install AI governance, - not opinions. -

-

- Browse curated resources from the LightSpeed control plane. Copy, install, integrate—everything is production-ready. -

-
- - Start here - - - Browse catalogues - -
-
-
- -
-
-
- {stats.map((stat) => ( -
-
{stat.value}
-
{stat.label}
-
- ))} -
-
-
- -
-
-

Browse by type

-

- Everything in the control plane is organized by resource type. Pick a category to get started. -

- -
- {catalogues.map((cat) => ( - -

{cat.name}

-

{cat.count} resources

-
- ))} -
-
-
- -
-
-

Getting started

-

- New to the control plane? Follow our 10-minute onboarding to get up and running. -

- - Start onboarding - -
-
-
- - diff --git a/website/src/pages/c/[type]/[slug].astro b/website/src/pages/c/[type]/[slug].astro new file mode 100644 index 000000000..9ea33d17b --- /dev/null +++ b/website/src/pages/c/[type]/[slug].astro @@ -0,0 +1,811 @@ +--- +import AwesomeGithubLayout from "../../../layouts/AwesomeGithubLayout.astro"; +import { getItemBySlug, getItemsByCategory, getCategoryInfo, urlsFor, installable, TYPES, ITEMS } from "../../../lib/catalogue"; + +const base = import.meta.env.BASE_URL; + +const { type, slug } = Astro.params; + +export async function getStaticPaths() { + return ITEMS.map((item) => ({ params: { type: item.cat, slug: item.slug } })); +} + +const item = getItemBySlug(type!, slug!); +if (!item) return Astro.redirect(`${base}`); + +const category = getCategoryInfo(type!); +const typeInfo = TYPES[item.type]; +const relatedItems = getItemsByCategory(type!).filter((i) => i.slug !== slug).slice(0, 3); + +const urls = urlsFor(item, "main"); +const canInstall = installable(item); +--- + + +
+
+ +
+
+ +
+
+
+
+ {typeInfo?.badge || category?.label} + {item.version} + {item.updated} +
+

{item.name}

+

{item.description}

+ {typeInfo &&

{typeInfo.note}

} +
+ + +
+ {canInstall && ( + + Install in VS Code + + )} + {!item.tree && ( + + )} + {!item.tree && ( + + )} + + View on GitHub + + +
+ + {item.applyTo && ( +
+ Applies to: + {item.applyTo} +
+ )} + {item.run && ( +
+ Run: + {item.run} +
+ )} + {item.validates && ( +
+ Validates: + {item.validates} +
+ )} + {item.duration && ( +
+ Duration: + {item.duration} +
+ )} +
+
+ +
+
+
+
+ {item.body ? ( +
{item.body}
+ ) : ( +
+

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

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

More {category?.label}

+ +
+
+ )} +
+ + + + diff --git a/website/src/pages/awesome-github/c/[type]/index.astro b/website/src/pages/c/[type]/index.astro similarity index 95% rename from website/src/pages/awesome-github/c/[type]/index.astro rename to website/src/pages/c/[type]/index.astro index c698d7c41..40cbb4202 100644 --- a/website/src/pages/awesome-github/c/[type]/index.astro +++ b/website/src/pages/c/[type]/index.astro @@ -1,8 +1,8 @@ --- -import AwesomeGithubLayout from "../../../../layouts/AwesomeGithubLayout.astro"; -import AwesomeGithubButton from "../../../../components/AwesomeGithub/AwesomeGithubButton.astro"; -import AwesomeGithubCard from "../../../../components/AwesomeGithub/AwesomeGithubCard.astro"; -import { getResourcesByType, getAvailableResourceTypes } from "../../../../lib/resources"; +import AwesomeGithubLayout from "../../../layouts/AwesomeGithubLayout.astro"; +import AwesomeGithubButton from "../../../components/AwesomeGithub/AwesomeGithubButton.astro"; +import AwesomeGithubCard from "../../../components/AwesomeGithub/AwesomeGithubCard.astro"; +import { getResourcesByType, getAvailableResourceTypes } from "../../../lib/resources"; const base = import.meta.env.BASE_URL; @@ -63,7 +63,7 @@ export async function getStaticPaths() { {resources.length > 0 ? (
{resources.map((resource) => ( - +

{resource.title}

@@ -107,7 +107,7 @@ export async function getStaticPaths() { {allTypes .filter(t => t.type !== type) .map((t) => ( -
+
{t.icon}

{t.label}

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

diff --git a/website/src/pages/cookbook/[slug].astro b/website/src/pages/cookbook/[slug].astro new file mode 100644 index 000000000..7410f9021 --- /dev/null +++ b/website/src/pages/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}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/cookbook/index.astro b/website/src/pages/cookbook/index.astro index b1ab781c2..495df89ce 100644 --- a/website/src/pages/cookbook/index.astro +++ b/website/src/pages/cookbook/index.astro @@ -1,157 +1,102 @@ --- 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 recipes = [ - { - title: "Project planning & PRD playbook", - badge: "PLAYBOOK", - readTime: "2 min", - href: "https://github.com/lightspeedwp/.github/blob/develop/cookbook/project-planning-prd.md", - }, - { - title: "Spec-driven workflow example", - badge: "EXAMPLE", - readTime: "2 min", - href: "https://github.com/lightspeedwp/.github/blob/develop/cookbook/spec-driven-workflow.md", - }, - { - title: "WordPress plugin checklist", - badge: "CHECKLIST", - readTime: "3 min", - href: "https://github.com/lightspeedwp/.github/blob/develop/cookbook/wordpress-plugin-checklist.md", - }, -]; +const kindBadgeColours: Record = { + Playbook: "kind--playbook", + Example: "kind--example", + Checklist: "kind--checklist", +}; --- -
-
- -
-
- -
-
- -

Cookbook

-

- Battle-tested, step-by-step recipes for planning, spec-driven delivery, and shipping WordPress plugins. Read them straight through, copy the template, or adapt for your workflow. +

+
+
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.

-
-
-
- {recipes.map((recipe) => ( - -
- {recipe.badge} +
+
- -
-
-
-
-

More recipes incoming

-

- Browse the full recipe index on GitHub and contribute your own playbooks, templates, and step-by-step guides. -

- - Browse cookbook → - -
-
- 📚 -
-
-
-
diff --git a/website/src/pages/getting-started.astro b/website/src/pages/getting-started.astro new file mode 100644 index 000000000..d66eccfeb --- /dev/null +++ b/website/src/pages/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}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}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}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/getting-started/implementation-roadmap/index.astro b/website/src/pages/getting-started/implementation-roadmap/index.astro deleted file mode 100644 index 2ffb394f4..000000000 --- a/website/src/pages/getting-started/implementation-roadmap/index.astro +++ /dev/null @@ -1,385 +0,0 @@ ---- -import BaseLayout from "../../../layouts/BaseLayout.astro"; ---- - - -
-
Implementation
-

30/60/90 Adoption Roadmap

-

- A practical sequence for rolling out `.github` governance, agents, and automation. Start with one - outcome, roll out incrementally, validate at each stage. -

- -
- -
-

Timeline Overview

-
-
-
Days 1–30
-

Baseline Governance

-

Foundation: standards, templates, and documentation

-
-
-
Days 31–60
-

Automation & Agents

-

Workflows, first agents, labeling automation

-
-
-
Days 61–90
-

Scale & Polish

-

Multi-platform parity, full rollout, reporting

-
-
-
- -
-

Phase 1: Days 1–30

-

Baseline Governance

-
-
-

Create Canonical Governance Assets

-
    -
  • - Label taxonomy — Define one-hot labels (type, priority, status, team) that all repos - will use -
  • -
  • - Issue template catalogue — Bug, feature, documentation, AI-ops issue types -
  • -
  • - PR templates — Feature, bug, release, refactor, docs change templates -
  • -
  • - Coding standards — Language-specific style guides (JS/TS, PHP, Python) -
  • -
  • - Accessibility guidelines — WCAG 2.2 AA standards for code and documentation -
  • -
-
- -
-

Documentation & Onboarding

-
    -
  • CONTRIBUTING.md — Clear contribution guidelines
  • -
  • GOVERNANCE.md — How standards are enforced
  • -
  • Label strategy guide — Why each label exists and when to use
  • -
  • - Getting started guide — How new repos adopt standards from `.github` -
  • -
-
- -
-

Pilot Rollout

-
    -
  • Select 3–5 pilot repos across different teams
  • -
  • Apply templates, labels, and standards
  • -
  • Gather feedback and iterate
  • -
  • Document lessons and refine approach
  • -
-
- -
- Success Criteria: All pilot repos use consistent labels, templates, and standards. Teams - understand the rationale. -
-
-
- -
-

Phase 2: Days 31–60

-

Automation & Agents

-
-
-

Build Reusable Workflows

-
    -
  • - Linting workflow — Enforce code style on every PR (JavaScript, PHP, etc.) -
  • -
  • - Testing workflow — Run tests and report coverage -
  • -
  • - Release workflow — Automate versioning, changelog, and artifact publishing -
  • -
  • - Security workflow — Scan for vulnerabilities and secrets -
  • -
-
- -
-

Deploy First Agents

-
    -
  • - Release Agent — Automate semantic versioning and release management -
  • -
  • - Labelling Agent — AI-driven auto-labeling for issues and PRs -
  • -
  • - Reviewer Agent — Automated code review checks -
  • -
-
- -
-

Automation & Metrics

-
    -
  • Deploy workflows to pilot repos first
  • -
  • Validate agent behavior and accuracy
  • -
  • Set up dashboards for metrics (label coverage, release frequency, CI pass rate)
  • -
  • Create escalation paths for automation failures
  • -
-
- -
- Success Criteria: Workflows run without manual intervention. Agents label issues/PRs with - >80% accuracy. Pilot teams report reduced manual work. -
-
-
- -
-

Phase 3: Days 61–90

-

Scale & Polish

-
-
-

Multi-Platform Parity

-
    -
  • - GitHub Copilot — Custom instructions and plugin deployment -
  • -
  • - Claude Code — Agent setup and guardrails configuration -
  • -
  • - Google Gemini — Equivalent instruction setup -
  • -
  • - Validation — Test all platforms produce consistent governance behavior -
  • -
-
- -
-

Full Organization Rollout

-
    -
  • Roll out plugin packs to all repositories
  • -
  • Train teams on new workflows and agent behavior
  • -
  • Establish governance review cycles
  • -
  • Create feedback channels for improvements
  • -
-
- -
-

Governance & Reporting

-
    -
  • - Reporting cadence — Weekly/monthly metrics on governance health -
  • -
  • - Escalation paths — Who owns governance decisions and exceptions -
  • -
  • - Audit trail — Track governance changes and rationale -
  • -
  • - Continuous improvement — Review and refine based on team feedback -
  • -
-
- -
- Success Criteria: All repositories use consistent governance. Agents are trusted and - actively used. Teams report faster delivery and fewer quality issues. Multi-platform parity validated. -
-
-
- -
-

Agent Adoption Sequence

-
-

- Not all agents are adopted simultaneously. Here's a recommended sequence: -

-
    -
  1. - Labelling Agent (early) — Reduces triage overhead immediately -
  2. -
  3. - Linting Agent (early) — Catches quality issues before review -
  4. -
  5. - Release Agent (phase 2) — Automates version management -
  6. -
  7. - Reviewer Agent (phase 2) — Validates code quality -
  8. -
  9. - Meta Agent (phase 3) — Tracks governance health -
  10. -
  11. - Planner Agent (phase 3) — Coordinates roadmaps and milestones -
  12. -
  13. - Branding Agent (ongoing) — Maintains messaging consistency -
  14. -
-
-
- -
-

Common Challenges & Mitigations

-
-
    -
  • - Over-centralisation blocks local progress — Solution: Allow local overrides for - justified exceptions -
  • -
  • - Too many templates overwhelm contributors — Solution: Curate and simplify; fewer, - better templates -
  • -
  • - Standards drift without validation — Solution: Continuous validation by agents and - workflows -
  • -
  • - Automation requires human checkpoints — Solution: Clear escalation paths and human - review gates -
  • -
-
-
- -
-

Next Steps

-
- -
-
-
- - diff --git a/website/src/pages/getting-started/index.astro b/website/src/pages/getting-started/index.astro deleted file mode 100644 index aa83e5a28..000000000 --- a/website/src/pages/getting-started/index.astro +++ /dev/null @@ -1,503 +0,0 @@ ---- -import AwesomeGithubLayout from "../../layouts/AwesomeGithubLayout.astro"; - -const base = import.meta.env.BASE_URL; - -const buildingBlocks = [ - { - icon: "📝", - name: "Instructions", - description: "Canonical coding standards, accessibility, and documentation formats.", - }, - { - icon: "🤖", - name: "Agents", - description: "Specialized AI agents for code review, release, branding, and planning.", - }, - { - icon: "⚡", - name: "Skills", - description: "Portable, self-contained skill packages with SKILL.md entrypoints.", - }, - { - icon: "⚙️", - name: "Workflows", - description: "Portable agentic workflow spaces, each paired with an integration point.", - }, - { - icon: "🛠️", - name: "Hooks", - description: "Pre-commit and post-commit guardrails that enforce quality before code lands.", - }, - { - icon: "🔧", - name: "Tools", - description: "The tool-chain layer — AI utilities, scripts, schemas, and editor configs.", - }, -]; - -const adoptionSteps = [ - { - number: 1, - title: "Set the context", - description: "Enable a central repository — ours is .github — as the source of truth for governance.", - }, - { - number: 2, - title: "Pull in the right assets", - description: "Copy .github-native portable assets into your .github/. You control what to install.", - }, - { - number: 3, - title: "Land Copilot instructions", - description: "Teach your Copilot — and your team — the rules by landing instruction files.", - }, - { - number: 4, - title: "Read and iterate", - description: "Review results. Work out what lands well and what doesn't. Rinse and repeat.", - }, -]; ---- - - - -
-
-

- One .github repo - to rule them all. -

-

- A central control plane owns governance — rules, workflows, instructions, agents. Resources cascade to every repository automatically. No copy-paste drift. No version skew. -

-
-
- - -
-
-
-
-

Drift, at agency scale

-

- WordPress teams scaled repositories faster than standards. Triage drifted. Workflows weren't consistent. Release discipline got loose. Operational drag crept in. -

-

- The deeper problem: governance files lived in every repository. When a standard changed, you edited a hundred copies. When a policy shifted, you re-triage a thousand issues. Culture and coordination exhausted engineering. -

-
-
-
- "How do you sync governance across 40 repositories when your team is 6 people and you're shipping features?" -
-
-
-
-
- - -
-
-
-
-

A control plane, not a folder

-

- The breakthrough was centralising governance. One .github repository became the source of truth: issue templates, labels, workflows, instructions, agents, hooks, and reusable assets all defined once. -

-

- But a central repo is only the first step. The real magic happens when you treat it as a control plane, not a folder. Each resource type is portable. Labels are importable. Instructions auto-land. Agents run on a schedule. Hooks cascade to every repository automatically. -

-

- This eliminates the core problem: no copy-paste, no version skew, no stale governance. -

-
-
- github.com/lightspeedwp/.github -

The control plane is the single source of truth for how we code, test, release, and govern.

-
-
-
-
- - -
-
-

The building blocks

-

- The control plane is built from six layers. Each is atomic, portable, and independently useful. -

-
- {buildingBlocks.map((block) => ( -
-
{block.icon}
-

{block.name}

-

{block.description}

-
- ))} -
-
-

- The six layers form a coherent whole: instructions teach standards, agents enforce them, hooks guard them, skills extend them, workflows automate them, tools implement them. Together, they comprise the control plane. -

-
-
-
- - -
-
-
-
-

From governance to a plugin you install

-

- Governance alone is not enough. As AI tooling expanded — Copilot, Claude, GitHub Actions, local hooks — we realised that a central repo was the source, but not the execution plane. -

-

- We pivoted to an installable model. The .github repo remains the source of truth. But now, portable plugin packs carry capabilities to Copilot, to Claude Code, to local git hooks, and to CI/CD pipelines. -

-

- This means: one source, many execution contexts. Standards, everywhere. -

-
-
-

Install the control plane as a Copilot plugin. As a Claude skill pack. As a git hook. As a reusable workflow.

-
-
-
-
- - -
-
-

Adopt it in four steps

-
- {adoptionSteps.map((step) => ( -
-
{step.number}
-

{step.title}

-

{step.description}

-
- ))} -
-
-
- - -
-
-

The horizon

-

- The control plane is designed to evolve. As standards clarify and tooling matures, we update the source once. Every repository, every tool, every context receives the update automatically. -

-
-

- The goal is not to build a monolithic system, but to establish a governance layer that is: -

-
    -
  • Inherited: Standards cascade automatically to every repository.
  • -
  • Portable: Capabilities work across any tool — GitHub, Copilot, Claude, local hooks.
  • -
  • Versioned: Changes are explicit, tested, and controlled. Teams opt in to new standards.
  • -
  • Human-centred: Automation amplifies human judgment; it never replaces it.
  • -
-
-
-
-
- - diff --git a/website/src/pages/getting-started/why-github-matters/index.astro b/website/src/pages/getting-started/why-github-matters/index.astro deleted file mode 100644 index 52084916a..000000000 --- a/website/src/pages/getting-started/why-github-matters/index.astro +++ /dev/null @@ -1,165 +0,0 @@ ---- -import BaseLayout from "../../../layouts/BaseLayout.astro"; ---- - - -
-
Getting Started
-

Why .github Matters

-

- Teams ship code faster than standards spread. Without a central place to define governance, automation drifts, standards break, and delivery gets slower. A `.github` control plane changes that. -

- -
- -
-

The Problem

-
-

- WordPress agencies and product teams scale repositories faster than standards. Each team adopts - different practices: -

-
    -
  • Inconsistent labels — No shared taxonomy, can't aggregate metrics across repos
  • -
  • Different templates — Issue and PR processes vary, onboarding is harder
  • -
  • Fragmented workflows — CI/CD patterns differ, no shared quality gates
  • -
  • Repeated manual work — Teams reinvent release processes, linting configs, and documentation standards
  • -
  • Delivery drift — What you document becomes obsolete in months; repos diverge
  • -
-

- The result: delivery friction, quality risk, and slower scaling. -

-
-
- -
-

The Insight: One Source of Truth

-
-

- The solution isn't more process—it's reliable flow through centralised standards. -

-

- By putting shared governance, automation, and instructions in one `.github` repository, you: -

-
    -
  • Define once, reuse everywhere — Labels, templates, workflows, instructions live in one place
  • -
  • Reduce cognitive load — New repos inherit governance automatically
  • -
  • Validate continuously — Governance doesn't drift; it's enforced by automation
  • -
  • Accelerate onboarding — New teams understand standards immediately
  • -
  • Enable experimentation — Teams can innovate locally without breaking shared patterns
  • -
-
-
- -
-

What Goes in .github?

-
-

- A `.github` control plane includes: -

-
    -
  • Labels taxonomy — Canonical labels used across all repos
  • -
  • Issue & PR templates — Structured intake and change processes
  • -
  • Reusable workflows — CI/CD automation (linting, testing, release)
  • -
  • Instructions — Coding standards, accessibility guidelines, contribution rules
  • -
  • Agent definitions — Roles and guardrails for AI-assisted operations
  • -
  • Metrics & governance — Observability and compliance tracking
  • -
-
-
- -
-

The 30/60/90 Roadmap

-
-

- Implementing `.github` governance doesn't happen overnight. Here's a practical sequence: -

- -

Days 1–30: Baseline Governance

-
    -
  • Define your label taxonomy (one-hot enforcement)
  • -
  • Create issue and PR templates
  • -
  • Document coding standards and contribution guidelines
  • -
  • Roll out to pilot repos; gather feedback
  • -
- -

Days 31–60: Automation & Agents

-
    -
  • Build reusable workflows (linting, testing, release)
  • -
  • Deploy the first agent (Release Agent for version management)
  • -
  • Automate labeling and triage
  • -
  • Validate governance with metrics
  • -
- -

Days 61–90: Multi-Platform & Scale

-
    -
  • Deploy plugin packs to all repositories
  • -
  • Ensure multi-platform parity (Copilot, Claude Code, Gemini)
  • -
  • Establish reporting cadence and escalation paths
  • -
  • Refine based on team feedback
  • -
-
-
- -
-

Why This Matters Now

-
-

- AI-assisted development amplifies both consistency and drift. If governance is weak, AI makes the - problem worse—it accelerates inconsistency. But with strong governance: -

-
    -
  • - AI becomes a force multiplier — Agents enforce standards faster and at scale -
  • -
  • - Risk is reduced — Quality gates and guardrails are explicit and auditable -
  • -
  • - Teams ship with confidence — They know standards are enforced, not hoped for -
  • -
-
-
- -
-

Next Steps

-
- -
-
-
- - diff --git a/website/src/pages/glossary/[term].astro b/website/src/pages/glossary/[term].astro new file mode 100644 index 000000000..c5da98165 --- /dev/null +++ b/website/src/pages/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}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/glossary/index.astro b/website/src/pages/glossary/index.astro new file mode 100644 index 000000000..3a16b09d3 --- /dev/null +++ b/website/src/pages/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/index.astro b/website/src/pages/index.astro index 457f4db75..0f28c3373 100644 --- a/website/src/pages/index.astro +++ b/website/src/pages/index.astro @@ -1,27 +1,261 @@ --- -import HomepageLayout from "../layouts/HomepageLayout.astro"; -import Nav from "../components/Homepage/Nav.astro"; -import HeroPlanner from "../components/Homepage/HeroPlanner.astro"; -import TrustStrip from "../components/Homepage/TrustStrip.astro"; -import SolutionPaths from "../components/Homepage/SolutionPaths.astro"; -import WhyLightSpeed from "../components/Homepage/WhyLightSpeed.astro"; -import FAQ from "../components/Homepage/FAQ.astro"; -import FinalCTA from "../components/Homepage/FinalCTA.astro"; -import Footer from "../components/Homepage/Footer.astro"; -import ContactOverlay from "../components/Homepage/ContactOverlay.astro"; +import AwesomeGithubLayout from "../layouts/AwesomeGithubLayout.astro"; +import AwesomeGithubButton from "../components/AwesomeGithub/AwesomeGithubButton.astro"; +import AwesomeGithubCard from "../components/AwesomeGithub/AwesomeGithubCard.astro"; +import { CATEGORIES, ITEMS, getCategoryCounts } from "../lib/catalogue"; + +const base = import.meta.env.BASE_URL; + +const counts = getCategoryCounts(); +const catalogues = CATEGORIES.map((cat) => ({ + id: cat.id, + name: cat.label, + blurb: cat.blurb, + icon: cat.icon, + href: `${base}c/${cat.id}`, + count: counts[cat.id] || 0, +})); + +const totalItems = ITEMS.length; + +const stats = [ + { label: "Resources", value: String(totalItems) }, + { label: "Categories", value: "8" }, + { label: "Ready to use", value: "100%" }, +]; --- - -