AI-Assisted Development

RapidRailsUI publishes four machine-readable surfaces so Cursor, Claude Code, ChatGPT, and any other agent can generate correct component code on the first try — no guessing at syntax.

AI-Facing Resources

Three static files, ranked by how much context budget they cost. Point an agent at whichever fits the task — all three are always current with the live docs site.

File Size Use it when...
llms.txt ~1,300 lines Default choice. One-line-per-component index, argument-order and color conventions, form builder pattern. Enough for most single-component requests.
llms-full.txt ~19,000 lines llms.txt's one-liner isn't enough detail — full params, slots, variants, and copy-paste examples per component, one ## ComponentName section each.
llms-mini.txt ~60 lines Tight context budget. A single table (complexity, param/slot counts, AI-friendliness score) for a first pass over "which component do I need" before loading detail.

Starting point for most prompts: "Using RapidRailsUI (read https://rapidrails.cc/llms.txt first), build a <thing>." That's the whole setup step — no MCP server, no config file, no copy-paste into a system prompt required for tools that can fetch a URL.

Content Negotiation

Every /docs/<component> page — all 37, including newer ones like /docs/carousel and /docs/kanban — serves three representations of the same content depending on the request's Accept header. No .json/.md extension needed; it's pure header negotiation.

Accept header Response
text/html The rendered docs page (default for browsers).
application/json (or */*) Structured schema for that one component: params, slots, gotchas, related components/compositions — the same data the schema YAMLs hold, pre-merged.
text/markdown (or text/plain) The matching ## ComponentName section of llms-full.txt, as plain Markdown.
curl examples
# Plain curl sends "Accept: */*" by default, which matches JSON first —
# no -H flag needed to get structured data:
curl -s https://rapidrails.cc/docs/card | jq

# Explicit JSON (same result as above, spelled out):
curl -s https://rapidrails.cc/docs/tabs -H "Accept: application/json" | jq

# Markdown — the llms-full.txt section for one component, nothing else:
curl -s https://rapidrails.cc/docs/carousel -H "Accept: text/markdown"

# HTML — the actual rendered page (what a browser gets):
curl -s https://rapidrails.cc/docs/kanban -H "Accept: text/html"

Two aggregate JSON endpoints sit alongside the per-component negotiation:

  • GET /api/schema.json — every component's schema in one response. Large; use it for a one-shot "load everything" pull, not per-request.
  • GET /api/schema/components/<name>.json — one component, same shape as the per-page JSON negotiation.

The Installed Gem: Your Version-True Fallback

This site always documents the latest gem release. If your app's Gemfile.lock pins an older rapid_rails_ui, the hosted docs can describe params or behavior your installed version doesn't have yet. Every component ships its own USAGE.md right next to component.rb inside the gem — that file is exact for whatever version is actually installed.

Find the installed USAGE.md files
# Locate every component's USAGE.md in the installed gem:
find "$(bundle show rapid_rails_ui)" -name USAGE.md

# Or jump straight to one component:
cat "$(bundle show rapid_rails_ui)/app/components/rapid_rails_ui/card/USAGE.md"

Tell your agent to prefer this when versions might disagree: "Before using rui_<component>, check $(bundle show rapid_rails_ui)/app/components/rapid_rails_ui/<component>/USAGE.md in this repo's installed gem — it's authoritative for our pinned version, even if it differs from rapidrails.cc."

Schema YAMLs for Advanced Agents

The JSON content negotiation above is a per-component merge of five machine-readable YAML files, shipped inside the gem at lib/rapid_rails_ui/schema/. An agent working directly in your codebase (rather than fetching from rapidrails.cc) can read these directly for the same data, offline:

File Purpose
manifest.yml Per-component metadata: helper name, complexity, param/slot counts, form-builder support, AI-usability score.
slots.yml Every renders_one/renders_many slot per component, with an example with_* call.
gotchas.yml Non-obvious param interactions that silently fail — e.g. a plain rui_button inside form_with renders type="button" and never submits; use f.rui_button or type: :submit.
families.yml Decision trees for choosing between similar components — e.g. "filter table rows" points to rui_live_search, not rui_combobox.
compositions.yml Multi-component recipes no single component covers — e.g. "author byline" = rui_avatar + rui_text, with the exact ERB.

A sixth file, relationships.yml, is auto-derived from the five above (which components compose with which, which are commonly confused) and merged into the per-component JSON automatically — you don't need to read it separately.

Signature sheet

Since v0.90.0 the same folder holds signatures.txt: every rui_* helper on one line with each keyword it accepts, its default, the allowed values where the set is closed, and its slots. About 23KB, against 55KB for llms.txt. Point an agent at it when it only needs to know which keywords a helper takes. Deprecated keywords are left out, and long value sets are shortened without dropping a value (xl2..xl10).

signatures-full.txt has the same lines plus short descriptions for the most used helpers. Use it when the agent also needs to know what a helper is for. bin/rails rui:signature reads this one.

Inspect a component signature
bin/rails "rui:signature[badge]"
bin/rails "rui:signature[colors]"
bin/rails rui:signature

Prompt Recipes

Four copy-paste starting points. Each is a full request you can hand to Cursor or Claude Code as-is — adjust the specifics, keep the "read llms.txt first" instruction and the component names.

1. Pricing section with rui_card

Prompt
Using RapidRailsUI (read https://rapidrails.cc/llms.txt first), build a pricing
section with 3 rui_card tiers: Starter, Pro, Enterprise. Each card needs:
- an icon slot (with_icon) matching the tier
- a header slot (with_header) with the tier name
- a checklist (with_list / with_item) of 4 features
- a footer CTA (with_footer) linking to /signup

Highlight the Pro tier with variant: :elevated and color: :primary; leave the
other two at their defaults.

Iterate: if the agent reaches for a plain <div> or invents a rui_pricing_card that doesn't exist, it didn't actually load llms.txt — re-paste the URL, or point it straight at https://rapidrails.cc/docs/card with Accept: text/markdown for the canonical slot API.

2. Tabbed section with rui_tabs

Prompt
Using RapidRailsUI (see https://rapidrails.cc/docs/tabs — fetch it with
Accept: text/markdown for the full spec), build a rui_tabs component with 3
tabs: Overview, Pricing, FAQ. Use variant: :spaced, deep_link: true so the
URL hash tracks the active tab, and give the Pricing tab a badge: "New".

Iterate: ask for changes in plain language — "make it vertical with tablist_position: :end" or "switch to :pills and make Overview active by default." A correctly-primed agent edits only the with_tab calls that changed, not the whole block.

3. Form with automatic server-error display

Prompt
Using RapidRailsUI form builder methods (f.rui_input, f.rui_select,
f.rui_textarea) inside form_with(model: @user), build a form for name, email,
and a bio textarea. Do not add manual error-checking code — f.rui_* methods
already detect @user.errors[:field] automatically and render the inline
error styling and message on their own.

Iterate: if the agent adds its own <% if @user.errors[:email].any? %> wrapper around a field, that's the tell it missed the automatic-detection convention. Point it at the "Errors" section of rui_input's USAGE.md and ask it to delete the manual check.

4. Dashboard with rui_stat + rui_table

Prompt
Using RapidRailsUI (read https://rapidrails.cc/llms.txt), build a dashboard
section: 3 rui_stat cards in a row (Total Sales, Active Listings, Conversion
Rate), each with a change: indicator (e.g. change: "+8%"), followed by a
rui_table(sortable: true) showing the 5 most recent listings with sortable
Name, Status, and Created columns.

Iterate: table and link are the two lowest AI-friendliness scores in llms-mini.txt — expect at least one follow-up round for column config. Ask the agent to check rui_table's USAGE.md before guessing at a column option a second time.

Using Your AI Tool

Setup is the same idea everywhere: get the tool to fetch or read llms.txt, then prompt as usual. Specifics per tool:

Cursor

@ → Add docs → paste https://rapidrails.cc/llms.txt. Cursor indexes it once; re-add the URL after a RapidRailsUI upgrade if @docs still generates old syntax (it caches).

Claude Code

No setup step — just reference the URL in your prompt (see the recipes above). Claude Code fetches it live on each session, so there's no stale-cache failure mode to debug.

ChatGPT and tools without URL fetching

Paste the file's contents directly into the first message instead of the URL:

Copy llms.txt to clipboard
curl -s https://rapidrails.cc/llms.txt | pbcopy
# Paste into the chat, then ask your question

Use llms-full.txt instead for a specific component's full detail — it's larger, so only paste it when llms.txt's one-liner genuinely isn't enough.

Claude Desktop, Windsurf, and other MCP-capable tools

Any client that speaks MCP can wire up an llms-txt-mcp server pointed at the same URLs (llms.txt, llms-full.txt) to auto-fetch context per conversation instead of re-pasting it — see that project's own setup docs for the exact config shape for your client.

Troubleshooting

Agent invents a component or wrong argument order

It's working from stale training data instead of the docs. Re-paste the llms.txt URL, or for a single stubborn component, fetch its exact section directly: curl -s https://rapidrails.cc/docs/<component> -H "Accept: text/markdown" and paste that instead — smaller, harder to ignore.

Cursor's @docs won't pick up a new release

Remove and re-add the llms.txt URL in @docs, or restart Cursor — it caches fetched docs content and doesn't re-poll on every message.

JSON/Markdown negotiation returns HTML or 404s

Double-check the Accept header spelling (application/json, not json) and that the component name matches the URL path exactly (e.g. /docs/button_to, not /docs/button-to). A 404 on the Markdown format for a real component means that component's section is missing from llms-full.txt — worth a bug report.

For Stimulus/JS-side issues (controllers not firing, esbuild collisions, etc.) — those aren't AI-specific; see the dedicated Troubleshooting page .