plugins/lavra/skills/optional/dhh-rails-style/SKILL.md
Write Ruby and Rails code in DHH's 37signals style. Use for Rails apps, models, controllers, or when DHH/Basecamp/Hotwire conventions are requested.
npx skillsauth add roberto-mello/beads-compound-plugin dhh-rails-styleInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
<essential_principles>
"The best code is the code you don't write. The second best is the code that's obviously correct."
Vanilla Rails is plenty:
What they deliberately avoid:
Development Philosophy:
Specify a number or describe your task. </intake>
<routing>| Response | Reference to Read | |----------|-------------------| | 1, controller | controllers.md | | 2, model | models.md | | 3, view, frontend, turbo, stimulus, css | frontend.md | | 4, architecture, routing, auth, job, cache | architecture.md | | 5, test, testing, minitest, fixture | testing.md | | 6, gem, dependency, library | gems.md | | 7, review | Read all references, then review code | | 8, general task | Read relevant references based on context |
After reading relevant references, apply patterns to the user's code. </routing>
<quick_reference>
Verbs: card.close, card.gild, board.publish (not set_style methods)
Predicates: card.closed?, card.golden? (derived from presence of related record)
Concerns: Adjectives describing capability (Closeable, Publishable, Watchable)
Controllers: Nouns matching resources (Cards::ClosuresController)
Scopes:
chronologically, reverse_chronologically, alphabetically, latestpreloaded (standard eager loading name)indexed_by, sorted_by (parameterized)active, unassigned (business terms, not SQL-ish)Instead of custom actions, create new resources:
POST /cards/:id/close → POST /cards/:id/closure
DELETE /cards/:id/close → DELETE /cards/:id/closure
POST /cards/:id/archive → POST /cards/:id/archival
# Symbol arrays with spaces inside brackets
before_action :set_message, only: %i[ show edit update destroy ]
# Private method indentation
private
def set_message
@message = Message.find(params[:id])
end
# Expression-less case for conditionals
case
when params[:before].present?
messages.page_before(params[:before])
else
messages.last_page
end
# Bang methods for fail-fast
@message = Message.create!(params)
# Ternaries for simple conditionals
@room.direct? ? @room.users : @message.mentionees
State as Records:
Card.joins(:closure) # closed cards
Card.where.missing(:closure) # open cards
Current Attributes:
belongs_to :creator, default: -> { Current.user }
Authorization on Models:
class User < ApplicationRecord
def can_administer?(message)
message.creator == self || admin?
end
end
</quick_reference>
<reference_index>
All detailed patterns in references/:
| File | Topics | |------|--------| | controllers.md | REST mapping, concerns, Turbo responses, API patterns, HTTP caching | | models.md | Concerns, state records, callbacks, scopes, POROs, authorization, broadcasting | | frontend.md | Turbo Streams, Stimulus controllers, CSS layers, OKLCH colors, partials | | architecture.md | Routing, authentication, jobs, Current attributes, caching, database patterns | | testing.md | Minitest, fixtures, unit/integration/system tests, testing patterns | | gems.md | What they use vs avoid, decision framework, Gemfile examples | </reference_index>
<success_criteria> Code follows DHH style when:
Important Disclaimers:
tools
Execute work on one or many beads -- auto-routes between single-bead, sequential, and multi-bead parallel paths based on input
tools
Single-bead implementation path for lavra-work, phases 1-5. Invoked by lavra-work router. Use when working on exactly one bead.
tools
Multi-bead orchestration path (Phases M1-M10) — invoked by lavra-work router. Use when working on multiple beads in parallel.
tools
Capture solved problems as knowledge entries for fast recall. Use when a solution should be preserved for future sessions.