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. |
# 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.
# 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. rui_text(as: :h1, size: :xl) silently ignoring size:. |
| 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.
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
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
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
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
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:
@ → 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).
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.
Paste the file's contents directly into the first message instead of the URL:
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.
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 .