Prototype logo

Prototype

Organization
nightly-labs
prototype

Build several different design directions (3 by default) for a feature or issue as Storybook stories, show them to the user, and let the user choose one. Use when the user writes `$prototype <feature>`, "prototype X", or asks for design variants, options, or directions before implementation.

Overview

Publishernightly-labs
Repositoryopenbot
Skill nameprototype
Stars
521
Forks
81
Bundled files
Instructions only
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by nightly-labs on GitHub. Read the source before you install it.

Installation

Install the Prototype AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/nightly-labs/openbot/tree/main/.agents/skills/prototype
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/nightly-labs/openbot.git /tmp/openbot
mkdir -p .claude/skills
cp -r /tmp/openbot/.agents/skills/prototype .claude/skills/prototype
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Prototype in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Prototype on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Prototype is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Prototype

Make a small number of different, clickable directions for one feature in Storybook. Show them to the user. The user chooses the direction. Do not implement the feature in product code before the user chooses.

The usual call is short, for example $prototype new pricing page. Get the missing details from the issue and the code. Ask only when you cannot continue without the user.

Inputs

  • Subject: the text after $prototype, an issue number, or an issue URL.
  • Count: 3 variants, unless the user gives a different number.
  • Style: follow the repository style and reuse its components, unless the user says otherwise (for example "go wild", "new visual style", "ignore the current design"). When the user sets the style aside, say which parts you changed.

Step 1 — Understand the subject

  1. When the subject is an issue, read it: gh issue view <n> --comments. Otherwise search open issues for the subject: gh issue list --search "<subject>" --state open. Use a match only when it is clearly the same feature.

  2. Find the current code for the feature, when it exists. Read it and its existing stories. Note what the user can do now, and the states it has (empty, loading, error, long data, narrow width).

  3. Find the surface:

    SurfaceStory locationStylesheet
    Desktop renderer, shared UIsrc/renderer/stories/Global; .storybook/preview.tsx loads it
    Public web (apps/auth-api)Beside the page, in apps/auth-api/src/components/<area>/. For a new page, use landing/Import apps/auth-api/src/styles.css in the story, as DiscordConnectPage.stories.tsx does

    A pricing page, landing page, or article is public web. A dialog, panel, sidebar, or settings screen is desktop.

    A public web page with the site header needs a router stand-in. Copy the WithRouter pattern from AgentTemplatePage.stories.tsx.

  4. Read packages/ui/AGENTS.md and src/renderer/AGENTS.md. For public web, also read apps/auth-api/AGENTS.md.

  5. Write down your assumptions in one short list. You show it to the user in Step 6.

Step 2 — List what to reuse

Before you write UI, list the parts that already exist:

  • Primitives from @openbot/ui (packages/ui/src/).
  • Feature components from @openbot/ui/features/<domain>/....
  • For public web: existing site components and classes in apps/auth-api/src/components/ and apps/auth-api/src/styles.css. Import only explicit @openbot/ui/... subpaths there. The @openbot/ui barrel fails the Worker typecheck.
  • Data that already exists, such as plans, prices, and limits in packages/contracts. Use the real values, not invented ones.
  • Fixtures and mocks: src/renderer/stories/*fixtures*, src/renderer/src/preview/, and the fixtures of related stories.
  • Design tokens and existing CSS classes. Do not add new colors, font sizes, radii, or spacing values when a token exists.
  • Similar screens in the app. A new screen must look like it belongs next to them.

Step 3 — Choose the directions

Each direction must be a different answer to the problem, not a different color. Change at least one of these between variants:

  • Information hierarchy: what the user sees first.
  • Layout: cards, table, list and detail, single column, steps.
  • Interaction model: inline edit, dialog, wizard, progressive disclosure.
  • Density: compact for experts, spacious for first use.

Give each direction a letter, a short name, one sentence for its idea, and one sentence for its main cost. Example for a pricing page:

VariantIdeaCost
A. Plan cardsThree cards side by side; the recommended plan is in the middleFeature differences are hard to compare
B. Comparison tableOne table with a row per featureDense on narrow screens
C. Guided choiceTwo questions, then one recommended planOne more step before the price

Do not ask the user to approve the directions. Build them.

Step 4 — Build the variants

Put each prototype in its own files. Do not change product code, shared components, contracts, or the i18n catalog for a prototype.

  • Stories: <Feature>Prototype.stories.tsx.
  • Prototype components, when the story file becomes long: <feature>-prototype.tsx in the same directory.
  • Styles, only when tokens and existing classes are not sufficient: <Feature>Prototype.css in the same directory. Scope each rule under a class of the prototype.

Use this story structure:

tsx
const meta = {
  title: "Prototypes/Pricing page",
  parameters: { layout: "fullscreen", a11y: { test: "error" } },
} satisfies Meta;

export default meta;
type Story = StoryObj<typeof meta>;

/** Three plan cards. The recommended plan is in the middle. */
export const PlanCards: Story = { name: "A. Plan cards", render: () => <PlanCardsVariant plans={PLANS} /> };
/** One table with a row for each feature. */
export const ComparisonTable: Story = { name: "B. Comparison table", render: () => <ComparisonTableVariant plans={PLANS} /> };
/** Two questions, then one recommended plan. */
export const GuidedChoice: Story = { name: "C. Guided choice", render: () => <GuidedChoiceVariant plans={PLANS} /> };

