A production-ready Rails 8.1 application template with modern tooling, UUID v7 primary keys, comprehensive testing setup, and Docker support.
- Features
 - Usage
 - Environment Variables
 - UUID v7 Primary Keys
 - SimpleState
 - Testing
 - Sidekiq Web UI
 - Development URLs
 - Robot Blocking
 - CI/CD
 - Customization
 - Tech Stack Summary
 - License
 
- Rails 8.1.0.beta1 - Latest edge version
 - PostgreSQL with UUID v7 primary keys (time-ordered, sortable)
 - Redis for caching and job queue
 - Memcached with Dalli for distributed caching
 - Puma web server (2 workers, 5 threads)
 
- Sidekiq for background job processing
 - Authenticated web UI at 
/werawith HTTP Basic Auth 
- RSpec testing framework
 - FactoryBot for test data
 - Shoulda Matchers for Rails-specific assertions
 - WebMock for HTTP request stubbing
 - DatabaseCleaner with transaction strategy
 - Performance optimizations (GC management, eager loading)
 
- HTTPX - modern HTTP/2 client
 - Active Storage with AWS S3 support
 - Multi-environment storage configuration (local/test/S3)
 
- dotenv-rails for environment variables
 - Ngrok tunnel support for webhooks
 - .localhost domain support (no /etc/hosts editing needed)
 - Port 3007 by default (avoids common conflicts)
 
- Robot blocking middleware (SEO and AI crawlers)
 - Comprehensive robots.txt
 - Constant-time authentication comparison (prevents timing attacks on password checks)
 - No default credentials (environment-based)
 
- Docker and docker-compose ready
 - GitHub Actions CI/CD pipeline
 - Health check endpoint silencing
 - Kamal deployment configuration
 - Brakeman security scanning
 - RuboCop and StandardRb code linting
 
- UTC timezone (standard for Rails applications)
 - PostgreSQL connection pooling and statement timeouts
 - Request specs only (no controller/view specs)
 - No helper file generation
 - Clean, organized Gemfile
 
rails new myapp -d postgresql -m https://raw.githubusercontent.com/mundanecodes/rails-starter/main/template.rbThe template will:
- Install and configure all gems
 - Set up RSpec with all testing tools
 - Configure PostgreSQL with UUID v7 support
 - Set up Sidekiq with authenticated web UI
 - Configure Docker and docker-compose
 - Create GitHub Actions workflow
 - Set up robot blocking
 - Generate 
.env.examplewith all required variables - Create initial git commit
 
- 
Configure environment variables:
cp .env.example .env # Edit .env with your values - 
Set up database:
bin/rails db:create db:migrate
 - 
Start the server:
bin/rails server -p 3007
 - 
Access your app:
- Main app: 
http://myapp.localhost:3007 - Sidekiq UI: 
http://myapp.localhost:3007/wera 
 - Main app: 
 
docker-compose upServices included:
- Web (Rails app on port 3007)
 - PostgreSQL 16
 - Redis 7
 - Memcached 1.6
 - Sidekiq worker
 
Required variables (see .env.example):
# Database
DATABASE_URL=postgres://postgres:postgres@localhost:5432/myapp_development
# Redis & Sidekiq
REDIS_URL=redis://localhost:6379/0
SIDEKIQ_USERNAME=your_username
SIDEKIQ_PASSWORD=your_secure_password
# Memcached
MEMCACHED_SERVERS=localhost:11211
# AWS S3 (production)
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
AWS_REGION=us-east-1
AWS_BUCKET=your-bucket-name
# Server
PORT=3007All models automatically use UUID v7 as primary keys:
# No configuration needed - it's automatic!
class User < ApplicationRecord
  # id will be UUID v7
end
# In migrations
create_table :users do |t|
  # id is automatically UUID v7
  t.string :email
  t.timestamps
endUUID v7 benefits:
- Time-ordered (sortable like auto-incrementing IDs)
 - Globally unique
 - Better for distributed systems
 - Database index-friendly
 
A lightweight state machine module included with this template. Perfect for modeling workflows like user onboarding, order processing
class Employee < ApplicationRecord
  include SimpleState
  state_column :status
  enum status: {
    created: "created",
    invited: "invited",
    enrolled: "enrolled",
    suspended: "suspended",
    terminated: "terminated"
  }
  # Basic transition
  transition :invite, from: :created, to: :invited, timestamp: :invited_at
  # Transition with guard
  transition :enroll, from: :invited, to: :enrolled, timestamp: true,
             guard: :valid_invitation?
  # Transition with callback
  transition :suspend, from: [:enrolled], to: :suspended do
    NotificationMailer.suspension_notice(self).deliver_later
  end
  # Multiple source states
  transition :reactivate, from: [:suspended, :terminated], to: :enrolled
  private
  def valid_invitation?
    invited_at.present? && invited_at > 30.days.ago
  end
endUsage:
employee = Employee.create!(status: :created)
employee.invite  # => transitions to :invited, sets invited_at
employee.enroll  # => transitions to :enrolled if guard passes
# Check if transition is allowed
employee.can_transition?(:suspend)  # => true
# Error handling
begin
  employee.invite  # raises SimpleState::TransitionError if invalid
rescue SimpleState::TransitionError => e
  # Handle invalid transition
endFeatures:
- Guards: Prevent transitions unless conditions are met
 - Timestamps: Auto-update columns on transition (e.g., 
invited_at) - Callbacks: Execute code after successful transitions
 - Events: Publishes 
ActiveSupport::Notificationsfor all transitions - Validation: Ensures states exist in your enum at class load time
 
Events published:
Events follow the pattern: {model_name}.{transition_name}.{outcome}
For example, the invite transition on Employee publishes:
employee.invite.success- Transition succeededemployee.invite.failed- Update failed (validation, etc.)employee.invite.invalid- Transition not allowed or guard failed
Subscribe to events for logging, metrics, or side effects:
ActiveSupport::Notifications.subscribe(/employee\..*\.success/) do |name, start, finish, id, payload|
  Rails.logger.info "Employee #{payload[:record_id]} transitioned to #{payload[:to_state]}"
endRun the full test suite:
bundle exec rspecTesting features:
- Request specs generated by default
 - FactoryBot syntax methods included
 - WebMock prevents external HTTP calls
 - Transaction-based database cleaning (fast)
 - GC disabled during tests for 20-30% speed improvement
 
Access at /wera with HTTP Basic Authentication.
Set credentials via environment variables:
SIDEKIQ_USERNAME=admin
SIDEKIQ_PASSWORD=secure_password_hereAuthentication uses constant-time comparison to prevent timing attacks.
The template configures support for:
http://myapp.localhost:3007(no /etc/hosts editing needed)- Ngrok tunnels: 
https://abc123.ngrok-free.app - Standard localhost: 
http://localhost:3007 
To expose your local server for webhook testing:
ngrok http 3007This creates a public URL like https://abc123.ngrok-free.app that forwards to your local port 3007.
All robots are blocked by default via:
public/robots.txt- Blocks all user agents including GPTBot, CCBot, etc.- Middleware - Adds 
X-Robots-Tagheaders to all responses - Multiple layers ensure comprehensive blocking
 
Remove or modify in production if you want SEO indexing.
GitHub Actions workflow includes:
- RSpec test suite
 - Brakeman security scanning
 - RuboCop and StandardRb linting
 - PostgreSQL and Redis services
 
Edit config/application.rb:
config.time_zone = "Your/Timezone"Edit .env:
PORT=3000And docker-compose.yml:
ports:
  - "3000:3000"Remove from config/application.rb:
config.middleware.use BlockRobots| Category | Technology | 
|---|---|
| Framework | Rails 8.1.0.beta1 | 
| Database | PostgreSQL 16 + UUID v7 | 
| Cache | Redis 7 + Memcached 1.6 + Dalli | 
| Background Jobs | Sidekiq | 
| Testing | RSpec + FactoryBot + Shoulda + WebMock | 
| HTTP Client | HTTPX | 
| Storage | Active Storage + AWS S3 | 
| Web Server | Puma (2 workers, 5 threads) | 
| Containerization | Docker + docker-compose | 
| CI/CD | GitHub Actions | 
| Deployment | Kamal | 
| Security | Brakeman | 
| Linting | RuboCop + StandardRb | 
MIT
Built by mundanecodes for rapid Rails application development.