
Rails generators that produce standalone application code. No runtime dependency — generate once, own the code forever. Delete the gem when you're done.

---

## What Is This?

After `rails new`, every developer follows the same steps: configure authentication, set up request throttling, wire up a job queue, add error tracking. These steps aren't gaps in the framework — they're workflow choices that are repetitive and time-consuming.

Maquina Generators make the post-`rails new` setup as deterministic as the framework itself. The gem is development-only. Everything it produces lives in your app and is yours to modify.

```bash
rails new myapp --css tailwind
bundle add maquina-generators --group development
rails generate maquina:app --auth clave
bin/rails db:migrate
bin/dev
```

Five commands. Auth, multi-tenancy, roles, job queue, error tracking, request protection — all generated, all yours.

![Generated app homepage showing authentication, background jobs, error tracking, rate limiting, caching, and real-time features](/images/blog/generators-screenshot-1.png)

---

## Quick Start

### 1. Create a Rails App

```bash
rails new myapp --css tailwind
cd myapp
```

### 2. Add the Gem

```bash
bundle add maquina-generators --group development
```

### 3. Run the App Generator

```bash
rails generate maquina:app --auth registration
```

### 4. Finish Setup

```bash
bin/rails db:migrate
bin/rails credentials:edit
# Add: backstage: { username: admin, password: your_password }
bin/dev
```

---

## Available Generators

| Generator | Command | Purpose |
|-----------|---------|---------|
| **App** | `rails g maquina:app` | Full application setup (orchestrator) |
| **Clave** | `rails g maquina:clave` | Passwordless email-code authentication |
| **Registration** | `rails g maquina:registration` | Password-based auth with accounts and roles |
| **Rack Attack** | `rails g maquina:rack_attack` | Request protection and IP throttling |
| **Solid Queue** | `rails g maquina:solid_queue` | Background job processing |
| **Solid Errors** | `rails g maquina:solid_errors` | Error tracking dashboard |
| **Mission Control** | `rails g maquina:mission_control_jobs` | Job queue monitoring dashboard |

---

## The App Generator

The orchestrator. Runs after `rails new` and configures a complete, production-ready application in a single command.

```bash
rails g maquina:app --auth clave --prefix /admin --port 3000
```

### What It Does

1. **Adds gems** — brakeman, standard, rails-i18n, maquina-components, aws-sdk-s3
2. **Creates configs** — Procfile.dev, .rubocop.yml, .standard.yml
3. **Configures environments** — letter_opener for dev, APPLICATION_HOST for production
4. **Installs Rails features** — Action Text, Active Storage, Turbo morphing
5. **Runs auth generator** — your choice of clave, registration, or none
6. **Runs sub-generators** — rack_attack, solid_queue, mission_control_jobs, solid_errors
7. **Installs Solid adapters** — Solid Queue, Solid Cache, Solid Cable, Solid Errors
8. **Installs Maquina Components** — UI library ready to use
9. **Creates HomeController** — with root route
10. **Sets up multi-database** — primary, queue, cache, cable, errors

### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--auth` | `none` | Authentication: `none`, `clave`, or `registration` |
| `--prefix` | `/admin` | URL prefix for ops dashboards |
| `--port` | `3000` | Development server port |

### Generated Database Configuration

```yaml
development:
  primary:
    database: storage/development.sqlite3
  queue:
    database: storage/development_queue.sqlite3
  cache:
    database: storage/development_cache.sqlite3
  cable:
    database: storage/development_cable.sqlite3
  errors:
    database: storage/development_errors.sqlite3
```

---

## Authentication: Clave (Passwordless)

Complete passwordless authentication using email verification codes. Users receive a 6-digit code via email to sign in — no passwords to manage, no password resets to build.

```bash
rails g maquina:clave
```

### What You Get

