layered-rails
Design Rails applications using layered architecture. Use when analyzing codebases for architecture violations, planning feature implementations, deciding where code belongs, or extracting abstractions from fat models/controllers. Complements dhh-coder (which keeps things simple) with guidance for when complexity demands structure.
What this skill does
# Layered Rails Architecture
**Audience:** Rails developers working on applications that have outgrown single-file patterns.
**Goal:** Know which layer code belongs in, when to extract, and which existing skill handles the implementation.
## Four-Layer Architecture
```
Presentation → Application → Domain → Infrastructure
(HTTP/UI) (Orchestration) (Business) (Persistence/APIs)
```
**Core rule:** Lower layers MUST NOT depend on higher layers. Data flows top-to-bottom only.
### Layer Responsibilities
| Layer | Owns | Does NOT Own |
|-------|------|-------------|
| **Presentation** | HTTP concerns, params, rendering, channels, mailers | Business logic, direct DB queries |
| **Application** | Orchestration across models, authorization, form validation | Persistence details, rendering |
| **Domain** | Business rules, validations, associations, value objects | HTTP context, request objects, `Current.*` |
| **Infrastructure** | ActiveRecord, external APIs, file storage, caching | Business rules, presentation |
### Common Layer Violations
| Violation | Why It's Wrong | Fix |
|-----------|---------------|-----|
| `Current.user` in model | Domain depends on presentation context | Pass user as explicit parameter |
| `request` param in service | Application depends on presentation | Extract needed values before calling service |
| Pricing calc in controller | Business logic in presentation | Move to model method or service |
| All logic in services, anemic models | Domain layer is hollow | Keep domain logic in models; services orchestrate |
| Model sends emails directly | Domain depends on infrastructure side-effects | Use callbacks only for data transforms; extract delivery |
## The Specification Test
Diagnostic for misplaced code:
1. List every responsibility the object handles
2. For each, ask: "Does this belong to this layer's primary concern?"
3. If NO → extract to the appropriate layer
**Example:** A `User` model that handles authentication, avatar processing, notification preferences, and activity logging.
- Authentication → Domain (keep)
- Avatar processing → Infrastructure (extract to service/job)
- Notification preferences → Domain (keep as concern)
- Activity logging → Infrastructure (extract to observer/event)
See [references/extraction-signals.md](references/extraction-signals.md) for the full methodology.
## Callback Scoring
Rate each callback 1-5. Extract anything scoring 1-2.
| Score | Type | Example | Action |
|-------|------|---------|--------|
| 5 | Transformer | `before_validation :normalize_email` | Keep |
| 4 | Normalizer | `before_save :strip_whitespace` | Keep |
| 4 | Utility | `after_create :update_counter_cache` | Keep |
| 2 | Observer | `after_save :notify_admin` | Consider extracting |
| 1 | Operation | `after_create :send_welcome_email, :provision_account` | Extract |
**Rule of thumb:** If removing the callback would break the model's own data integrity → keep. If it triggers external side-effects → extract.
## Pattern Selection
**"Where should this code go?"**
| Situation | Pattern | Layer | Skill |
|-----------|---------|-------|-------|
| Complex multi-model form | Form Object | Presentation | — |
| Request param filtering | Filter Object | Presentation | — |
| View-specific formatting | Presenter / ViewComponent | Presentation | `viewcomponent-coder` |
| Authorization rules | Policy Object | Application | `action-policy-coder` |
| Business operation (one-time) | Service / Interaction | Application | `active-interaction-coder` |
| Multi-model orchestration | Service Object | Application | `active-interaction-coder` |
| State lifecycle management | State Machine | Domain | `aasm-coder` |
| Complex reusable query | Query Object | Domain | — |
| Immutable concept (Money, DateRange) | Value Object | Domain | — |
| Shared model behavior | Concern | Domain | — |
| Typed configuration | Config Object | Infrastructure | `anyway-config-coder` |
| Domain events / audit trail | Event Sourcing | Infrastructure | `event-sourcing-coder` |
| JSON-backed attributes | Store Model | Domain | `store-model-coder` |
### Decision Tree
```
Is it about HTTP/params/rendering?
YES → Presentation layer
Multi-model form? → Form Object
Filtering params? → Filter Object
Formatting for view? → Presenter or ViewComponent
NO ↓
Is it authorization?
YES → Policy Object (action-policy-coder)
NO ↓
Does it orchestrate multiple models/services?
YES → Application layer
One-time operation? → Service/Interaction (active-interaction-coder)
Needs typed inputs? → ActiveInteraction (active-interaction-coder)
NO ↓
Is it a business rule about a single model?
YES → Domain layer (keep in model or concern)
Has state transitions? → AASM (aasm-coder)
Reusable query? → Query Object
Immutable value? → Value Object
NO ↓
Is it about persistence/external APIs/caching?
YES → Infrastructure layer
```
## Services as Waiting Rooms
`app/services/` is a **temporary staging area**, not a permanent home.
- Services that survive should eventually reveal the real abstraction they represent
- If a service wraps a single model operation → it probably belongs in the model
- If a service coordinates 3+ models → it's a legitimate orchestrator
- If a service grows complex → look for Form Object, Policy, or Query Object hiding inside
**Smell test:** If `app/services/` has 50+ files and no subdirectories, the waiting room has become permanent storage.
## Extraction Signals
When to extract code from existing locations:
| Signal | Threshold | Action |
|--------|-----------|--------|
| Method length | > 15 lines | Extract method or object |
| External API call in model | Any | Extract to service/gateway |
| God object | High churn × high complexity | Decompose (see [references/extraction-signals.md](references/extraction-signals.md)) |
| Spec exceeds layer concern | Specification test fails | Extract to appropriate layer |
| Callback score | 1-2/5 | Extract to service or event handler |
| Duplicated query logic | 2+ locations | Extract Query Object |
| `Current.*` in model | Any usage | Pass as explicit parameter |
See [references/extraction-signals.md](references/extraction-signals.md) for the complete methodology.
## Model Organization
Recommended ordering within model files:
```ruby
class Order < ApplicationRecord
# 1. Extensions/DSL (has_secure_password, acts_as_*)
# 2. Associations
# 3. Enums
# 4. Normalizations
# 5. Validations
# 6. Scopes
# 7. Callbacks (transformers/normalizers only — score 4-5)
# 8. Delegations
# 9. Public methods
# 10. Private methods
end
```
## When Layered vs DHH Style
This skill complements `dhh-coder`, not replaces it.
| Situation | Use |
|-----------|-----|
| Small/medium app, standard CRUD | `dhh-coder` — keep it simple |
| Complex domain, multiple bounded contexts | `layered-rails` — add structure |
| Authorization beyond simple checks | `action-policy-coder` via layered guidance |
| Fat model with 500+ lines | `layered-rails` extraction signals |
| Standard controller actions | `dhh-coder` — 7 REST actions |
| Multi-step business operation | `active-interaction-coder` via layered guidance |
**Default to simplicity.** Reach for layered patterns only when complexity demands it.
## Success Checklist
- [ ] No reverse dependencies (lower layers don't reference higher)
- [ ] Models don't access `Current` attributes
- [ ] Services don't accept request/controller objects
- [ ] Controllers contain only HTTP concerns
- [ ] Domain logic lives in models, not leaked into services
- [ ] All callbacks score 4+ (or extracted)
- [ ] Concerns group by behavior, not by artifact type
- [ ] Each abstraction belongs to exactly one layer
## Cross-References
| Need | Skill |
|------|-------|
| Authorization policies | `action-policy-coder` |
| Typed business operations | `active-interaction-coder` |
| State machines | `aasm-coder` |
| Operations + state routing | `buRelated in Design
contribute
IncludedLocal-only OSS contribution command center. Auto-refreshes the user's in-flight PR and issue state on invoke so conversations start with full context — no need to brief Claude on what's in flight. Helps the user find issues to contribute to on GitHub, builds per-repo dossiers of what each upstream expects (CLA, DCO, branch convention, AI policy, draft-first, review bots, issue templates), runs deterministic gates before any external action so AI-assisted contributions don't reach maintainers as slop. State is markdown-only: candidate files at ~/.contribute-system/candidates/, repo dossiers at ~/.contribute-system/research/, append-only event log at ~/.contribute-system/log.jsonl. No database, no cloud calls. Use when the user asks about their PRs / issues / contributions, wants to find new work to take on, claim an issue, build/refresh a repo's dossier, or draft a Design Issue or PR. Trigger with "/contribute", "what's my PR status", "find a contribution", "claim issue X", "draft a Design Issue for Y", "refresh dossier for Z".
architectural-analysis
IncludedUser-triggered deep architectural analysis of a codebase or scoped subtree across eight modes — information architecture, data flow, integration points, UI surfaces, interaction patterns, data model, control flow, and failure modes. This skill should be used when the user asks to "diagram this codebase," "map the architecture," "show the data flow," "give me an ERD," "trace control flow," "find the integration points," "verify the layout pattern," "audit the UX architecture," or any similar request whose primary deliverable is mermaid diagrams plus cited reports under docs/architecture/. Dispatches haiku/sonnet sub-agents in parallel for per-mode exploration, then verifies every citation mechanically before any node lands in a diagram. Not for one-off prose explanations of code (use code-explanation) or for high-level system design from scratch (use system-design).
mcp
IncludedModel Context Protocol (MCP) server development and tool management. Languages: Python, TypeScript. Capabilities: build MCP servers, integrate external APIs, discover/execute MCP tools, manage multi-server configs, design agent-centric tools. Actions: create, build, integrate, discover, execute, configure MCP servers/tools. Keywords: MCP, Model Context Protocol, MCP server, MCP tool, stdio transport, SSE transport, tool discovery, resource provider, prompt template, external API integration, Gemini CLI MCP, Claude MCP, agent tools, tool execution, server config. Use when: building MCP servers, integrating external APIs as MCP tools, discovering available MCP tools, executing MCP capabilities, configuring multi-server setups, designing tools for AI agents.
react-native-skia
IncludedDesign, build, debug, and optimise high-polish animated graphics in React Native or Expo using @shopify/react-native-skia, Reanimated, and Gesture Handler. Use when the user wants canvas-driven UI, shaders, paths, rich text, image filters, sprite fields, Skottie, video frames, snapshots, web CanvasKit setup, or performance tuning for custom motion-heavy elements such as loaders, hero art, cards, charts, progress indicators, particle systems, or gesture-driven surfaces. Also use when the user asks for fluid, glow, glass, blob, parallax, 60fps/120fps, or GPU-friendly animated effects in React Native, even if they do not explicitly say "Skia". Do not use for ordinary form/layout work with standard views.
plaid
IncludedProduct Led AI Development — guides founders from idea to launched product. Six capabilities: Idea (discover a product idea), Validate (pressure-test the idea against fatal flaws, problem reality, competition, and 2-week MVP feasibility), Plan (vision intake + document generation), Design (translate image references into a design.md spec), Launch (go-to-market strategy), and Build (roadmap execution). Use when someone says "PLAID", "plaid idea", "help me find an idea", "product idea", "idea from my business", "idea from my expertise", "plaid validate", "validate my idea", "pressure-test", "is this idea good", "find fatal flaws", "validate the problem", "plan a product", "define my vision", "generate a PRD", "product strategy", "plaid design", "design from image", "translate image to design", "create design.md", "extract design tokens", "plaid launch", "go-to-market", "launch plan", "GTM strategy", "launch playbook", "plaid build", "build the app", "start building", or "execute the roadmap".
nextjs-framer-motion-animations
IncludedAdds production-safe Motion for React or Framer Motion animations to Next.js apps, including reveal, hover and tap micro-interactions, whileInView, stagger, AnimatePresence, layout and layoutId transitions, reorder, scroll-linked UI, and lightweight route-content transitions. Use when the user asks to add, refactor, or debug Motion or Framer Motion in App Router or Pages Router codebases, especially around server/client boundaries, reduced motion, LazyMotion, bundle size, hydration, or route transitions. Avoid for GSAP-style timelines, WebGL or 3D scenes, heavy scroll storytelling, or CSS-only effects unless Motion is explicitly requested.