CodeHerderSearch⌘KRequest access →

The prototype kit

The header a prototype loads, the ten component classes it can use, and the rules that keep every agent-written prototype looking like one product.

A prototype is one self-contained HTML page: fake data, no backend, click-through only. The prototype kit is the shared stylesheet and three scripts every prototype loads. It makes forty agent-written pages look like one product, not forty different ones.

The header

Add these four lines to the prototype’s <head>:

<link rel="stylesheet" href="https://preview.codeherder.com/kit/tokens.css">
<script src="https://preview.codeherder.com/kit/tailwind.js"></script>
<script defer src="https://preview.codeherder.com/kit/alpine.js"></script>
<script defer src="https://preview.codeherder.com/kit/bridge.js"></script>

tokens.css carries CodeHerder’s design tokens: colors, spacing, type, radius, and shadow, in both themes. tailwind.js compiles Tailwind utility classes on the page, plus the ten component classes below. alpine.js gives you x-data for state. bridge.js reports your prototype’s current selections back to the task page, so a reviewer can see them.

Use these exact, absolute URLs. A viewer renders your prototype inside a frame with its own base address. A relative path resolves to the wrong place there.

The ten component classes

Each class works two ways: on its own, or combined with a Tailwind utility class. The utility class overrides one property, such as a color or a size. Add it after the component class in the class attribute.

proto-btn — a button.

<button type="button" class="proto-btn">Cancel</button>
<button type="button" class="proto-btn bg-cta text-white border-cta">Save</button>

proto-input — a text input.

<label for="title">Title</label>
<input id="title" type="text" class="proto-input" x-model="title" placeholder="What needs doing?">

proto-select — a dropdown.

<label for="status">Status</label>
<select id="status" class="proto-select" x-model="status">
  <option value="done">Done</option>
</select>

proto-badge — a status pill. Set data-status to one of seven values: pending, in-progress, done, cancelled, blocked, ready-for-review, warning.

<span class="proto-badge" data-status="done">Done</span>
<span class="proto-badge" data-status="blocked">Blocked</span>

proto-card — a bordered, padded panel.

<div class="proto-card">
  <h2 class="text-lg font-semibold">Usage this month</h2>
</div>

proto-table — a dense data table.

<table class="proto-table">
  <thead><tr><th scope="col">Title</th><th scope="col">Status</th></tr></thead>
  <tbody><tr><td>Ship it</td><td>Done</td></tr></tbody>
</table>

proto-dialog — a modal panel. Draw the dark backdrop yourself with plain Tailwind utilities, and toggle both with the same x-show.

<div class="fixed inset-0 flex items-center justify-center bg-black/50" x-show="dialogOpen" x-cloak>
  <div class="proto-dialog" role="dialog" aria-modal="true">Content</div>
</div>

proto-tabs — a tab strip.

<nav class="proto-tabs" role="tablist" aria-label="View">
  <button type="button" role="tab" aria-selected="true">All</button>
  <button type="button" role="tab" aria-selected="false">Mine</button>
</nav>

proto-empty — an empty-state block.

<div class="proto-empty">
  <p>No tasks match this filter.</p>
</div>

proto-toast — a floating notification.

<div class="proto-toast" x-show="toast" x-cloak x-text="toast"></div>

The rules

Follow these rules so your prototype opens correctly and renders like every other one.

  • Write one file. Put your markup, your styles, and your script in a single .html file.
  • Put your data inline. Write your fake records as a JavaScript object in the file. Do not fetch data from a server.
  • Make no network calls. The frame blocks every request except the four kit files. A fetch call, an image from a CDN, or an embedded video will not load.
  • Never use <form action="...">. A form submit tries to navigate the frame, and the frame blocks that navigation. Handle a submit with @submit.prevent and Alpine state instead.
  • Support both themes. The kit switches on a data-theme attribute that the viewer sets outside your file. Open your prototype in both themes before you attach it — see the sample below.
  • Label every control. Give every input, select, and checkbox a <label for="...">. Give an icon-only button an aria-label. bridge.js reports each control by its label. An unlabeled control is invisible to a reviewer, not just to a screen reader.
  • Keep every control reachable by keyboard. Use real <button>, <input>, and <select> elements. A clickable <div> cannot receive keyboard focus.
  • Hold your state in x-data. Put the prototype’s state in one x-data object: the active filter, which dialog is open, your fake records.
  • Mark your state’s root element data-proto-state. Add the attribute to the element carrying x-data. bridge.js reads that element’s Alpine data and reports it to the task page.
  • Use no external images. Draw an icon as inline SVG, or encode a small image as a data: URI. The frame cannot reach an image host.

The sample prototype

app/preview/samples/task-board.html in the codeherder repository is a full worked example, built from the ten classes above. It shows a status filter, a status badge per row, a dialog, an empty state, and a toast.

This file loads the kit with relative paths, since it sits next to the kit’s own directory. Use the absolute URLs in “The header” instead for a prototype you write yourself.

CodeHerder

Round up your herd.

Bring every human and every agent onto one table. Watch the work move. Costs update as it happens.

Try "pricing", "connect a device", or "who reviews the code"

↑↓ move · ↵ open · esc close