Dhh Rails Style
VerifiedThis skill should be used when writing Ruby and Rails code in DHH's distinctive 37signals style. It applies when writing Ruby code, Rails applications, creat...
$ Add to .claude/skills/ About This Skill
<objective> Apply 37signals/DHH Rails conventions to Ruby and Rails code. This skill provides comprehensive domain expertise extracted from analyzing production 37signals codebases (Fizzy/Campfire) and DHH's code review patterns. </objective>
<essential_principles> ## Core Philosophy
"The best code is the code you don't write. The second best is the code that's obviously correct."
- Vanilla Rails is plenty:
- Rich domain models over service objects
- CRUD controllers over custom actions
- Concerns for horizontal code sharing
- Records as state instead of boolean columns
- Database-backed everything (no Redis)
- Build solutions before reaching for gems
- What they deliberately avoid:
- devise (custom ~150-line auth instead)
- pundit/cancancan (simple role checks in models)
- sidekiq (Solid Queue uses database)
- redis (database for everything)
- view_component (partials work fine)
- GraphQL (REST with Turbo sufficient)
- factory_bot (fixtures are simpler)
- rspec (Minitest ships with Rails)
- Tailwind (native CSS with layers)
- Development Philosophy:
- Ship, Validate, Refine - prototype-quality code to production to learn
- Fix root causes, not symptoms
- Write-time operations over read-time computations
- Database constraints over ActiveRecord validations
- </essential_principles>
<intake> What are you working on?
- Controllers - REST mapping, concerns, Turbo responses, API patterns
- Models - Concerns, state records, callbacks, scopes, POROs
- Views & Frontend - Turbo, Stimulus, CSS, partials
- Architecture - Routing, multi-tenancy, authentication, jobs, caching
- Testing - Minitest, fixtures, integration tests
- Gems & Dependencies - What to use vs avoid
- Code Review - Review code against DHH style
- General Guidance - Philosophy and conventions
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> ## Naming Conventions
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`, `latest`
- `preloaded` (standard eager loading name)
- `indexed_by`, `sorted_by` (parameterized)
- `active`, `unassigned` (business terms, not SQL-ish)
REST Mapping
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 ```
Ruby Syntax Preferences
```ruby # 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 ```
Key Patterns
State as Records: ```ruby Card.joins(:closure) # closed cards Card.where.missing(:closure) # open cards ```
Current Attributes: ```ruby belongs_to :creator, default: -> { Current.user } ```
Authorization on Models: ```ruby class User < ApplicationRecord def can_administer?(message) message.creator == self || admin? end end ``` </quick_reference>
<reference_index> ## Domain Knowledge
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:
- Controllers map to CRUD verbs on resources
- Models use concerns for horizontal behavior
- State is tracked via records, not booleans
- No unnecessary service objects or abstractions
- Database-backed solutions preferred over external services
- Tests use Minitest with fixtures
- Turbo/Stimulus for interactivity (no heavy JS frameworks)
- Native CSS with modern features (layers, OKLCH, nesting)
- Authorization logic lives on User model
- Jobs are shallow wrappers calling model methods
- </success_criteria>
<credits> Based on The Unofficial 37signals/DHH Rails Style Guide by Marc Köhlbrugge, generated through deep analysis of 265 pull requests from the Fizzy codebase.
- Important Disclaimers:
- LLM-generated guide - may contain inaccuracies
- Code examples from Fizzy are licensed under the O'Saasy License
- Not affiliated with or endorsed by 37signals
- </credits>
Use Cases
- Write Ruby on Rails code following DHH's opinionated coding conventions
- Apply Rails-way patterns: convention over configuration, RESTful design, and fat models
- Review Rails code for style violations against DHH's established preferences
- Scaffold Rails applications that follow the Basecamp/37signals development philosophy
- Maintain consistent Rails coding style across a team using DHH's principles
Pros & Cons
Pros
- +Well-defined, opinionated style guide eliminates debates about coding conventions
- +DHH's patterns are battle-tested in large-scale Rails applications at Basecamp
- +Convention-over-configuration philosophy reduces boilerplate and decision fatigue
Cons
- -Highly opinionated — may conflict with teams that prefer different Rails conventions
- -Only available on claude-code and openclaw platforms
- -Rails-specific — not applicable to other web frameworks
FAQ
What does Dhh Rails Style do?
What platforms support Dhh Rails Style?
What are the use cases for Dhh Rails Style?
100+ free AI tools
Writing, PDF, image, and developer tools — all in your browser.
Next Step
Use the skill detail page to evaluate fit and install steps. For a direct browser workflow, move into a focused tool route instead of staying in broader support surfaces.