A modern Rails template for building AI-powered apps — with built-in chat, MCP tools, multi-provider LLM support, and agent-native architecture. Follows 37signals' vanilla Rails philosophy.
- Ruby 4.0.x / Rails (edge)
- AI: RubyLLM (OpenAI, Anthropic) with streaming chat
- MCP: Model Context Protocol server via fast-mcp
- Database: SQLite with Solid Stack (Cache, Queue, Cable)
- Replication: Litestream (SQLite → S3-compatible storage)
- Frontend: Hotwire (Turbo + Stimulus), Tailwind CSS 4
- Billing: Stripe (subscriptions, checkout, customer portal)
- Deployment: Kamal 2
- Authentication: Magic Links (passwordless)
- Multitenancy: Team-based with roles (owner/admin/member)
- Multilingual: Mobility gem with RubyLLM auto-translation; full UI locales for
en, de, es, fr, ruplus language-name stubs fortg, uz, ky, tr, sr(add content per consuming project) - Currencies:
money+money-currencylayer-bank(daily rate refresh) - Countries:
countries(iso3166) with emoji flags - Analytics: Nullitics with MaxMind geolocation (optional)
- Admin Panel: Madmin
- Error Tracking: Rails Error Dashboard (RED) at
/red - Notifications: Noticed v2
- Search: SQLite FTS5 via the
Searchableconcern (Unicode61, bm25) - Vector Search: sqlite-vec (loadable extension) via
Embeddable,Chunkable,HybridSearchable - Charts: Chartkick + Groupdate
- Primary Keys: UUIDv7 (sortable, distributed-friendly)
- AI Chat with OpenAI and Anthropic models
- Streaming responses via Turbo Streams
- Model switching per chat
- Token tracking and cost estimation
- MCP Server — every UI action is also available as an MCP tool
- Streamable HTTP transport at
/mcp/messages - Team-level API key authentication
- 30+ tools for chats, messages, models, billing, teams, users, articles, and languages
- Streamable HTTP transport at
- Agent-native architecture — agents have full parity with human users
- Magic Link Authentication for users and admins
- Users: First magic link creates account, subsequent ones sign in
- Admins: Only existing admins can create new admins (via Madmin)
- Team-Based Multitenancy with configurable single/multi-tenant modes
- Roles: owner, admin, member
- Team-scoped routes under
/t/:team_slug/
- Multilingual Content with automatic LLM translation
- Per-team language management
- Auto-translates user-generated content (articles, etc.) on save
- Stripe Billing with subscriptions, checkout, and customer portal
- Litestream SQLite Replication to S3-compatible storage (optional)
- Continuous backup of all databases (main, cache, queue, cable)
- UUIDv7 Primary Keys for better distributed system support
- Solid Stack for production-ready background jobs, caching, and cable
- Notifications (via Noticed v2)
- Database + email delivery out of the box
- Live-updating inbox via Turbo Streams
- Per-kind, per-channel user preferences
- Ready for Slack, SMS, web/mobile push as opt-in adapters
- Full audit trail in Madmin at
/madmin/noticed_events
- Currencies + Countries
- Money gem with daily rate refresh from CurrencyLayer
- Admin-toggleable currencies — enable/disable individual currencies at
/madmin/languages(Currencies tab) - Per-team default currency, per-user preferred currency
- Per-team and per-user country (ISO 3166) with emoji flag picker
- Locale-aware amount formatting (Russian:
1 000 000; English:1,000,000) Current.currencyset on every request via a 5-step detection chain
- Full-Text Search via SQLite FTS5
include Searchableon any model, declaresearchable_fields- Unicode61 tokenizer handles Cyrillic, Turkish, and Latin diacritics out of the box
- Composable
Model.search(query)returns a relevance-orderedActiveRecord::Relation - Zero external services — SQLite ships with FTS5 built in
- Vector Search + RAG kit (
Embeddable,Chunkable,HybridSearchable)- sqlite-vec backed vec0 virtual tables, zero external dependencies
- Ordered KNN results with per-record confidence (
record.similarity_distance) - Configurable distance threshold (
max_distance) to filter irrelevant results - Metadata pre-filtering for WHERE-aware KNN
- Chunking for long documents via the polymorphic
Chunkmodel - Hybrid keyword + semantic retrieval via Reciprocal Rank Fusion
- All RAG parameters (distance threshold, RRF k, chunk size/overlap, pool multiplier) configurable via admin sliders at
/madmin/rag - Cosine (default), L2, L1, Hamming distance metrics
- Team Messaging (Conversations)
- Team-scoped person-to-person chat with attachments
- Polymorphic
subject— attach conversations to any record - Live updates via Turbo Streams
- Opt-in message translation (
TranslatableMessageconcern) - Opt-in contact-leak moderation (
ModeratableMessageconcern) - Email digests grouped by conversation with anti-spam throttling
- Dashboards (Chartkick + Groupdate)
- Reference team dashboard at
/t/:slug/with KPI cards, a chartkick line chart, attention-items strip, and a 7d/30d/90d time-range selector - Admin dashboard at
/madminwith platform-wide KPIs, cost + signup time-series, top teams and users by AI cost - Reusable partials:
_kpi_card,_chart_card,_attention_items_strip,_progress_ring DashboardHelperwithcached_dashboard(key, expires_in:)for team- and range-aware aggregation caching- OKLCH-aware Stimulus controllers for chart theming, sparklines, and the time-range selector
- Reference team dashboard at
- Vanilla Rails approach — no unnecessary abstractions
# Clone this template
git clone git@github.com:newstler/template.git my_new_project
cd my_new_project
# Setup project (runs configuration wizard on first run)
bin/setupOn first run, bin/setup will launch the configuration wizard that:
- Renames the project from "Template" to your project name
- Configures deployment domain and admin email
- Optionally enables Nullitics analytics
- Consolidates migrations into a single initial schema
- Renames git origin to
templateand asks for your repo URL - Commits all configuration changes
- Installs dependencies, prepares database, and starts dev server
# Pull latest changes from template
git fetch template
git merge template/main
# Or cherry-pick specific commits
git cherry-pick <commit-hash>Users can sign up and sign in using magic links sent to their email:
- Visit
/session/new - Enter email address
- Receive magic link via email (creates account on first use)
- Click link to sign in
Admins are managed via the Madmin admin panel:
- First admin is created via
rails db:seed(email configured duringbin/setup) - Existing admins can create new admins at
/madmin/admins - New admin receives magic link via email
- Admin signs in at
/admins/session/new
- Admin panel:
/madmin - Error dashboard:
/red(Rails Error Dashboard) - Admin login:
/admins/session/new
Only authenticated admins can access Madmin and the error dashboard.
# Start dev server (Procfile.dev)
bin/dev
# Console
rails console
# Database
rails db
rails db:migrate
rails db:seed
# Tests
rails test
rails test test/models/user_test.rb:42
# Code quality
bundle exec rubocop -A
# Reconfigure project (delete .configured first)
rm .configured && bin/setupThis template follows 37signals vanilla Rails philosophy:
- Rich domain models over service objects
- CRUD controllers - everything is a resource
- Concerns for horizontal code sharing
- Grow into abstractions - don't create empty directories
- Ship to learn - prototype quality is valid
See CLAUDE.md for complete guidelines.
app/
├── controllers/
│ ├── sessions_controller.rb # User auth (magic links)
│ ├── chats_controller.rb # AI chat
│ ├── articles_controller.rb # Multilingual articles
│ ├── home_controller.rb # Team dashboard
│ ├── onboardings_controller.rb # First-time user setup
│ ├── profiles_controller.rb # User profile
│ ├── admins/
│ │ └── sessions_controller.rb # Admin auth
│ ├── teams/ # Team management
│ │ ├── settings_controller.rb
│ │ ├── members_controller.rb
│ │ ├── pricing_controller.rb
│ │ ├── billing_controller.rb
│ │ └── languages_controller.rb
│ └── madmin/ # Admin panel overrides
├── models/
│ ├── user.rb, admin.rb, team.rb # Core models
│ ├── chat.rb, message.rb, model.rb # AI chat
│ ├── article.rb, language.rb # Multilingual content
│ ├── membership.rb # Team membership
│ └── concerns/ # Shared behavior
├── tools/ # MCP tools
├── resources/ # MCP resources
├── mailers/
│ ├── user_mailer.rb # User magic links
│ └── admin_mailer.rb # Admin magic links
└── views/
Using Kamal 2:
# Update config/deploy.yml with your settings
kamal setup
kamal deploySee config/deploy.yml for configuration.
API keys (AI, Stripe, SMTP, Litestream) are managed in the admin panel at /madmin/settings.
For credentials that must be encrypted (e.g. MaxMind geolocation keys), use Rails credentials:
rails credentials:edit --environment development
rails credentials:edit --environment production# MaxMind GeoLite2 for IP geolocation (optional, for Nullitics analytics)
maxmind:
account_id: "123456"
license_key: "abc..."Litestream provides continuous replication of all SQLite databases to S3-compatible storage:
Setup: Configure S3-compatible credentials in the admin panel at /madmin/settings.
What gets replicated:
- Main database
- Solid Cache
- Solid Queue
- Solid Cable
Commands:
rails litestream:replicate # Start replication
rails litestream:restore # Restore from backupSee config/litestream.yml for full configuration and CLAUDE.md for details.
MIT
Built by Yuri Sidorov following best practices from 37signals.