**Models:**
- `Account` — multi-tenant container (`has_many :users`)
- `User` — with role enum (member/admin), account association, blocking support
- `Session` — browser session tracking with IP and user agent
- `EmailVerification` — verification codes with expiry and attempt tracking
- `Current` — `ActiveSupport::CurrentAttributes` with session, user, and account

**Controllers:**
- `SessionsController` — email entry for sign-in
- `Session::VerificationsController` — code verification
- `Session::VerificationResendsController` — resend with 15-minute cooldown
- `RegistrationsController` — account creation (optional)
- Registration verification controllers

**Additional:**
- `VerificationMailer` — HTML + text email templates
- `AuthenticationCleanupJob` — daily cleanup of expired sessions and codes
- `SessionTestHelper` — `sign_in_as(user)` and `sign_out` for tests
- Full i18n support (English and Spanish)

### How It Works

```
User enters email → receives 6-digit code → enters code → signed in
```

- Codes expire in 15 minutes
- 15-minute cooldown before resend
- Rate limited: 10 attempts per 3 minutes
- Sessions last 30 days (configurable)
- `+` characters blocked in emails to prevent alias attacks

### Multi-Tenancy

Every user belongs to an Account. The first user who creates an account becomes its admin.

```ruby
# Access anywhere in your app
Current.user          # The signed-in user
Current.account       # The user's account
Current.user.admin?   # Check role
```

### Scoping Queries

```ruby
class ProjectsController < ApplicationController
  def index
    @projects = Current.account.projects
  end

  def create
    @project = Current.account.projects.build(project_params)
    # ...
  end

  private

  def set_project
    @project = Current.account.projects.find(params[:id])
  end
end
```

### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--skip-views` | `false` | Skip view templates |
| `--skip-registration` | `false` | Skip sign-up flow (sign-in only) |

---

## Authentication: Registration (Password-Based)

Password-based authentication that builds on Rails 8's built-in `rails generate authentication`. Adds multi-tenancy with an Account model, user roles, and a registration flow.

```bash
rails g maquina:registration
```

### What It Adds to Rails Auth

Rails 8's authentication generator gives you login but no signup. Registration adds:

- `Account` model with `has_many :users`
- User gains `belongs_to :account` and role enum (admin/member)
- `Current.account` delegation
- `RegistrationsController` — creates Account + User in a single transaction
- Tailwind-styled views
- English and Spanish translations

### Generated Models

```ruby
class Account < ApplicationRecord
  has_many :users, dependent: :destroy
  validates :name, presence: true
end

class User < ApplicationRecord
  has_secure_password
  has_many :sessions, dependent: :destroy
  belongs_to :account
  validates :name, presence: true
  enum :role, { member: "member", admin: "admin" }, default: "member"
end

class Current < ActiveSupport::CurrentAttributes
  attribute :session
  delegate :user, to: :session, allow_nil: true
  delegate :account, to: :user, allow_nil: true
end
```

### Registration Flow

```ruby
class RegistrationsController < ApplicationController
  allow_unauthenticated_access
  rate_limit to: 10, within: 3.minutes, only: :create

  def create
    ActiveRecord::Base.transaction do
      account = Account.create!(name: params[:account_name])
      user = account.users.create!(
        name: params[:name],
        email_address: params[:email_address],
        password: params[:password],
        role: :admin
      )
    end
    start_new_session_for user
    redirect_to root_path
  end
end
```

### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--skip-views` | `false` | Skip view templates |

---

## Rack Attack

Request protection with sensible defaults. Blocks common attack vectors and throttles abusive requests.

```bash
rails g maquina:rack_attack
```

### Default Protections

**Blocklists:**
- PHP files and WordPress paths
- Sensitive files (`.env`, `.git`, `.aws`, `.ssh`)
- Scanner targets (`/cgi-bin`, `/phpmyadmin`, `/actuator`, `/debug`)

**Throttles:**
- General: 300 requests per 5 minutes per IP (assets exempt)
- Login: 5 attempts per 20 seconds per IP

