{
  "$schema": "https://ui.shadcn.com/schema/registry.json",
  "name": "benhof",
  "homepage": "https://benhof.ai/components",
  "items": [
    {
      "name": "tournament-bracket",
      "title": "Tournament Bracket",
      "description": "A single-elimination bracket with pure-CSS connectors — seeds, scores, byes, winner highlighting, live/final game states, linkable match cards, and per-game times and field locations. No measuring, no libraries.",
      "files": [
        {
          "path": "src/registry/components/tournament-bracket/tournament-bracket.tsx",
          "type": "registry:component",
          "target": "@components/tournament-bracket.tsx"
        },
        {
          "path": "src/registry/components/tournament-bracket/bracket-team-trace.tsx",
          "type": "registry:component",
          "target": "@components/bracket-team-trace.tsx"
        }
      ],
      "categories": [
        "tournament"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "game-setup-panel",
      "title": "Game Setup Panel",
      "description": "A controlled pregame form for team names, location, innings, and run-rule presets. Validation stays in the component; persistence and game creation stay in your app.",
      "files": [
        {
          "path": "src/registry/components/game-setup-panel/game-setup-panel.tsx",
          "type": "registry:component",
          "target": "@components/game-setup-panel.tsx"
        }
      ],
      "categories": [
        "scorekeeping"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "active-game-card",
      "title": "Active Game Card",
      "description": "A compact resume card for an in-progress or paused game with teams, score, inning, location, update text, and an optional controlled action.",
      "files": [
        {
          "path": "src/registry/components/active-game-card/active-game-card.tsx",
          "type": "registry:component",
          "target": "@components/active-game-card.tsx"
        }
      ],
      "categories": [
        "scorekeeping"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "score-panel",
      "title": "Score Panel",
      "description": "The live two-team score card from a scorekeeper's phone — inning header, AT BAT indicator, and +/− steppers that appear when you wire up onScoreChange. Read-only without it.",
      "files": [
        {
          "path": "src/registry/components/score-panel/score-panel.tsx",
          "type": "registry:component",
          "target": "@components/score-panel.tsx"
        }
      ],
      "categories": [
        "scorekeeping"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "count-display",
      "title": "Count Display",
      "description": "Balls, strikes, and outs as broadcast-style dot rows. A full row means the next one ends it; max counts are configurable because wiffle formats disagree about everything.",
      "files": [
        {
          "path": "src/registry/components/count-display/count-display.tsx",
          "type": "registry:component",
          "target": "@components/count-display.tsx"
        }
      ],
      "categories": [
        "scorekeeping"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "base-diamond",
      "title": "Base Diamond",
      "description": "Runners on base at a glance — a basepath diamond with bases that fill when occupied. Built for umpires tracking ghost runners on a phone between pitches.",
      "files": [
        {
          "path": "src/registry/components/base-diamond/base-diamond.tsx",
          "type": "registry:component",
          "target": "@components/base-diamond.tsx"
        }
      ],
      "categories": [
        "scorekeeping"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "play-by-play",
      "title": "Play-by-Play",
      "description": "A chronological game log, newest play on top — inning markers, kind-colored dots, optional timestamps. Pass events, get a feed; the offline-sync machinery stayed at the ballpark.",
      "files": [
        {
          "path": "src/registry/components/play-by-play/play-by-play.tsx",
          "type": "registry:component",
          "target": "@components/play-by-play.tsx"
        }
      ],
      "categories": [
        "scorekeeping"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "scorekeeper-layout",
      "title": "Scorekeeper Layout",
      "description": "The game-day app shell: pinned score header, scrolling work area, and a side panel that becomes a pull-up sheet on phones. Dependency-free — give the root a height and it stays self-contained.",
      "files": [
        {
          "path": "src/registry/components/scorekeeper-layout/scorekeeper-layout.tsx",
          "type": "registry:component",
          "target": "@components/scorekeeper-layout.tsx"
        }
      ],
      "categories": [
        "scorekeeping"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "final-score-summary",
      "title": "Final Score Summary",
      "description": "A postgame score card that identifies the winner or tie, explains how the game ended, and exposes optional share and play-again actions.",
      "registryDependencies": [
        "https://benhof.ai/r/score-panel.json"
      ],
      "files": [
        {
          "path": "src/registry/components/final-score-summary/final-score-summary.tsx",
          "type": "registry:component",
          "target": "@components/final-score-summary.tsx"
        }
      ],
      "categories": [
        "scorekeeping"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "pool-standings",
      "title": "Pool Standings",
      "description": "Pool-play standings — rank, W-L(-T), run differential, runs scored, with a marker for teams advancing to the bracket. Ranks internally by the common pool tiebreak order, or pass pre-sorted rows.",
      "files": [
        {
          "path": "src/registry/components/pool-standings/pool-standings.tsx",
          "type": "registry:component",
          "target": "@components/pool-standings.tsx"
        }
      ],
      "categories": [
        "tournament"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "bracket-pickem",
      "title": "Bracket Pick'em",
      "description": "A bracket challenge on top of Tournament Bracket: tap a team to advance them round by round; changing an early pick invalidates everything downstream. Pass first-round matchups, get picks back.",
      "registryDependencies": [
        "https://benhof.ai/r/tournament-bracket.json"
      ],
      "files": [
        {
          "path": "src/registry/components/tournament-bracket/bracket-pickem.tsx",
          "type": "registry:component",
          "target": "@components/bracket-pickem.tsx"
        }
      ],
      "categories": [
        "tournament"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "scoreboard",
      "title": "Scoreboard",
      "description": "A ballpark line score — innings across the top, away/home lines, R/H/E totals. Works for any period count.",
      "files": [
        {
          "path": "src/registry/components/scoreboard/scoreboard.tsx",
          "type": "registry:component",
          "target": "@components/scoreboard.tsx"
        }
      ],
      "categories": [
        "scorekeeping"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "event-countdown",
      "title": "Event Countdown",
      "description": "A live countdown with stat slots beside the clock, a LIVE state once the event starts, and hydration-safe rendering.",
      "files": [
        {
          "path": "src/registry/components/event-countdown/event-countdown.tsx",
          "type": "registry:component",
          "target": "@components/event-countdown.tsx"
        }
      ],
      "categories": [
        "tournament"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "field-schedule",
      "title": "Field Schedule",
      "description": "Map games across times and fields with live and final states.",
      "files": [
        {
          "path": "src/registry/components/field-schedule/field-schedule.tsx",
          "type": "registry:component",
          "target": "@components/field-schedule.tsx"
        }
      ],
      "categories": [
        "operations"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "roster-check-in",
      "title": "Roster Check-In",
      "description": "Track player arrival and waiver readiness before first pitch.",
      "files": [
        {
          "path": "src/registry/components/roster-check-in/roster-check-in.tsx",
          "type": "registry:component",
          "target": "@components/roster-check-in.tsx"
        }
      ],
      "categories": [
        "operations"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "run-of-show",
      "title": "Run of Show",
      "description": "Keep event timing, owners, and live operating status in one timeline.",
      "files": [
        {
          "path": "src/registry/components/run-of-show/run-of-show.tsx",
          "type": "registry:component",
          "target": "@components/run-of-show.tsx"
        }
      ],
      "categories": [
        "operations"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "blueprint-frame",
      "title": "Blueprint Frame",
      "description": "A technical-drawing frame: dashed construction grid, figure caption, and a cursor-following spotlight that re-reveals your content through a radial mask. Dependency-free.",
      "files": [
        {
          "path": "src/registry/components/blueprint-frame/blueprint-frame.tsx",
          "type": "registry:component",
          "target": "@components/blueprint-frame.tsx"
        }
      ],
      "categories": [
        "site"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "now-section",
      "title": "Now Section",
      "description": "A dated, Markdown-capable list of what you're focused on right now — the /now page pattern as a drop-in section.",
      "dependencies": [
        "react-markdown"
      ],
      "files": [
        {
          "path": "src/registry/components/now-section/now-section.tsx",
          "type": "registry:component",
          "target": "@components/now-section.tsx"
        }
      ],
      "categories": [
        "site"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "wiffle-at-bat",
      "title": "Wiffle At-Bat",
      "description": "A tiny wiffle-ball mini game for 404 pages: a wobbling pitch, a swing timed with Space or click, and a home-run counter.",
      "files": [
        {
          "path": "src/registry/components/wiffle-at-bat/wiffle-at-bat.tsx",
          "type": "registry:component",
          "target": "@components/wiffle-at-bat.tsx"
        }
      ],
      "categories": [
        "site"
      ],
      "type": "registry:component",
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "content-blocks",
      "title": "Content Blocks",
      "description": "A self-contained block renderer for markdown, images, galleries, video, embeds, links, and callouts. Pass an array of blocks, get structured content.",
      "files": [
        {
          "path": "src/registry/components/content-blocks/content-blocks.tsx",
          "type": "registry:component",
          "target": "@components/content-blocks.tsx"
        }
      ],
      "categories": [
        "snax"
      ],
      "type": "registry:component",
      "dependencies": [
        "react-markdown"
      ],
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "content-block-editor",
      "title": "Content Block Editor",
      "description": "A drag-and-drop editor for managing a sequence of content blocks — markdown, media, embeds, and interactive components.",
      "files": [
        {
          "path": "src/registry/components/content-block-editor/content-block-editor.tsx",
          "type": "registry:component",
          "target": "@components/content-block-editor.tsx"
        }
      ],
      "categories": [
        "snax"
      ],
      "type": "registry:component",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "https://benhof.ai/r/content-blocks.json",
        "https://benhof.ai/r/link-preview.json"
      ],
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "link-preview",
      "title": "Link Preview",
      "description": "A compact link preview card with favicon, title, description, and thumbnail. Accepts preview data as props.",
      "files": [
        {
          "path": "src/registry/components/link-preview/link-preview.tsx",
          "type": "registry:component",
          "target": "@components/link-preview.tsx"
        }
      ],
      "categories": [
        "snax"
      ],
      "type": "registry:component",
      "dependencies": [
        "lucide-react"
      ],
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "vote-control",
      "title": "Vote Control",
      "description": "A Reddit-style upvote/downvote control with score display and vote retraction. Self-contained with internal state.",
      "files": [
        {
          "path": "src/registry/components/vote-control/vote-control.tsx",
          "type": "registry:component",
          "target": "@components/vote-control.tsx"
        }
      ],
      "categories": [
        "snax"
      ],
      "type": "registry:component",
      "dependencies": [
        "lucide-react"
      ],
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "poll",
      "title": "Poll",
      "description": "An interactive poll component with vote bars, result visibility modes, and response change support. Accepts poll data and vote callbacks.",
      "files": [
        {
          "path": "src/registry/components/poll/poll.tsx",
          "type": "registry:component",
          "target": "@components/poll.tsx"
        }
      ],
      "categories": [
        "snax"
      ],
      "type": "registry:component",
      "dependencies": [
        "lucide-react"
      ],
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "quiz",
      "title": "Quiz",
      "description": "An interactive quiz component for trivia and personality quizzes. Accepts questions (without correct answers) and a server-computed result. Never exposes correct_index to the client.",
      "files": [
        {
          "path": "src/registry/components/quiz/quiz.tsx",
          "type": "registry:component",
          "target": "@components/quiz.tsx"
        }
      ],
      "categories": [
        "snax"
      ],
      "type": "registry:component",
      "dependencies": [
        "lucide-react"
      ],
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "ranked-list",
      "title": "Ranked List",
      "description": "An interactive ranked list with optional community voting, item links, and descriptions. Accepts items as props.",
      "files": [
        {
          "path": "src/registry/components/ranked-list/ranked-list.tsx",
          "type": "registry:component",
          "target": "@components/ranked-list.tsx"
        }
      ],
      "categories": [
        "snax"
      ],
      "type": "registry:component",
      "dependencies": [
        "lucide-react"
      ],
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "moderation-queue",
      "title": "Moderation Queue",
      "description": "A moderation queue for reviewing community submissions — pending items with approve/reject actions and reviewed history.",
      "files": [
        {
          "path": "src/registry/components/moderation-queue/moderation-queue.tsx",
          "type": "registry:component",
          "target": "@components/moderation-queue.tsx"
        }
      ],
      "categories": [
        "snax"
      ],
      "type": "registry:component",
      "dependencies": [
        "lucide-react"
      ],
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "format-chooser",
      "title": "Format Chooser",
      "description": "A grid of 16 content format options grouped by Content, Lists, and Interactive. Accepts a selection callback.",
      "files": [
        {
          "path": "src/registry/components/format-chooser/format-chooser.tsx",
          "type": "registry:component",
          "target": "@components/format-chooser.tsx"
        }
      ],
      "categories": [
        "snax"
      ],
      "type": "registry:component",
      "dependencies": [
        "lucide-react"
      ],
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    },
    {
      "name": "create-studio",
      "title": "Create Studio",
      "description": "A create studio layout with format selection and a render-prop for the active form. Built on Format Chooser.",
      "files": [
        {
          "path": "src/registry/components/create-studio/create-studio.tsx",
          "type": "registry:component",
          "target": "@components/create-studio.tsx"
        }
      ],
      "categories": [
        "snax"
      ],
      "type": "registry:component",
      "dependencies": [
        "lucide-react"
      ],
      "registryDependencies": [
        "https://benhof.ai/r/format-chooser.json"
      ],
      "author": "Ben Hofstetter <ben.hofstetter@gmail.com>"
    }
  ]
}