Use when writing ERB templates, partials, or view helpers - covers partial organization, optional locals, CSS class patterns, and collection rendering with caching
From vanilla-railsnpx claudepluginhub zemptime/zemptime-marketplace --plugin vanilla-railsThis skill uses the workspace's default tool permissions.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Enables AI agents to execute x402 payments with per-task budgets, spending controls, and non-custodial wallets via MCP tools. Use when agents pay for APIs, services, or other agents.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
ERB conventions for vanilla Rails applications.
Lowest common ancestor — place partials at the highest shared directory:
app/views/cards/_card.html.erb # Shared by cards/show and cards/index
app/views/application/_flash.html.erb # Shared across controllers
app/views/cards/display/_compact.html.erb # Display variants
Never create deeply nested partials only used in one place.
Use local_assigns.fetch with explicit defaults:
<% pinned = local_assigns.fetch(:pinned, false) %>
<% card = local_assigns.fetch(:card) %> <%# raises if missing %>
Not local_assigns[:x] || default (silent nil, ambiguous intent).
Build classes with array + compact + join:
<div class="<%= [
'card',
('card--pinned' if card.pinned?),
('card--closed' if card.closed?)
].compact.join(' ') %>">
For complex cases: <div class="<%= token_list('card', 'card--pinned': card.pinned?) %>">
Always cache, always specify as::
<%= render partial: 'cards/card', collection: @cards, as: :card, cached: true %>
Prepend/append with update for empty states:
<%= turbo_stream.before :cards, @card %>
<%= turbo_stream.update :cards_count, @cards.count %>
<%= turbo_stream.remove @card %>
See vanilla-rails-hotwire for dom_id, morph, and Stimulus patterns.
Layer controllers on existing elements, don't add wrapper divs:
<body data-controller="keyboard shortcuts dropdown">
| Pattern | Use |
|---|---|
local_assigns.fetch(:x, default) | Optional locals |
[...].compact.join(' ') | Conditional CSS classes |
cached: true, as: :item | Collection rendering |
turbo_stream.before + .update | Add + refresh related |
| Wrong | Right |
|---|---|
local_assigns[:x] || default | local_assigns.fetch(:x, default) |
| Wrapper div for Stimulus | Add controller to existing element |
render @cards without cache | render collection:, cached: true |
| Partial in deep nested path | Lowest common ancestor |