**Safelists:**
- Localhost (127.0.0.1, ::1)

All rules live in `config/initializers/rack_attack.rb`. Edit directly.

---

## Solid Queue

Sets up Solid Queue as your Active Job backend with a separate database and Procfile integration.

```bash
rails g maquina:solid_queue --database sqlite3
```

### Configuration

```yaml
# config/solid_queue.yml
default: &default
  dispatchers:
    - polling_interval: 1
      batch_size: 500
  workers:
    - queues: "*"
      threads: 3
      polling_interval: 0.1
  recurring:
    authentication_cleanup:
      class: AuthenticationCleanupJob
      schedule: every day at 3am
```

### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--database` | `sqlite3` | Database adapter (`sqlite3` or `postgresql`) |

---

## Solid Errors

Error tracking dashboard with custom Tailwind views and HTTP basic auth.

```bash
rails g maquina:solid_errors --prefix /admin
```

### What You Get

- Custom Tailwind-styled error views
- HTTP basic auth (credentials-first, ENV fallback)
- Severity badge helpers
- Clipboard and backtrace filter Stimulus controllers
- Shared admin navigation bar

### Authentication

```ruby
# Checks in order:
# 1. Rails.application.credentials.backstage.username / .password
# 2. ENV["SOLID_ERRORS_USER"] / ENV["SOLID_ERRORS_PASSWORD"]
```

Set up credentials:

```bash
bin/rails credentials:edit
```

```yaml
backstage:
  username: admin
  password: your_secure_password
```

### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--prefix` | *required* | URL prefix (e.g., `/admin`) |
| `--user-env-var` | `SOLID_ERRORS_USER` | Custom env var for username |
| `--password-env-var` | `SOLID_ERRORS_PASSWORD` | Custom env var for password |
| `--copy-views` | `true` | Include custom Tailwind views |

---

## Mission Control Jobs

Job queue monitoring dashboard with custom Tailwind views. 41 view files styled to match your application.

```bash
rails g maquina:mission_control_jobs --prefix /admin
```

### What You Get

- Full Tailwind-styled dashboard for Solid Queue
- Job status badges, queue views, worker monitoring
- Recurring task management
- Shared admin navigation (links to Solid Errors)
- HTTP basic auth (same credentials as Solid Errors)

### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--prefix` | *required* | URL prefix (e.g., `/admin`) |
| `--user-env-var` | `MISSION_CONTROL_JOBS_USER` | Custom env var for username |
| `--password-env-var` | `MISSION_CONTROL_JOBS_PASSWORD` | Custom env var for password |
| `--copy-views` | `true` | Include custom Tailwind views |

---

## Architecture Overview

After running `maquina:app --auth clave`, your project structure looks like this:

```
app/
  controllers/
    concerns/
      authentication.rb          # Session management
    sessions_controller.rb       # Sign-in
    registrations_controller.rb  # Sign-up
    home_controller.rb           # Root page
  models/
    account.rb                   # Multi-tenant container
    user.rb                      # Roles + auth
    current.rb                   # Request context
    session.rb                   # Browser sessions
    email_verification.rb        # Verification codes
  mailers/
    verification_mailer.rb       # Email codes
  jobs/
    authentication_cleanup_job.rb  # Daily cleanup

config/
  initializers/
    rack_attack.rb               # Request protection
    solid_errors.rb              # Error tracking auth
    mission_control.rb           # Job dashboard auth
  solid_queue.yml                # Queue configuration
```

### Security Defaults

- Rate limiting on registration and login
- Rack Attack blocks scanners and bots
- All controllers require authentication by default
- Account scoping prevents cross-tenant data access

### Ops Dashboards

- `/admin/solid_errors` — error tracking
- `/admin/mission_control_jobs` — job queue monitoring

Both protected with HTTP basic auth using shared backstage credentials.

---

## Role-Based Authorization

