Public
Interactive trading-card view of an agent skill repo
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.

skillbook

A trading-card view of an agent skill repo.

Live: / · Raw JSON the agent reads: /api/skills · Raw SKILL.md: /raw/daily-standup/SKILL.md

Why

Inspired by Thariq's "HTML is the new markdown". Agent skills today are just folders of markdown files — fine for the agent, bleak for the human looking at their own library. The data layer should stay markdown (so the agent picks up edits next session); the human view can be anything HTML lets you build.

So this val is a skill repo, with a card-binder UI on top:

  • Agent face: read skills/<slug>/SKILL.md, skills/<slug>/memories/*.md, etc. directly. Routes at /raw/... expose them with the right content-type.
  • Human face: painted fantasy trading cards — front shows what the skill does + how to invoke it + flavor text. Flip to read the full SKILL.md, drag to reorder, search by trigger phrase. Memories sit on the back as stickers; card gems mark setup cost; Lv 7+ cards get the gold foil treatment. Click open on the back to open a full-width view at proper reading width. Every deck also gets its own page at /<deck-slug> (/valtown, /anthropic, /skillbook) — deck headings link there.
  • Color is per-card vibe, not a strict color system. Have fun with each card individually.
  • Card art: OpenAI image generation from a per-skill prompt, cached in blob storage so each card costs one generation. Set OPENAI_API_KEY to enable; without it cards show a framed paper placeholder.

Layout

The skills/ directory mirrors the standard skill-repo shape so an agent could read this val unchanged:

skills/
  _index.json                       <- binder-only card metadata (color, art prompt, level, deck — cards group into one section per deck)
  daily-standup/
    SKILL.md                        ← YAML frontmatter (name, description, triggers) + markdown body
    memories/
      feedback_group_by_thread.md   ← per-memory file, frontmatter typed
      project_q2_focus.md
      feedback_plain_prose.md
    templates/
      standup_message.md
      blocker_nudge.md
    scripts/                        ← optional helper scripts
  inbox-zero/
  pr-review/
  anthropic/                        ← imported decks get their own folder;
    xlsx/                              the slug is the full path ("anthropic/xlsx")
    pdf/
    ...
  valtown/
    http-endpoints/
    sqlite-storage/
    ...

The only non-standard piece is skills/_index.json, which carries the presentational metadata the agent doesn't need (mana cost, art prompt, card color, mock level/invocation stats). An agent that doesn't know about it just ignores it.

Files

  • main.tsx — Hono server. Page shell, JSON API, raw-file routes per skill, OpenAI art route.
  • data/loader.ts — walks skills/, parses frontmatter, assembles Skill[].
  • static/index.html — page shell + card template + modal markup.
  • static/client.js — vanilla JS: fetches, renders, flip / drag / search / shuffle / expand modal.

Remix it for your own skills

  1. Replace the demo skills/<slug>/ folders with your own. Use name, description, triggers in SKILL.md frontmatter.
  2. Update skills/_index.json with one entry per skill (color, art prompt, mana cost, etc.).
  3. Set OPENAI_API_KEY if you want art generation.
  4. The agent stays happy — it reads the markdown verbatim. The binder updates on its own.

The live page includes a Val Town remix banner that points back to this val's project page, where visitors can use Val Town's Remix button.

Not included on purpose

  • No persistence for UI state. Drag-reorder and shuffle are session-only. Adding sqlite or a save-back-to-disk pattern is the v2 move.
  • No editing — stickers are read-only here. The "edit a memory in place and round-trip to feedback_*.md" interaction would feel great but pulls in conflict resolution.
  • No auth — public template. Fork it and add oauthMiddleware if your skill content is private.