Skip to main content

ce-dhh-rails-style

A skill from Every's compound-engineering plugin that writes Ruby and Rails in DHH's 37signals style — REST purity, fat models and thin controllers, `Current` attributes, Hotwire over heavy JS, and 'clarity over cleverness.' It deliberately rejects devise, pundit, sidekiq, and rspec in favor of vanilla Rails: ~150 lines of custom auth on the User model, Solid Queue for jobs, and Minitest for tests.

Write Rails code the way Basecamp, HEY, and Campfire do — vanilla framework, rich domain models, no gem sprawl

Source Every
License MIT
First documented
Receipts TODO

Trigger phrases

Phrases that activate this skill when typed to Claude Code:

  • write this Rails code in DHH style
  • 37signals conventions for this model
  • should this be a service object or a fat model

What it does

ce-dhh-rails-style applies the 37signals / DHH coding philosophy to Ruby on Rails — see skills/ce-dhh-rails-style in Every’s compound-engineering plugin. Use it when writing Rails, refactoring existing code toward that style, or settling a convention debate. It enforces a distinctive set of conventions: REST purity (map resources, don’t invent custom controller actions), fat models and thin controllers, database-backed state records instead of boolean columns, Current attributes, Hotwire (Turbo / Stimulus) over heavy JS frameworks, native modern CSS, and authorization logic placed directly on the User model. The throughline is “clarity over cleverness” and “the best code is the code you don’t write.”

It is as opinionated about what to avoid as what to do. It rejects popular gems — devise, pundit, sidekiq, rspec — in favor of vanilla Rails: roughly 150 lines of custom auth, Solid Queue for background jobs, Minitest for testing, and rich domain models instead of service objects. It routes to detailed reference files covering controllers, models, frontend patterns, architecture, testing, and gem decisions, so the rules come with worked examples rather than slogans.

When to use it

  • Writing or refactoring Rails code that should read like Basecamp / HEY / Campfire
  • Settling a “service object vs. fat model” or “do we add devise” debate against a coherent philosophy
  • Code review on a Rails PR — does this reach for a gem where vanilla Rails would do?
  • Onboarding an agent to a 37signals-style codebase so its generated code matches house style

When not to reach for it:

  • Non-Rails Ruby, or Rails apps whose team has deliberately chosen a different stack (heavy SPA front end, an RSpec shop) — the skill will fight your conventions
  • When a gem the skill rejects is genuinely load-bearing in your app — it’s opinionated, not situational
  • Greenfield non-web Ruby where the Rails idioms don’t apply

Install

Part of the compound-engineering plugin (not a standalone ~/.claude/skills/ drop-in). In Claude Code:

/plugin marketplace add EveryInc/compound-engineering-plugin
/plugin install compound-engineering

Then invoke /ce-dhh-rails-style while writing or reviewing Rails code. The plugin namespaces every skill with ce-. MIT-licensed.

What a session looks like

  1. Ask for a feature. “Add the ability to archive a project.”
  2. REST purity. Instead of ProjectsController#archive, model it as a resource: Projects::ArchivesController#create.
  3. State as a record. Rather than project.archived = true, create an Archival record (who archived it, when) — a database-backed state record, not a boolean column.
  4. Fat model. The archiving logic lives on the Project / Archival models; the controller stays thin.
  5. Auth on User. user.can_archive?(project) lives on the model, not in a pundit policy.
  6. Frontend. A Turbo Stream updates the project card in place and a Stimulus controller handles the toggle — no React.
  7. Jobs and tests. Any async work goes to Solid Queue; the test is Minitest, not RSpec.

The discipline that makes it work: “the best code is the code you don’t write.” On every choice the skill’s instinct is to reach for a built-in Rails primitive before a gem or a new abstraction.

Receipts

TODO — to be filled in from a real session. Once the skill has been run on a real Rails feature, this section will capture: which convention generated the most friction against an existing non-DHH codebase, whether the gem-rejection rules (no devise / pundit / sidekiq / rspec) were practical or dogmatic on a real feature, how the ~150-line custom auth compared to reaching for devise, and whether “state record instead of boolean” actually paid off or just added a table.

Source and attribution

From Every’s compound-engineering plugin — the MIT-licensed plugin (Dan Shipper & Kieran Klaassen) packaging Every’s engineering workflow.

License: MIT.

Quoting the governing rule verbatim: “The best code is the code you don’t write.” Every convention in the skill — REST resources over custom actions, vanilla Rails over gems, fat models over service objects — is an application of that one line.