37signals-rails
37signals Rails Best Practices
Comprehensive coding principles and conventions for Ruby on Rails applications, as practiced at 37signals (Basecamp, HEY, Fizzy). Contains 56 rules across 8 categories, prioritized by architectural impact. Derived from official 37signals sources: the Fizzy codebase, STYLE.md, AGENTS.md, the Rails Doctrine, DHH's "On Writing Software Well" series, and the unofficial 37signals style guide (265 Fizzy PRs).
When to Apply
Reference these guidelines when:
- Writing new Rails controllers, models, or views
- Deciding between gems and vanilla Rails
- Modeling state and database schema
- Setting up background jobs, caching, or real-time features
- Reviewing code for 37signals-style conventions
- Refactoring toward rich domain models
- Choosing authentication or authorization approach
- Adding Stimulus controllers or Turbo patterns
Rule Categories by Priority
| Priority | Category | Impact | Prefix |
|---|---|---|---|
| 1 | Architecture Fundamentals | CRITICAL | arch- |
| 2 | Controllers & REST | CRITICAL | ctrl- |
| 3 | Domain Modeling | HIGH | model- |
| 4 | State Management | HIGH | state- |
| 5 | Database & Infrastructure | HIGH | db- |
| 6 | Views & Frontend | MEDIUM | view- |
| 7 | Code Style | MEDIUM | style- |
| 8 | Testing | MEDIUM | test- |
Quick Reference
1. Architecture Fundamentals (CRITICAL)
arch-rich-models- Rich Domain Models Over Service Objectsarch-vanilla-rails- Vanilla Rails is Plentyarch-avoid-patterns- Deliberately Avoided Patterns and Gemsarch-earn-abstractions- Earn Abstractions Through Rule of Threearch-build-before-gems- Build It Yourself Before Reaching for Gemsarch-ship-to-learn- Start Simple — Add Complexity Only After Validationarch-domain-facades- Domain Models as Facades Over Internal Complexityarch-single-business-layer- Single Layer for Business Logicarch-custom-auth- Custom Passwordless Auth Over Devise
2. Controllers & REST (CRITICAL)
ctrl-crud-only- CRUD Controllers Over Custom Actionsctrl-model-as-resources- Model Non-CRUD Operations as Separate Resourcesctrl-thin-controllers- Thin Controllers with Rich Domain Modelsctrl-params-expect- Use params.expect() for Parameter Validationctrl-controller-concerns- Controller Concerns for Cross-Cutting Behaviorctrl-nested-resources- Nested Resources with scope module
3. Domain Modeling (HIGH)
model-concerns- Concerns for Horizontal Code Sharingmodel-normalizes- Use normalizes Macro for Data Cleaningmodel-store-accessor- Use store_accessor for JSON Column Accessmodel-delegated-type- Use delegated_type for Polymorphismmodel-counter-caches- Counter Caches to Prevent N+1 Count Queriesmodel-touch-chains- Touch Chains for Cache Invalidationmodel-callbacks-auxiliary- Callbacks for Auxiliary Complexitymodel-event-tracking- Polymorphic Event Model for Activity Trackingmodel-poro-namespacing- Namespace POROs Under Parent Models
4. State Management (HIGH)
state-records-over-booleans- Records as State Over Boolean Columnsstate-timestamps- Timestamps for State Transitionsstate-enums- Enums for Categorical Statesstate-db-constraints- Database Constraints Over ActiveRecord Validationsstate-write-time- Compute at Write Time Not Read Time
5. Database & Infrastructure (HIGH)
db-backed-everything- Database-Backed Everythingdb-solid-queue- Solid Queue for Background Jobsdb-solid-cable- Solid Cable for Real-Time Pub/Subdb-solid-cache- Solid Cache for Application Cachingdb-multi-tenancy- Path-Based Multi-Tenancy with Current.accountdb-uuid-primary-keys- UUIDs as Primary Keysdb-no-foreign-keys- No Foreign Key Constraints
6. Views & Frontend (MEDIUM)
view-turbo-frames- Turbo Frames for Scoped Page Fragmentsview-turbo-streams- Turbo Streams for Real-Time Updatesview-stimulus-targets- Stimulus Targets Over CSS Selectorsview-stimulus-design- Stimulus Controller Design Principlesview-helpers-not-partials- Extract Logic to Helpers Not Partialsview-progressive-enhancement- Progressive Enhancement as Primary Patternview-fragment-caching- Fragment Caching for View Performanceview-http-caching- HTTP Caching with fresh_when and ETags
7. Code Style (MEDIUM)
style-conditionals- Expanded Conditionals Over Guard Clausesstyle-method-ordering- Methods Ordered by Call Sequencestyle-positive-names- Use Positive Names for Methods and Scopesstyle-naming-return-values- Method Names Reflect Return Valuesstyle-visibility-modifiers- Visibility Modifier Formattingstyle-bang-methods- Bang Methods Only When Non-Bang Existsstyle-async-naming- Use _later and _now Suffixes for Async Operations
8. Testing (MEDIUM)
test-minitest- Minitest Over RSpectest-fixtures- Database Fixtures Over FactoryBottest-no-damage- No Test-Induced Design Damagetest-no-system-tests- Integration Tests Over System Teststest-behavior- Test Behavior Not Implementation
How to Use
Read individual reference files for detailed explanations and code examples:
- Section definitions - Category structure and impact levels
- Rule template - Template for adding new rules
Reference Files
| File | Description |
|---|---|
| references/_sections.md | Category definitions and ordering |
| assets/templates/_template.md | Template for new rules |
| metadata.json | Version and reference information |
More from pproenca/dot-skills
zod
Zod schema validation best practices for type safety, parsing, and error handling. This skill should be used when defining z.object schemas, using z.string validations, safeParse, or z.infer. This skill does NOT cover React Hook Form integration patterns (use react-hook-form skill) or OpenAPI client generation (use orval skill).
2.0Kclean-architecture
Clean Architecture principles and best practices from Robert C. Martin's book. This skill should be used when designing software systems, reviewing code structure, or refactoring applications to achieve better separation of concerns. Triggers on tasks involving layers, boundaries, dependency direction, entities, use cases, or system architecture.
1.4Kemilkowal-animations
Emil Kowalski's animation best practices for web interfaces. Use when writing, reviewing, or implementing animations in React, CSS, or Framer Motion. Triggers on tasks involving transitions, easing, gestures, toasts, drawers, or motion.
923vitest
Vitest testing framework patterns for test setup, async testing, mocking with vi.*, snapshots, and test performance (formerly test-vitest). This skill should be used when writing or debugging Vitest tests. This skill does NOT cover TDD methodology (use test-tdd skill), API mocking with MSW (use test-msw skill), or Jest-specific APIs.
909typescript
This skill should be used when the user asks to "optimize TypeScript performance", "speed up tsc compilation", "configure tsconfig.json", "fix type errors", "improve async patterns", or encounters TS errors (TS2322, TS2339, "is not assignable to"). Also triggers on .ts, .tsx, .d.ts file work involving type definitions, module organization, or memory management. Does NOT cover TypeScript basics, framework-specific patterns, or testing.
824nuqs
nuqs (type-safe URL query state) best practices for Next.js applications. This skill should be used when writing, reviewing, or refactoring code that uses nuqs for URL state management. Triggers on tasks involving useQueryState, useQueryStates, search params, URL state, query parameters, nuqs parsers, or Next.js routing with state.
737