Use the role enum to restrict actions:

```ruby
class ProjectsController < ApplicationController
  before_action :require_admin, only: [:destroy]

  private

  def require_admin
    unless Current.user.admin?
      redirect_to projects_path, alert: t("flash.general.forbidden")
    end
  end
end
```

**Roles:**
- **admin** — first user created with account, full access
- **member** — default role, restricted from destructive actions

---

## Customization

All generated code lives in your app. Common customization points:

| What | Where |
|------|-------|
| Redirect after login | `app/controllers/concerns/authentication.rb` → `after_authentication_url` |
| Session duration | Change `30.days.from_now` in `authentication.rb` |
| Code expiration | Change `15.minutes.from_now` in verification controllers |
| Resend cooldown | `EmailVerification::COOLDOWN_MINUTES` (default: 15) |
| View styling | Edit view templates directly |
| Email sender | `app/mailers/verification_mailer.rb` |
| Translations | `config/locales/clave.*.yml` or `registration.*.yml` |
| Rack Attack rules | `config/initializers/rack_attack.rb` |
| Dashboard credentials | `bin/rails credentials:edit` → `backstage:` |
| Queue config | `config/solid_queue.yml` |

---

## Requirements

- Ruby >= 3.2.0
- Rails >= 7.2
- Tailwind CSS (for generated views)

The gem has zero runtime dependencies. Add it to your development group, generate your code, and remove it.

```ruby
# Gemfile
group :development do
  gem "maquina-generators"
end
```

---

## Next Steps

<div class="not-prose mt-8 grid grid-cols-1 gap-4 sm:grid-cols-2">
  <a href="https://github.com/maquina-app/maquina_generators" target="_blank" rel="noopener" class="group relative rounded-2xl border border-zinc-200 p-6 hover:border-[#50B1FD]/50 dark:border-zinc-800 dark:hover:border-[#50B1FD]/50 transition">
    <h3 class="font-sora font-semibold text-zinc-900 dark:text-white group-hover:text-[#50B1FD] transition">
      GitHub Repository
    </h3>
    <p class="mt-2 text-sm text-zinc-600 dark:text-zinc-400">
      View source code and contribute.
    </p>
  </a>

  <a href="/documentation/components/" class="group relative rounded-2xl border border-zinc-200 p-6 hover:border-[#50B1FD]/50 dark:border-zinc-800 dark:hover:border-[#50B1FD]/50 transition">
    <h3 class="font-sora font-semibold text-zinc-900 dark:text-white group-hover:text-[#50B1FD] transition">
      Maquina Components
    </h3>
    <p class="mt-2 text-sm text-zinc-600 dark:text-zinc-400">
      UI components installed by the app generator.
    </p>
  </a>

  <a href="/documentation/ai-tools/rails-simplifier/" class="group relative rounded-2xl border border-zinc-200 p-6 hover:border-[#50B1FD]/50 dark:border-zinc-800 dark:hover:border-[#50B1FD]/50 transition">
    <h3 class="font-sora font-semibold text-zinc-900 dark:text-white group-hover:text-[#50B1FD] transition">
      Rails Simplifier
    </h3>
    <p class="mt-2 text-sm text-zinc-600 dark:text-zinc-400">
      Keep generated code idiomatic with 37signals patterns.
    </p>
  </a>

  <a href="/documentation/ai-tools/rails-mcp-server/" class="group relative rounded-2xl border border-zinc-200 p-6 hover:border-[#50B1FD]/50 dark:border-zinc-800 dark:hover:border-[#50B1FD]/50 transition">
    <h3 class="font-sora font-semibold text-zinc-900 dark:text-white group-hover:text-[#50B1FD] transition">
      Rails MCP Server
    </h3>
    <p class="mt-2 text-sm text-zinc-600 dark:text-zinc-400">
      Give AI visibility into your generated codebase.
    </p>
  </a>
</div>
