
Dhh Rails Style
Generate or refactor Ruby on Rails code in 37signals/DHH style—fat models, RESTful controllers, Hotwire, and minimal gems.
Overview
dhh-rails-style is an agent skill most often used in Build (also Ship review) that applies 37signals/DHH Rails conventions to models, controllers, and Hotwire-oriented Ruby code.
Install
npx skills add https://github.com/everyinc/compound-engineering-plugin --skill dhh-rails-styleWhat is this skill?
- 37signals philosophy: clarity over cleverness, vanilla Rails is plenty
- Fat models and thin CRUD controllers over service objects and custom actions
- Prefers database-backed queues/cache over Redis; Solid Queue over Sidekiq
- Explicit avoid list: devise, pundit, sidekiq, redis, view_component, GraphQL
- Hotwire/Turbo REST patterns instead of heavy SPA or GraphQL layers
- Documents deliberate avoids for 7+ common gems/patterns (devise, pundit, sidekiq, redis, view_component, GraphQL, etc.)
Adoption & trust: 708 installs on skills.sh; 20.5k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your agent produces generic Rails with service objects, Devise, or Redis patterns that do not match how you want a 37signals-style codebase to look.
Who is it for?
Indie Rails SaaS or internal tools where you want Campfire/Basecamp-like simplicity and REST plus Turbo.
Skip if: Teams standardizing on Devise, Sidekiq, Pundit, or GraphQL who will not adopt the avoid list.
When should I use this skill?
Writing Ruby/Rails code, refactoring, code review, or when user mentions DHH, 37signals, Basecamp, HEY, or Campfire style.
What do I get? / Deliverables
Ruby and Rails artifacts follow DHH conventions—CRUD controllers, fat models, database-backed infra choices, and avoided gem patterns—so the codebase stays coherent.
- Rails code matching DHH conventions
- Refactored models/controllers/concerns
- Style-aligned review notes
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Rails application structure and domain modeling are primary build-backend concerns even when Hotwire touches the UI. Backend subphase is the canonical shelf for models, controllers, concerns, and DB-backed patterns that define the product core.
Where it fits
Scaffold a new resource with CRUD controllers and domain logic on the model.
Shape Hotwire/Turbo views and controller responses without a separate SPA layer.
Review a PR for forbidden gems or service-object creep against 37signals rules.
How it compares
Opinionated style skill—not RuboCop alone and not a replacement for Rails security or test suites.
Common Questions / FAQ
Who is dhh-rails-style for?
Rails solo builders who explicitly want 37signals/DHH patterns in generated and reviewed code.
When should I use dhh-rails-style?
During build when creating models and controllers, when refactoring Ruby, or during ship review when the user mentions DHH, Basecamp, HEY, or Campfire style.
Is dhh-rails-style safe to install?
Review the Security Audits panel on this Prism page; the skill is editorial/procedural and does not require network access by itself.
SKILL.md
READMESKILL.md - Dhh Rails Style
<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? 1. **Controllers** - REST mapping, concerns, Turbo responses, API patterns 2. **Models** - Concerns, state records, callbacks, scopes, POROs 3. **Views & Frontend** - Turbo, Stimulus, CSS, partials 4. **Architecture** - Routing, multi-tenancy, authentication, jobs, caching 5. **Testing** - Minitest, fixtures, integration tests 6. **Gems & Dependencies** - What to use vs avoid 7. **Code Review** - Review code against DHH style 8. **General Guidance** - Philosophy and conventions **Specify a number or describe your task.** </intake> <routing> | Response | Reference to Read | |----------|-------------------| | 1, controller | `references/controllers.md` | | 2, model | `references/models.md` | | 3, view, frontend, turbo, stimulus, css | `references/frontend.md` | | 4, architecture, routing, auth, job, cache | `references/architecture.md` | | 5, test, testing, minitest, fixture | `references/testing.md` | | 6, gem, dependency, library | `references/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