Give each variant component a Variant suffix, so its name is not the same as the story export.

Rules:

  • All variants use the same fixture data, so the user compares design, not content. Use realistic data: real plan names, long names, many rows.
  • Make each variant interactive with local signals or a store. A button that does nothing is acceptable only when its result is outside the feature.
  • When a state is important to the decision (empty, error, loading), add it as an extra story with the same letter, for example A2. Plan cards, empty.
  • Draft new copy as literals. no-hardcoded-ui-text.grit does not check stories, prototype files beside them, or apps/auth-api. On desktop, use existing i18n keys when they fit; the chosen variant moves its other text to catalog keys in Step 7.
  • When you reuse a shared class, check its media queries at phone width. Some site classes, such as compare-table, change layout below 640 px.
  • Keep a11y: { test: "error" }. Fix each accessibility violation. Use real roles, labels, and focus order.
  • Do not add play functions or data-testid. check:ui rejects them.
  • Do not add dependencies.
  • Do not add tests for a prototype.

Step 5 — Check and capture

Run these checks one at a time:

  1. bunx biome check --write --max-diagnostics=none <new files>
  2. The one typecheck project for the surface: bun run typecheck:renderer for src/renderer/stories/, or bun run typecheck:api for public web.
  3. Run bun run dev:status. When it lists a Storybook for this worktree, reuse it. Otherwise start Storybook with the Bash background option: env -u ELECTRON_RUN_AS_NODE bun run storybook --no-open. Use the port that it prints in Storybook: http://localhost:<port>. Do not pass --port. When Storybook exits with "Port is not available", another process holds the port that the wrapper chose. Start again with OPENBOT_STORYBOOK_PORT=<a free port> before the command.
  4. Open each variant at http://localhost:<port>/iframe.html?id=<story-id>&viewMode=story. The story ID is the title and the export name in kebab case, for example prototypes-pricing-page--plan-cards.
  5. Take a screenshot of each variant with the Playwright or Chrome DevTools tools. Save them in .openbot-build/prototypes/<feature>/ (git ignores this directory), for example a-plan-cards.png. Use a desktop width (1440 px) and, for public web, also a phone width (390 px). The desktop stylesheet sets overflow: hidden on html and body, so a full-page screenshot shows only the viewport. Before each screenshot, resize the viewport height to the scrollHeight of #storybook-root.
  6. Look at each screenshot. Fix broken layout, clipped text, overlap, and console errors that the prototype causes before you show the variants. Report errors that also occur without the prototype; do not fix them.

Leave Storybook running, so that the user can open the variants. When a subagent did the work, its background Storybook can stop when the subagent ends. Before you send the links, open one. When it does not load, start Storybook again.

Step 6 — Show the variants

Write one message:

  1. Your assumptions from Step 1, as a short list.
  2. One table: variant, idea, strengths, costs, Storybook link (http://localhost:<port>/?path=/story/<story-id>).
  3. The screenshots, embedded with their absolute paths.
  4. Your recommendation, in one sentence, with the reason.
  5. One question: which direction, or which mix (for example "B with the header of A").

Then stop. Do not commit, push, or open a PR unless the user asks.

Step 7 — After the user chooses

  • More rounds: when the user asks for changes or a mix, change the prototypes and repeat Steps 5 and 6. Remove the variants that the user rejected.
  • Implement: when the user tells you to build the chosen direction, build it in product code with the normal repository rules: shared UI in packages/ui, text as docs/i18n.md says for the surface, release notes in changelog.d/, and focused checks only. Then delete the prototype files, or change the chosen story into the feature's normal story under its domain title. Do not keep Prototypes/ stories in a PR unless the user asks for them.

Frequently asked questions

What does the Prototype AI skill do?

Build several different design directions (3 by default) for a feature or issue as Storybook stories, show them to the user, and let the user choose one. Use when the user writes `$prototype <feature>`, "prototype X", or asks for design variants, options, or directions before implementation.

Why use Prototype on TypingMind?

Because you install it once and use it with any model. Prototype is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Prototype in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/nightly-labs/openbot/tree/main/.agents/skills/prototype. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Prototype?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Prototype?

As many as you like. As long as a model supports skills, you can use Prototype with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Prototype AI skill free?

It is published on GitHub by nightly-labs. Check the repository for licensing terms. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