261 lines
11 KiB
Markdown
261 lines
11 KiB
Markdown
r4# Rails 8 Starter Kit
|
|
|
|
> A production-grade, AI-native fullstack starter kit for Rails 8.
|
|
> Zero-config Docker. Parallel tests. Real-time WebSockets. Premium dark UI.
|
|
> From `git clone` to running app in one command.
|
|
|
|
```
|
|
docker compose up
|
|
```
|
|
|
|
That's it. The `setup` container creates your database, seeds sample data, and the `tests` container validates everything with parallel linting and specs — all before your app boots.
|
|
|
|
---
|
|
|
|
## What's Inside
|
|
|
|
| Layer | Technology | Why |
|
|
|---|---|---|
|
|
| **Framework** | Rails 8.1 (edge) + Ruby 4.0 | Latest Rails with all modern defaults |
|
|
| **Frontend** | Hotwire (Turbo + Stimulus) + Tailwind CSS v4 + DaisyUI | SPA-like UX without a JS build step |
|
|
| **Real-time** | AnyCable + AnyCable-Go + Turbo Streams | WebSocket broadcasting at scale |
|
|
| **Database** | PostgreSQL 17.5 + PgBouncer | Connection pooling out of the box |
|
|
| **Background Jobs** | Sidekiq + Sidekiq-Cron | Reliable async processing with recurring jobs |
|
|
| **Object Storage** | Active Storage + LocalStack (S3) | Production-parity file uploads locally |
|
|
| **3D Graphics** | Three.js (via importmap) | Ready for WebGL/3D without bundlers |
|
|
| **Testing** | RSpec + Capybara + Parallel Tests | Full-stack E2E with headless Chromium |
|
|
| **Code Quality** | RuboCop (Shopify) + Brakeman + Reek + Flog + Flay | 8 linters running in parallel |
|
|
| **Auth Framework** | CanCanCan | Authorization scaffolding baked in |
|
|
| **Security** | Rack::Attack + SSRF Filter + Bundler Audit | Rate limiting and vulnerability scanning |
|
|
| **Deployment** | Kamal + Thruster + Multi-stage Dockerfile | Production-ready container deployment |
|
|
| **CI** | GitHub Actions + Dependabot | Automated testing and dependency updates |
|
|
| **Dev Tools** | Foreman + jemalloc + Bootsnap | Fast boot, low memory, process management |
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
### Docker (recommended)
|
|
|
|
```bash
|
|
git clone https://github.com/{owner}/rails-8-AI-native-starter-kit.git
|
|
cd rails-8-AI-native-starter-kit
|
|
docker compose up
|
|
```
|
|
|
|
The startup pipeline runs automatically:
|
|
|
|
```
|
|
setup → creates DB, runs migrations, seeds data
|
|
tests → runs all 8 linters + parallel specs
|
|
app → boots Puma + Tailwind watcher + Sidekiq
|
|
ws → boots AnyCable-Go WebSocket server
|
|
```
|
|
|
|
Your app is live at `http://localhost:3000`, WebSockets at `ws://localhost:8081/cable`.
|
|
|
|
### Local (without Docker)
|
|
|
|
Requirements: Ruby 4.0+, PostgreSQL, Redis, `anycable-go`
|
|
|
|
```bash
|
|
bin/setup # install deps, create DB, seed, start server
|
|
bin/check-fast # run all linters in parallel
|
|
bin/prspec # run specs with parallel_tests
|
|
```
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
|
|
│ Browser │◄──►│ Puma :3000 │◄──►│ PostgreSQL │
|
|
│ │ │ (Rails 8) │ │ + PgBouncer │
|
|
└──────┬──────┘ └──────┬───────┘ └─────────────┘
|
|
│ │
|
|
│ WebSocket │ Pub/Sub
|
|
▼ ▼
|
|
┌──────────────┐ ┌──────────┐ ┌─────────────┐
|
|
│ AnyCable-Go │◄──►│ Redis │◄──►│ Sidekiq │
|
|
│ :8081 │ │ │ │ (workers) │
|
|
└──────────────┘ └──────────┘ └─────────────┘
|
|
│
|
|
┌────▼────────┐
|
|
│ LocalStack │
|
|
│ (S3) :4566 │
|
|
└──────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Testing
|
|
|
|
### Parallel Execution
|
|
|
|
Tests run across all available CPU cores via `parallel_tests`:
|
|
|
|
```bash
|
|
bin/prspec # parallel specs (default)
|
|
bin/check-fast # 8 linters + specs, all parallel
|
|
bin/check --parallel=rubocop,rspec --then=brakeman
|
|
```
|
|
|
|
### Headless Browser Testing
|
|
|
|
Capybara system specs run with headless Chromium. The driver auto-detects the environment:
|
|
- **Docker**: uses `/usr/bin/chromium` (pre-installed in `Dockerfile.dev`)
|
|
- **macOS/Linux**: uses Selenium Manager to find native Chrome
|
|
|
|
Animations and transitions are automatically disabled in `RAILS_ENV=test` for deterministic, fast specs.
|
|
|
|
### Test Pipeline in Docker
|
|
|
|
```bash
|
|
docker compose up # setup → tests → app (sequential gates)
|
|
docker compose run --rm tests # run tests only
|
|
```
|
|
|
|
The `tests` service uses `service_completed_successfully` as a gate — your app literally won't boot unless every linter and spec passes.
|
|
|
|
---
|
|
|
|
## Code Quality Gates
|
|
|
|
| Linter | Purpose |
|
|
|---|---|
|
|
| `rubocop` | Style enforcement (Shopify conventions) |
|
|
| `brakeman` | Static security analysis |
|
|
| `bundler-audit` | Known CVE scanning in dependencies |
|
|
| `reek` | Code smell detection |
|
|
| `flog` | Complexity scoring |
|
|
| `flay` | Duplication detection |
|
|
| `haml-syntax` | Template validation |
|
|
| `rspec` | Unit + system specs (parallel) |
|
|
|
|
All 8 run in parallel via `bin/check-fast`. Sequential chains are supported with `bin/check --then=`.
|
|
|
|
---
|
|
|
|
## Docker Compose Services
|
|
|
|
| Service | Image | Port | Role |
|
|
|---|---|---|---|
|
|
| `postgres` | `postgres:17.5` | 5432 | Primary database with tuned config |
|
|
| `pgbouncer` | `edoburu/pgbouncer` | — | Transaction-mode connection pooling |
|
|
| `redis` | `redis:8.4-alpine` | 6379 | Pub/sub + cache + job queue backend |
|
|
| `localstack` | `localstack:4.13.1` | 4566 | S3-compatible object storage |
|
|
| `ws` | `anycable-go:1.6` | 8081 | WebSocket server |
|
|
| `setup` | (app image) | — | DB creation, migrations, seeds |
|
|
| `tests` | (app image) | — | Linters + parallel specs gate |
|
|
| `app` | (app image) | 3000 | Rails + Tailwind + Sidekiq |
|
|
|
|
All three app-derived containers (`setup`, `tests`, `app`) share a single Docker image build to prevent wasteful rebuilds.
|
|
|
|
---
|
|
|
|
## Key Decisions
|
|
|
|
### Why AnyCable over Action Cable?
|
|
|
|
AnyCable-Go handles WebSocket connections in a dedicated Go process, keeping Ruby threads free for business logic. It's a drop-in replacement — the Rails side uses standard Action Cable APIs via `anycable-rails`.
|
|
|
|
### Why PgBouncer?
|
|
|
|
Transaction-mode connection pooling prevents the "too many connections" problem in production. The `setup` and `tests` services bypass PgBouncer and connect directly to Postgres (required for `CREATE DATABASE`).
|
|
|
|
### Why Sidekiq over Solid Queue?
|
|
|
|
Sidekiq provides battle-tested async processing with a mature web UI, cron scheduling (`sidekiq-cron`), and deep Redis integration. The `recurring.yml` has example jobs pre-configured.
|
|
|
|
### Why jemalloc?
|
|
|
|
`LD_PRELOAD=/usr/local/lib/libjemalloc.so` — reduces Ruby memory fragmentation by 30-40% in production. Pre-configured in both Dockerfiles.
|
|
|
|
### Why Bootsnap Cache Isolation?
|
|
|
|
Each Docker container gets an anonymous volume (`/rails/tmp/cache`) to prevent concurrent Bootsnap compilation from crashing on shared macOS mounts.
|
|
|
|
---
|
|
|
|
## Demo Content
|
|
|
|
> ⚠️ **The following components exist purely for demonstration.** They show how each layer of the stack works together. **Delete them when starting a real application.**
|
|
|
|
| Component | Files | Demonstrates |
|
|
|---|---|---|
|
|
| **Todo CRUD** | `app/models/todo.rb`, `app/controllers/todos_controller.rb`, `app/views/todos/`, `db/migrate/*_create_todos.rb` | Model → Controller → View with Turbo Frames |
|
|
| **Turbo Stream broadcasting** | `after_create_commit` in `todo.rb`, `turbo_stream_from` in `index.html.erb` | Real-time push via AnyCable |
|
|
| **Stimulus controller** | `app/javascript/controllers/hello_controller.js` | Basic Stimulus wiring |
|
|
| **Three.js import** | `config/importmap.rb` (the `three` pin) | Importmap-based JS library usage |
|
|
| **Sample seed** | `db/seeds.rb` (the `Todo.create!` block) | Idempotent database seeding |
|
|
| **System spec** | `spec/system/todos_spec.rb` | Capybara + headless Chromium E2E test |
|
|
| **Home controller** | `app/controllers/home_controller.rb`, `app/views/home/` | Static page routing |
|
|
| **Example job** | `app/jobs/example_recurring_job.rb`, `config/recurring.yml` | Sidekiq-Cron recurring task |
|
|
|
|
---
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
├── app/
|
|
│ ├── assets/tailwind/ # Tailwind v4 + DaisyUI theme (Halloween dark)
|
|
│ ├── controllers/ # Rails controllers
|
|
│ ├── javascript/ # Stimulus controllers + application.js
|
|
│ ├── models/ # ActiveRecord models
|
|
│ └── views/ # ERB + HAML templates
|
|
├── bin/
|
|
│ ├── check # Orchestrator: parallel + sequential task runner
|
|
│ ├── check-fast # Fast CI mode (8 linters in parallel)
|
|
│ ├── prspec # Parallel RSpec runner
|
|
│ ├── setup # One-command dev environment setup
|
|
│ └── linters/ # Individual linter scripts
|
|
├── config/
|
|
│ ├── cable.yml # AnyCable adapter config
|
|
│ ├── database.yml # PostgreSQL (env-driven, PgBouncer-aware)
|
|
│ └── recurring.yml # Sidekiq-Cron job schedules
|
|
├── docker-compose.yml # Full 8-service development stack
|
|
├── Dockerfile # Multi-stage production image
|
|
├── Dockerfile.dev # Development image (with Chromium)
|
|
└── spec/
|
|
├── support/capybara.rb # Cross-env headless browser driver
|
|
└── system/ # E2E browser specs
|
|
```
|
|
|
|
---
|
|
|
|
## Environment Variables
|
|
|
|
All configuration is driven by environment variables with sensible defaults. See `env.example` for the complete list. Key variables:
|
|
|
|
| Variable | Default | Purpose |
|
|
|---|---|---|
|
|
| `DB_HOST` | `localhost` | PostgreSQL host (use `pgbouncer` in Docker) |
|
|
| `DB_DIRECT_HOST` | `localhost` | Direct PG host (bypasses PgBouncer for migrations) |
|
|
| `REDIS_URL` | `redis://localhost:6379/1` | Redis connection string |
|
|
| `RAILS_MASTER_KEY` | from `config/master.key` | Credentials decryption key |
|
|
|
|
---
|
|
|
|
## For AI Agents
|
|
|
|
This repository is optimized for LLM-assisted development:
|
|
|
|
- **Deterministic setup**: `docker compose up` produces identical environments
|
|
- **Fast feedback**: `bin/check-fast` validates all changes in seconds
|
|
- **Clear conventions**: Shopify Ruby style, RSpec, Stimulus naming
|
|
- **Minimal surface area**: one model, one controller, flat config files
|
|
- **No magic**: explicit imports, no metaprogramming in app code
|
|
|
|
To modify this project, start by reading:
|
|
1. `config/routes.rb` — all routes
|
|
2. `Gemfile` — all dependencies
|
|
3. `docker-compose.yml` — full infrastructure
|
|
4. `bin/check-fast` — validation pipeline
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
MIT
|