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
/wera
with 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.rb
The 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.example
with 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 up
Services 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=3007
All 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
end
UUID 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
end
Usage:
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
end
Features:
- 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::Notifications
for 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]}"
end
Run the full test suite:
bundle exec rspec
Testing 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_here
Authentication 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 3007
This 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-Tag
headers 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=3000
And 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.