Skip to content

feat(landing): add /skill-watch page wired to frames.ag dataset#16

Merged
Markeljan merged 1 commit into
mainfrom
claude/nervous-galileo-c7d76e
May 12, 2026
Merged

feat(landing): add /skill-watch page wired to frames.ag dataset#16
Markeljan merged 1 commit into
mainfrom
claude/nervous-galileo-c7d76e

Conversation

@Markeljan
Copy link
Copy Markdown
Collaborator

Summary

Adds a new Skill Watch page at /skill-watch that pulls audited agent skills from the microchipgnu/skill-watch dataset on frames.ag and renders them as a live, sortable, filterable inventory. The "Examples" link in the header and both footer columns now point at the new page; the existing /examples route stays in place for now.

What's on the page

  1. Hero with live count + most-recent scan timestamp
  2. Snapshot stats (6 cards: skills monitored, with findings, clean, avg overall score, avg security score, total installs)
  3. Findings-by-severity bars + grade distribution chart (headlined by the modal grade — e.g. "Mostly C · 261")
  4. OWASP top categories — click any row to filter the inventory below by that AST-NN
  5. Inventory grid with paginated cards (24 per page), search, filter by grade / vuln status / OWASP, and 7-way sort
  6. CTA linking to install + the upstream dataset

Inventory UX

  • Pagination — 24 cards per page with "Show 24 more" + "Show all N" actions; resets to 24 whenever a filter changes
  • Sticky filter bar at top-[64px] with backdrop-blur so filters stay reachable while scrolling
  • Mobile sort — sort row is visible at all viewports with horizontal-scroll fallback (was previously hidden md:flex)
  • OWASP bars → table filter — bars dispatch a skill-watch:filter-owasp event that the table listens for, then smooth-scrolls to #inventory. The bar count (e.g. AST05 = 260) matches the filter result exactly
  • Reset filters affordance + empty-state with reset button
  • Search matches name, owner, repo, description, OWASP id, and rule id
  • Accessibilityaria-pressed on every toggle, role="img" + aria-label on grade chips and capability badges, aria-live="polite" on the result counter, scroll-mt-24 on #inventory to clear the fixed header

Performance note for reviewers

The upstream JSON is ~4.5 MB. Passing the raw response (including the per-field evidence block with URLs + excerpts on every record) to the client component embeds the full payload in the page HTML and stalls React hydration — clicks become unresponsive. Fixed by slimEntity() in page.tsx which drops evidence before serialization, shrinking the inline payload from ~3.8 MB to ~600 KB. Next.js's fetch data cache also refuses the 4.5 MB response (>2 MB limit) — that's a non-fatal warning at build time; ISR still works, each revalidate hits the API fresh.

Test plan

  • bun run build/skill-watch route emits at ~6.5 kB, static, 1h revalidate
  • bun run lint clean
  • Desktop preview: filter by grade/vuln/OWASP, sort by each option, pagination, OWASP bar click → applies filter + scrolls to inventory
  • Mobile (375px) preview: search input full-width, filters wrap, sort row scrolls horizontally
  • AST05 click → 260/295 cards (matches bar count exactly)
  • Reset filters → counter back to 295/295, visible count back to 24
  • Header and footer links resolve to /skill-watch

🤖 Generated with Claude Code

Adds a live Skill Watch page that pulls audited agent skills from the
microchipgnu/skill-watch dataset on frames.ag (ISR, 1h revalidate) and
displays them as sortable, filterable cards with snapshot stats, a
severity + grade breakdown, an OWASP AST-10 distribution chart, and a
paginated inventory grid. Replaces the "Examples" nav entry in the
header and both footer columns with "Skill Watch" pointing at the new
route; the /examples page itself stays in place.

Inventory UX: 24 cards per page with "Show 24 more" + "Show all" load
actions, sticky filter bar (search + grade + vuln + OWASP filter
groups), sort row visible at all viewports, Reset filters affordance,
ARIA pressed states on every toggle, and per-card grade/capability
labels for screen readers. OWASP bars dispatch a custom event that
auto-applies the OWASP filter and smooth-scrolls to #inventory.

To unblock React hydration the server prop is slimmed via slimEntity()
to drop the heavy per-field evidence block before serialization,
shrinking the embedded HTML payload from ~3.8MB to ~600KB.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Markeljan Markeljan merged commit 27e4128 into main May 12, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant