📦 deps(thirdparty): update snapshots

This commit is contained in:
ci[bot]
2026-07-29 07:59:17 +00:00
parent 60364c6660
commit 0c634043e3
427 changed files with 26138 additions and 2336 deletions
@@ -10,23 +10,23 @@
<meta name="apple-mobile-web-app-title" content="agentic-awesome-skills" />
<link rel="manifest" href="%BASE_URL%site.webmanifest" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Use AAS Core preview for neutral catalog retrieval, exact agent-owned selection, validation, and planning for Codex, Claude Code, and compatible clients, backed by 1,987+ cataloged skills." />
<meta name="description" content="Use AAS Core preview for neutral catalog retrieval, exact agent-owned selection, validation, and planning for Codex, Claude Code, and compatible clients, backed by 1,993+ cataloged skills." />
<meta name="author" content="Agentic Awesome Skills" />
<meta name="msvalidate.01" content="CAC904EB0D2DD1B22B5F2BC540CAD654" />
<meta property="og:title" content="AAS Core Preview | Agent-first stacks backed by 1,987+ skills" />
<meta property="og:description" content="Use AAS Core preview for neutral catalog retrieval, exact agent-owned selection, validation, and planning for Codex, Claude Code, and compatible clients, backed by 1,987+ cataloged skills." />
<meta property="og:title" content="AAS Core Preview | Agent-first stacks backed by 1,993+ skills" />
<meta property="og:description" content="Use AAS Core preview for neutral catalog retrieval, exact agent-owned selection, validation, and planning for Codex, Claude Code, and compatible clients, backed by 1,993+ cataloged skills." />
<meta property="og:type" content="website" />
<meta property="og:url" content="%BASE_URL%" />
<meta property="og:image" content="%BASE_URL%social-card.png" />
<meta name="twitter:title" content="AAS Core Preview | Agent-first stacks backed by 1,987+ skills" />
<meta name="twitter:description" content="Use AAS Core preview for neutral catalog retrieval, exact agent-owned selection, validation, and planning for Codex, Claude Code, and compatible clients, backed by 1,987+ cataloged skills." />
<meta name="twitter:title" content="AAS Core Preview | Agent-first stacks backed by 1,993+ skills" />
<meta name="twitter:description" content="Use AAS Core preview for neutral catalog retrieval, exact agent-owned selection, validation, and planning for Codex, Claude Code, and compatible clients, backed by 1,993+ cataloged skills." />
<meta name="twitter:image" content="%BASE_URL%social-card.png" />
<meta name="twitter:image:alt" content="Agentic Awesome Skills catalog preview" />
<meta name="robots" content="index, follow" />
<meta property="og:site_name" content="Agentic Awesome Skills" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="theme-color" content="#0f172a" />
<title>AAS Core Preview | Agent-first stacks backed by 1,987+ skills</title>
<title>AAS Core Preview | Agent-first stacks backed by 1,993+ skills</title>
</head>
<body>
<div id="root"></div>
File diff suppressed because it is too large Load Diff
@@ -19,20 +19,20 @@
"@fontsource/jetbrains-mono": "^5.2.8",
"@fontsource/outfit": "^5.2.8",
"@phosphor-icons/react": "^2.1.10",
"@supabase/supabase-js": "^2.110.0",
"@supabase/supabase-js": "^2.111.0",
"github-markdown-css": "^5.9.0",
"highlight.js": "^11.11.1",
"react": "^19.2.7",
"react-dom": "^19.2.7",
"react-markdown": "^10.1.0",
"react-router-dom": "^7.17.0",
"react-router": "^8.3.0",
"react-virtuoso": "^4.18.7",
"rehype-highlight": "^7.0.2",
"remark-gfm": "^4.0.1",
"sanitize-filename": "^1.6.4"
},
"devDependencies": {
"@eslint/js": "^9.39.1",
"@eslint/js": "^10.0.1",
"@tailwindcss/postcss": "^4.2.0",
"@testing-library/jest-dom": "^6.4.0",
"@testing-library/react": "^16.0.0",
@@ -42,16 +42,16 @@
"@vitejs/plugin-react": "^6.0.2",
"@vitest/coverage-v8": "^4.1.8",
"autoprefixer": "^10.4.24",
"eslint": "^9.39.1",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.4.24",
"eslint": "^10.8.0",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.3",
"express-rate-limit": "^8.5.2",
"globals": "^16.5.0",
"jsdom": "^24.0.0",
"postcss": "^8.5.6",
"postcss": "8.5.18",
"tailwindcss": "^4.2.0",
"typescript": "^5.4.0",
"typescript-eslint": "^8.46.1",
"typescript-eslint": "^8.65.0",
"vite": "^8.0.16",
"vitest": "^4.1.8"
},
@@ -1,12 +1,12 @@
# Agentic Awesome Skills
> AAS Core is a local, agent-first control plane for complete catalog discovery, agent-owned skill selection, stack validation, and planning, backed by 1,987+ agentic SKILL.md playbooks.
> AAS Core is a local, agent-first control plane for complete catalog discovery, agent-owned skill selection, stack validation, and planning, backed by 1,993+ agentic SKILL.md playbooks.
## Key Facts
- Current release: V15.3.0.
- Release boundary: V15.3.0 includes AAS Core under the Agent-First Preview; pin this exact version when configuring the local MCP.
- Skill count: 1,987+.
- Current release: V15.6.0.
- Release boundary: V15.6.0 includes AAS Core under the Agent-First Preview; pin this exact version when configuring the local MCP.
- Skill count: 1,993+.
- Primary product: AAS Core preview, exposed through the `aas` CLI and local `aas-mcp` stdio server.
- Agent tools: `search_skills`, `get_skill`, `compose_stack`, `inspect_stack`, `diff_stack`, `export_selection_evidence`, and `inspect_selection_evidence`.
- Lifecycle: the client enumerates primary project capabilities, searches and compares candidates for each, covers every capability or reports a catalog gap, and chooses exact IDs. Core has no semantic policy favoring a small stack; each manifest has a technical maximum of 128 skills. Read-only `compose_stack` returns the manifest in memory, while a client or CLI persists `aas-stack.json` and optional `aas-selection-evidence.json` in an `artifact-dir` before CLI validation and immutable plan preview.
@@ -17,7 +17,7 @@
- Evidence privacy: the sidecar records raw `search_skills` queries, so catalog queries must not contain secrets or private source text.
- Preview boundary: planning may write an explicitly requested plan artifact but does not write target state; apply and recovery are not part of the supported preview path.
- Supported real clients include Codex CLI and Claude Code; the catalog also serves Cursor, Gemini CLI, Antigravity, and other compatible hosts.
- The 1,987+ skill catalog, specialized plugins, bundles, and workflows are supporting discovery and distribution surfaces.
- The 1,993+ skill catalog, specialized plugins, bundles, and workflows are supporting discovery and distribution surfaces.
- Repository: https://github.com/sickn33/agentic-awesome-skills
- Hosted catalog and companion review surface: https://sickn33.github.io/agentic-awesome-skills/
- Specialized plugin landing page: https://sickn33.github.io/agentic-awesome-skills/plugins
File diff suppressed because it is too large Load Diff
@@ -8340,6 +8340,41 @@
"reasons": []
}
},
{
"id": "brendangregg-use-tsa",
"path": "skills/brendangregg-use-tsa",
"category": "devops",
"name": "brendangregg-use-tsa",
"description": "Methodical performance troubleshooting and root-cause analysis with Brendan Gregg's USE and TSA methods, plus evidence-backed RCA and postmortem reports.",
"risk": "safe",
"source": "community",
"date_added": "2026-07-28",
"plugin": {
"targets": {
"codex": "supported",
"claude": "supported"
},
"setup": {
"type": "none",
"summary": "",
"docs": null
},
"reasons": []
},
"source_type": "community",
"source_repo": "thecsdoctor/brendangregg-use-tsa-skill",
"license": "MIT",
"license_source": "https://github.com/thecsdoctor/brendangregg-use-tsa-skill/blob/main/LICENSE",
"tags": [
"performance",
"troubleshooting",
"root-cause-analysis",
"linux",
"observability",
"sre",
"postmortem"
]
},
{
"id": "brevo-automation",
"path": "skills/brevo-automation",
@@ -8573,6 +8608,39 @@
"license": "MIT",
"license_source": "https://github.com/hyhmrright/brooks-lint/blob/main/LICENSE"
},
{
"id": "browser-act",
"path": "skills/browser-act",
"category": "browser-automation",
"name": "browser-act",
"description": "Use BrowserAct for authenticated browser automation, JS-rendered extraction, screenshots, parallel sessions, verification handling, and human handoff.",
"risk": "critical",
"source": "https://github.com/browser-act/skills/tree/main/browser-act",
"date_added": "2026-07-28",
"plugin": {
"targets": {
"codex": "supported",
"claude": "supported"
},
"setup": {
"type": "none",
"summary": "",
"docs": null
},
"reasons": []
},
"source_type": "official",
"source_repo": "browser-act/skills",
"license": "MIT",
"license_source": "https://github.com/browser-act/skills/blob/main/LICENSE",
"tags": [
"browser-automation",
"web-extraction",
"ai-agents",
"cli",
"multi-session"
]
},
{
"id": "browser-automation",
"path": "skills/browser-automation",
@@ -18202,6 +18270,38 @@
"session-handoff"
]
},
{
"id": "fedora-hyprland-installer",
"path": "skills/fedora-hyprland-installer",
"category": "devops",
"name": "fedora-hyprland-installer",
"description": "Install, configure, verify, repair, update, and uninstall Hyprland on Fedora Linux with GPU-aware detection (NVIDIA/AMD/Intel).",
"risk": "critical",
"source": "community",
"date_added": "2026-07-26",
"plugin": {
"targets": {
"codex": "supported",
"claude": "supported"
},
"setup": {
"type": "none",
"summary": "",
"docs": null
},
"reasons": []
},
"source_type": "community",
"source_repo": "maleksaadi0109/hyprfedora",
"license": "MIT",
"license_source": "https://github.com/maleksaadi0109/hyprfedora/blob/3ec6d4fc5eecdb188613dd841dce9926ae5c8319/LICENSE",
"tags": [
"fedora",
"hyprland",
"wayland",
"linux"
]
},
{
"id": "ffuf-claude-skill",
"path": "skills/ffuf-claude-skill",
@@ -18378,6 +18478,39 @@
"reasons": []
}
},
{
"id": "find-complementary-founders",
"path": "skills/find-complementary-founders",
"category": "business-strategy",
"name": "find-complementary-founders",
"description": "Use when an owner asks to find a cofounder or project partner. Assess only that agent's own owner and rank only approved profiles other agents posted for their own owners.",
"risk": "critical",
"source": "community",
"date_added": "2026-07-26",
"plugin": {
"targets": {
"codex": "supported",
"claude": "supported"
},
"setup": {
"type": "none",
"summary": "",
"docs": null
},
"reasons": []
},
"source_type": "community",
"source_repo": "merc1305/findMate",
"license": "MIT",
"license_source": "https://github.com/merc1305/findMate/blob/main/LICENSE",
"tags": [
"cofounder",
"founder-matching",
"collaboration",
"privacy",
"agent-skills"
]
},
{
"id": "finishing-a-development-branch",
"path": "skills/finishing-a-development-branch",
@@ -29046,9 +29179,9 @@
"reasons": []
},
"source_type": "official",
"source_repo": "Modellix/modellix-skill",
"source_repo": "Modellix/modellix-plugin",
"license": "MIT",
"license_source": "https://github.com/Modellix/modellix-skill/blob/main/LICENSE",
"license_source": "https://github.com/Modellix/modellix-plugin/blob/main/LICENSE",
"tags": [
"image-generation",
"video-generation",
@@ -32142,6 +32275,39 @@
"reasons": []
}
},
{
"id": "orchestrate",
"path": "skills/orchestrate",
"category": "agent-orchestration",
"name": "orchestrate",
"description": "Coordinate focused subagents on substantial work, keep their ownership non-overlapping, and integrate verified results. Use for large-scope Codex tasks; keep trivial work with the coordinator.",
"risk": "safe",
"source": "https://github.com/provencher/codex-skills/tree/8aa6c42b73781c905c55f8a1253a18127079ac21/orchestrate",
"date_added": "2026-07-26",
"plugin": {
"targets": {
"codex": "supported",
"claude": "supported"
},
"setup": {
"type": "none",
"summary": "",
"docs": null
},
"reasons": []
},
"source_type": "community",
"source_repo": "provencher/codex-skills",
"license": "MIT",
"license_source": "https://github.com/provencher/codex-skills/blob/8aa6c42b73781c905c55f8a1253a18127079ac21/LICENSE",
"tags": [
"codex",
"orchestration",
"multi-agent",
"delegation",
"subagents"
]
},
{
"id": "orchestrate-batch-refactor",
"path": "skills/orchestrate-batch-refactor",
@@ -38795,6 +38961,39 @@
"reasons": []
}
},
{
"id": "seo-drift",
"path": "skills/seo-drift",
"category": "marketing",
"name": "seo-drift",
"description": "Snapshot a site's SEO state and detect ranking, indexation, metadata, canonical, robots, schema, and on-page regressions over time.",
"risk": "safe",
"source": "https://github.com/nowork-studio/NotFair/tree/main/seo/seo-drift",
"date_added": "2026-07-22",
"plugin": {
"targets": {
"codex": "supported",
"claude": "supported"
},
"setup": {
"type": "none",
"summary": "",
"docs": null
},
"reasons": []
},
"source_type": "official",
"source_repo": "nowork-studio/NotFair",
"license": "MIT",
"license_source": "https://github.com/nowork-studio/NotFair/blob/main/LICENSE",
"tags": [
"seo",
"monitoring",
"search-console",
"technical-seo",
"regression-testing"
]
},
{
"id": "seo-forensic-incident-response",
"path": "skills/seo-forensic-incident-response",
@@ -44737,7 +44936,7 @@
"path": "skills/uizze-ui-research",
"category": "design",
"name": "uizze-ui-research",
"description": "Use when building or reviewing web and iOS product UI and you need real UI references, structured design contracts, or implementation validation through UIZZE MCP.",
"description": "Use when building or reviewing web and iOS UI and you need real references from the free UIZZE public catalog, a structured design contract, a consent-gated rendered HTML/CSS preview, or a hard pre-ship finish gate.",
"risk": "safe",
"source": "https://github.com/aislon/uizze-mcp/tree/main/skills/uizze-ui-research",
"date_added": "2026-07-12",
@@ -44755,6 +44954,8 @@
},
"source_type": "official",
"source_repo": "aislon/uizze-mcp",
"license": "MIT",
"license_source": "https://github.com/aislon/uizze-mcp/blob/main/LICENSE",
"tags": [
"ui-design",
"ui-research",
@@ -1,6 +1,7 @@
import { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Link, NavLink, Route, Routes } from 'react-router-dom';
import { BrowserRouter as Router, Link, NavLink, Route, Routes } from 'react-router';
import { Icon } from './components/ui/Icon';
import { toIndexableRoutePath } from './utils/seo';
const Home = lazy(() => import('./pages/Home'));
const SkillDetail = lazy(() => import('./pages/SkillDetail'));
@@ -38,13 +39,13 @@ function App(): React.ReactElement {
Core
</NavLink>
<NavLink
to="/workbench"
to={toIndexableRoutePath('/workbench')}
className={({ isActive }) => `app-nav__link ${isActive ? 'is-active' : ''}`}
>
Workbench
</NavLink>
<NavLink
to="/plugins"
to={toIndexableRoutePath('/plugins')}
className={({ isActive }) => `app-nav__link ${isActive ? 'is-active' : ''}`}
>
Plugins
@@ -66,8 +67,8 @@ function App(): React.ReactElement {
<summary aria-label="Open navigation">Menu</summary>
<nav aria-label="Mobile navigation">
<Link to="/">Core</Link>
<Link to="/workbench">Workbench</Link>
<Link to="/plugins">Plugins</Link>
<Link to={toIndexableRoutePath('/workbench')}>Workbench</Link>
<Link to={toIndexableRoutePath('/plugins')}>Plugins</Link>
<a href="https://github.com/sickn33/agentic-awesome-skills" target="_blank" rel="noreferrer">View on GitHub</a>
</nav>
</details>
@@ -22,6 +22,9 @@ describe('Workbench route isolation', () => {
render(<App />);
await screen.findByRole('heading', { level: 1, name: 'Review what your agent selected.' });
screen.getAllByRole('link', { name: 'Plugins' }).forEach((link) => {
expect(link).toHaveAttribute('href', '/plugins/');
});
const stack = {
schemaVersion: 2,
name: 'isolated-stack',
@@ -1,5 +1,5 @@
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { MemoryRouter } from 'react-router';
import { expect, it, vi } from 'vitest';
import { createMockSkill } from '../factories/skill';
@@ -1,8 +1,9 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { Link } from 'react-router';
import { SkillStarButton } from './SkillStarButton';
import { Icon } from './ui/Icon';
import type { Skill } from '../types';
import { toIndexableRoutePath } from '../utils/seo';
interface SkillCardProps {
skill: Skill;
@@ -13,7 +14,7 @@ export const SkillCard = React.memo(({ skill, starCount }: SkillCardProps) => {
return (
<article className="skill-row group">
<Link
to={`/skill/${skill.id}`}
to={toIndexableRoutePath(`/skill/${skill.id}`)}
className="skill-row__link"
aria-label={`Read skill ${skill.name}`}
>
@@ -1,4 +1,4 @@
import { Outlet } from 'react-router-dom';
import { Outlet } from 'react-router';
import { SkillProvider } from './SkillContext';
export function CatalogRouteProvider(): React.ReactElement {
@@ -1,5 +1,5 @@
import { useEffect, useMemo, useState } from 'react';
import { Link } from 'react-router-dom';
import { Link } from 'react-router';
import { VirtuosoGrid } from 'react-virtuoso';
import { SkillCard } from '../components/SkillCard';
import { Icon } from '../components/ui/Icon';
@@ -7,7 +7,7 @@ import { useSkills } from '../context/SkillContext';
import { seoLandingPages } from '../data/seoLandingPages';
import { usePageMeta } from '../hooks/usePageMeta';
import type { CategoryStats, SyncMessage } from '../types';
import { buildHomeMeta, getHomeFaqItems } from '../utils/seo';
import { buildHomeMeta, getHomeFaqItems, toIndexableRoutePath } from '../utils/seo';
const conceptCards = [
{ title: 'AAS Core preview', body: 'The local boundary that validates an agent-selected skill stack and immutable plan preview.' },
@@ -120,7 +120,7 @@ export function Home(): React.ReactElement {
</button>
))}
</nav>
<Link to="/workbench" className="catalog-rail__workbench">
<Link to={toIndexableRoutePath('/workbench')} className="catalog-rail__workbench">
<Icon name="fileCode" size={17} />
AAS Core Workbench
</Link>
@@ -180,7 +180,7 @@ export function Home(): React.ReactElement {
</select>
</label>
</div>
<Link to="/workbench">Review an AAS Core stack <Icon name="arrowRight" size={16} /></Link>
<Link to={toIndexableRoutePath('/workbench')}>Review an AAS Core stack <Icon name="arrowRight" size={16} /></Link>
</div>
</section>
@@ -251,7 +251,7 @@ export function Home(): React.ReactElement {
</div>
<div>
<h2>Search topics</h2>
<nav>{seoLandingPages.map((page) => <Link key={page.slug} to={`/topics/${page.slug}`}>{page.h1}<Icon name="arrowRight" size={14} /></Link>)}</nav>
<nav>{seoLandingPages.map((page) => <Link key={page.slug} to={toIndexableRoutePath(`/topics/${page.slug}`)}>{page.h1}<Icon name="arrowRight" size={14} /></Link>)}</nav>
</div>
</div>
<div className="catalog-faq">
@@ -1,5 +1,5 @@
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { MemoryRouter } from 'react-router';
import { expect, it } from 'vitest';
import NotFound from './NotFound';
@@ -1,4 +1,4 @@
import { Link, useLocation } from 'react-router-dom';
import { Link, useLocation } from 'react-router';
import { usePageMeta } from '../hooks/usePageMeta';
export default function NotFound(): React.ReactElement {
@@ -1,9 +1,9 @@
import { useMemo, useState } from 'react';
import { Link } from 'react-router-dom';
import { Link } from 'react-router';
import { Icon } from '../components/ui/Icon';
import { specializedPlugins, type SpecializedPlugin } from '../data/specializedPlugins';
import { usePageMeta } from '../hooks/usePageMeta';
import { buildPluginsMeta } from '../utils/seo';
import { buildPluginsMeta, toIndexableRoutePath } from '../utils/seo';
const repoBaseUrl = 'https://github.com/sickn33/agentic-awesome-skills';
const pluginFolderUrl = (pluginId: string) => `${repoBaseUrl}/tree/main/plugins/agentic-bundle-${pluginId}`;
@@ -92,7 +92,7 @@ function PluginRow({ plugin }: { plugin: SpecializedPlugin }): React.ReactElemen
<p role="cell">{plugin.audience}</p>
<p role="cell">{plugin.why}</p>
<div role="cell" className="plugin-row__skills">
{plugin.skills.slice(0, 4).map((skillId) => <Link key={skillId} to={`/skill/${encodeURIComponent(skillId)}`}>@{skillId}</Link>)}
{plugin.skills.slice(0, 4).map((skillId) => <Link key={skillId} to={toIndexableRoutePath(`/skill/${encodeURIComponent(skillId)}`)}>@{skillId}</Link>)}
{plugin.skills.length > 4 && <span>+{plugin.skills.length - 4} more</span>}
</div>
<div role="cell" className="plugin-row__actions">
@@ -1,10 +1,10 @@
import { useState, useEffect, useMemo, lazy, Suspense } from 'react';
import { useParams, Link } from 'react-router-dom';
import { useParams, Link } from 'react-router';
import { SkillStarButton } from '../components/SkillStarButton';
import { Icon } from '../components/ui/Icon';
import { useSkills } from '../context/SkillContext';
import { usePageMeta } from '../hooks/usePageMeta';
import { buildSkillFallbackMeta, buildSkillMeta, selectTopSkills } from '../utils/seo';
import { buildSkillFallbackMeta, buildSkillMeta, selectTopSkills, toIndexableRoutePath } from '../utils/seo';
import { getSkillMarkdownCandidateUrls } from '../utils/publicAssetUrls';
import { getRelatedSeoLandingPagesForSkill } from '../data/seoLandingPages';
import remarkGfm from 'remark-gfm';
@@ -336,7 +336,7 @@ export function SkillDetail(): React.ReactElement {
{skill.id}
</code>
<Link
to="/workbench"
to={toIndexableRoutePath('/workbench')}
className="inline-flex items-center border border-teal-700 px-3 py-2 text-sm font-semibold text-teal-800 transition-colors hover:bg-teal-50 dark:border-teal-400 dark:text-teal-200 dark:hover:bg-teal-950/40"
>
Review Core artifacts
@@ -376,7 +376,7 @@ export function SkillDetail(): React.ReactElement {
</p>
</div>
<Link
to="/topics/github-ai-skills-repository"
to={toIndexableRoutePath('/topics/github-ai-skills-repository')}
className="inline-flex items-center justify-center rounded-lg border border-slate-300 px-4 py-2.5 text-sm font-semibold text-slate-800 transition-colors hover:bg-slate-100 dark:border-slate-700 dark:text-slate-200 dark:hover:bg-slate-800"
>
GitHub skills guide
@@ -386,7 +386,7 @@ export function SkillDetail(): React.ReactElement {
{relatedTopicPages.map((page) => (
<Link
key={page.slug}
to={`/topics/${page.slug}`}
to={toIndexableRoutePath(`/topics/${page.slug}`)}
className="rounded-xl border border-slate-200 bg-gradient-to-br from-white to-slate-50 p-4 transition-colors hover:border-slate-400 dark:border-slate-800 dark:from-slate-950 dark:to-slate-900 dark:hover:border-slate-600"
>
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-slate-500 dark:text-slate-400">
@@ -1,9 +1,9 @@
import { Link, useParams } from 'react-router-dom';
import { Link, useParams } from 'react-router';
import { Icon } from '../components/ui/Icon';
import { useSkills } from '../context/SkillContext';
import { getCuratedSkillsForSeoLandingPage, getSeoLandingPage, seoLandingPages } from '../data/seoLandingPages';
import { usePageMeta } from '../hooks/usePageMeta';
import { buildTopicLandingFallbackMeta, buildTopicLandingMeta } from '../utils/seo';
import { buildTopicLandingFallbackMeta, buildTopicLandingMeta, toIndexableRoutePath } from '../utils/seo';
export function TopicLanding(): React.ReactElement {
const { slug } = useParams<{ slug: string }>();
@@ -35,7 +35,7 @@ export function TopicLanding(): React.ReactElement {
{seoLandingPages.slice(0, 2).map((landing) => (
<Link
key={landing.slug}
to={`/topics/${landing.slug}`}
to={toIndexableRoutePath(`/topics/${landing.slug}`)}
className="inline-flex items-center justify-center rounded-lg border border-slate-300 px-4 py-2.5 text-sm font-semibold text-slate-800 transition-colors hover:bg-slate-100 dark:border-slate-700 dark:text-slate-200 dark:hover:bg-slate-800"
>
{landing.eyebrow}
@@ -68,7 +68,7 @@ export function TopicLanding(): React.ReactElement {
{page.links.map((link) => link.to ? (
<Link
key={`${link.label}-${link.to}`}
to={link.to}
to={toIndexableRoutePath(link.to)}
className="inline-flex items-center justify-center rounded-lg border border-slate-300 px-4 py-2.5 text-sm font-semibold text-slate-800 transition-colors hover:bg-slate-100 dark:border-slate-700 dark:text-slate-200 dark:hover:bg-slate-800"
>
{link.label}
@@ -131,7 +131,7 @@ export function TopicLanding(): React.ReactElement {
{curatedSkills.map((skill) => (
<article key={skill.id} className="rounded-xl border border-slate-200 p-4 dark:border-slate-800">
<h3 className="text-base font-semibold text-slate-900 dark:text-slate-100">
<Link to={`/skill/${encodeURIComponent(skill.id)}`}>@{skill.name}</Link>
<Link to={toIndexableRoutePath(`/skill/${encodeURIComponent(skill.id)}`)}>@{skill.name}</Link>
</h3>
<p className="mt-2 text-sm leading-relaxed text-slate-600 dark:text-slate-300">{skill.description}</p>
<p className="mt-3 text-xs font-medium uppercase tracking-wide text-slate-500">{skill.category}</p>
@@ -166,7 +166,7 @@ export function TopicLanding(): React.ReactElement {
{relatedTopicPages.map((landing) => (
<Link
key={landing.slug}
to={`/topics/${landing.slug}`}
to={toIndexableRoutePath(`/topics/${landing.slug}`)}
className="inline-flex items-center justify-center rounded-lg border border-slate-300 px-3.5 py-2 text-sm font-semibold text-slate-800 transition-colors hover:bg-slate-100 dark:border-slate-700 dark:text-slate-200 dark:hover:bg-slate-800"
>
{landing.h1}
@@ -93,7 +93,7 @@ describe('Home', () => {
name: /AAS Core: agent-first skill stacks for Codex, Claude Code, and compatible clients/i,
})).toBeInTheDocument();
expect(screen.getByText(/Search\. Choose\. Validate\. Preview\./i)).toBeInTheDocument();
expect(screen.getByRole('link', { name: /Review an AAS Core stack/i })).toHaveAttribute('href', '/workbench');
expect(screen.getByRole('link', { name: /Review an AAS Core stack/i })).toHaveAttribute('href', '/workbench/');
expect(screen.getByText(/What is the difference between skills and MCP tools/i)).toBeInTheDocument();
expect(document.querySelector('meta[property="og:title"]')).toHaveAttribute(
'content',
@@ -18,6 +18,10 @@ describe('Plugins', () => {
expect.stringContaining('docs/users/getting-started.md'),
);
expect(screen.getByText(/Plugins, bundles, and workflows serve different decisions/i)).toBeInTheDocument();
expect(screen.getByRole('link', { name: '@frontend-developer' })).toHaveAttribute(
'href',
'/skill/frontend-developer/',
);
expect(document.title).toContain('AAS Specialized Plugins');
expect(document.querySelector('meta[name="description"]')).toHaveAttribute(
'content',
@@ -107,7 +107,7 @@ describe('SkillDetail', () => {
expect(screen.getByText(/Related topic guides/i)).toBeInTheDocument();
expect(screen.getByRole('link', { name: /Antigravity plugins/i })).toHaveAttribute(
'href',
'/topics/antigravity-plugins',
'/topics/antigravity-plugins/',
);
expect(screen.getByTestId('markdown-content')).toHaveTextContent('This is the skill content.');
expect(document.title).toContain('react-patterns');
@@ -294,7 +294,7 @@ describe('SkillDetail', () => {
expect(screen.getByRole('link', { name: /Review Core artifacts/i })).toHaveAttribute(
'href',
'/workbench',
'/workbench/',
);
});
});
@@ -37,11 +37,11 @@ describe('TopicLanding', () => {
expect(screen.getByRole('heading', { name: /Recommended skills for this workflow/i })).toBeInTheDocument();
expect(screen.getByRole('link', { name: /@Antigravity Agent Manager/i })).toHaveAttribute(
'href',
'/skill/antigravity-agent-manager',
'/skill/antigravity-agent-manager/',
);
expect(screen.getByRole('link', { name: /GitHub source for AAS Core and its skill catalog/i })).toHaveAttribute(
'href',
'/topics/github-ai-skills-repository',
'/topics/github-ai-skills-repository/',
);
expect(screen.getAllByText(/Antigravity CLI skills/i).length).toBeGreaterThan(0);
@@ -1,6 +1,6 @@
import React from 'react';
import { render, RenderOptions } from '@testing-library/react';
import { MemoryRouter, Routes, Route } from 'react-router-dom';
import { MemoryRouter, Routes, Route } from 'react-router';
import { SkillProvider } from '../context/SkillContext';
// Custom render with router and SkillProvider