Rails Superstack is a ready-to-go Ruby on Rails instance with front-end, database, and accouterments. A majestic monolith with a f*ckton of useful gems. It's a free public template anyone can use to hit the ground running with their own apps.
- Getting Started
- What's in a Superstack, Exactly?
- Linting, Testing, and CI
- GraphQL API
- Stripe Billing
- Ephemera
- Acknowledgements
First things first. Create a repository from this template. It's only two steps!
- Click on "Use this template" above the file list
- Select "Create a new repository"
Clone the new repo to your local machine, and you're done! (I suppose that's technically three steps)
With your shiny new repo in hand, here's what you need to get cooking:
- Bundler v4.0
- PostgreSQL 18
- Redis 8.6
- Ruby 3.4.7
- Typesense Server 30.1
I'd personally recommend Homebrew and rbenv to install these prerequisites:
cd /path/to/your/repo
# Install Homebrew + Postgres
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install postgresql@18
# Install Redis + Typesense
brew install redis
brew install typesense/tap/typesense-server@30.1
# Install rbenv + Ruby
curl -fsSL https://rbenv.org/install.sh | bash
rbenv install 3.4.7
# Install Bundler
gem install bundler
# Start up the services
brew services start postgresql@18
brew services start redis
brew services start typesense-server@30.1Unless you want your app to be called "Rails Superstack", you'll probably want to run this script:
cd /path/to/your/repo
# Get help
script/rename.sh --help
# Preview changes
script/rename.sh --dry-run
# Run interactively
script/rename.sh
# Run without prompts
script/rename.sh --no-confirmationThe script should be clever enough to detect your new repo's origin url. If not, it'll prompt you for it. If that fails, it'll prompt for your GitHub username and repository name.
After the script runs successfully, it'll delete itself and create a new README.
This one's easy. Navigate to Get Started with Font Awesome to sign up and add a new icon kit. Create an app configuration using the included config/application.yml.example file, then plug in your shiny new kit:
cd /path/to/your/repo
cp config/application.yml.example config/application.ymlOpen config/application.yml and replace font_awesome_kit_url with your kit's url.
You can install dependencies, set up the database, run migrations – etc. etc. – or you can live on the wild side and run the setup script:
cd /path/to/your/repo
# Set up everything + start the development server
bin/setup
# Set up everything + don't start the development server
bin/setup --skip-server
# Reset back to factory settings
bin/setup --resetDone this song-and-dance before? If you just need to start up the development server, you can skip straight to the end and run the dev script:
cd /path/to/your/repo
bin/devOpen localhost:3000 in your web browser and you're good to go!
Rails Superstack is a modern Ruby on Rails app, so by default it comes with:
Rails Superstack has been preloaded and configured with the following:
- Strong Migrations (catch unsafe migrations)
- LogBench (log viewer)
- RSpec + Factory Bot + Faker (testing)
- SimpleCov + SimpleCov Tailwind + SimpleCov Badger (code coverage)
- RubyCritic (code quality)
- Passwordless + CanCanCan (auth + roles)
- Letter Opener + Letter Opener Web (preview emails)
- Pom Component + Draper (view components + decorators)
- Font Awesome + Gravatar Image Tag Plugin (icons)
- SuperAdmin + Flipper (admin + feature flags)
- Commonmarker (syntax highlighting)
- Resque (background jobs)
- Typesense + Pagy (search + pagination)
- GraphQL (API)
- Noticed (notifications)
- Figaro (app configuration)
- Stripe (payments + subscriptions)
Just a few highlights to whet the palette.
| Feature | Description |
|---|---|
| Abilities (Roles) | CanCanCan abilities (dynamic) |
| Models | Users, API tokens, subscriptions |
| Helpers | Text, web urls, forms, Font Awesome icons |
| Normalizers | Email addresses |
| Notifiers | Bulk (toast) and individual (toast, email) |
| Parsers | Email addresses, web urls |
| Services | Stripe billing, email, notifications |
| Validators | Email addresses, web urls |
| View Components | Clipboard, flash alerts, code snippets |
| Endpoint | Description |
|---|---|
/billing/plans |
View subscription plans (Stripe) |
/sent_mail |
Preview sent mail (Passwordless login codes) |
/settings |
Change email, create API tokens, manage billing |
/sign_in |
Sign in as a new or existing user |
/sign_out |
Sign out the current user |
| Endpoint | Description |
|---|---|
/admin |
SuperAdmin dashboard |
/notifications |
System notifications |
/flipper |
Feature flags |
/resque |
Background jobs |
(The cleanup script will remove these endpoints)
| Endpoint | Description |
|---|---|
/demo/alert |
Example for flash alerts (as notification toasts) |
/demo/api |
GraphQL API routes and examples |
/demo/mac_guffins |
Placeholder items accessible by the current user |
/demo/notice |
Example for flash notices (as notification toasts) |
/demo/secrets |
A "secret" route hidden behind a feature flag |
/demo/terminal |
Lists a few useful terminal commands |
/demo/themes |
Shows off Stripe purchases as app themes |
/demo/welcome |
Starter page with helpful links |
There's handy binstubs for RSpec and RuboCop. Local CI will mirror the GitHub workflow that runs when you make commits and merge pull requests.
cd /path/to/your/repo
# Lint code for consistent style
bin/rubocopcd /path/to/your/repo
# Run RSpec tests
bin/rspec
# Open SimpleCov coverage report
open coverage/index.htmlcd /path/to/your/repo
bin/ciGraphQL is a touch different than your vanilla JSON API. The data structures are effectively dynamic, so you can hit a single endpoint to request any sort of data in any sort of order.
An endpoint covers a single GraphQL schema, which could compromise an individual model or literally your entire database. For simplicity and clarity, this repo has two schemas to disambiguate between common and demo endpoints.
The API uses token-based authentication. You'll need a bearer authentication token to make queries to authenticated endpoints.
You can use ApiToken.issue!(user:, name:) to get a bearer auth token in Rails. Pass in current_user to query resources available in the current session.
There's a one-stop binstub to pipe a bearer auth token directly into your GraphQL queries:
cd /path/to/your/repo
# Returns "Bearer TOKEN" for direct usage
bin/api-token api@superstack.devTo query data in GraphQL, you POST to an endpoint with your query as the payload. The examples below use curl to hit the API and pipe the responses to jq for pretty formatting in the terminal.
cd /path/to/your/repo
# health check
curl -s -H 'Content-Type: application/json' \
-X POST http://localhost:3000/graphql \
-d '{"query":"{ health { status } }"}' | jq
# users (requires authentication)
bin/api-token | xargs -I% curl -s -H 'Content-Type: application/json' \
-H 'Authorization: %' -X POST http://localhost:3000/graphql \
-d '{"query":"{ users { id email role } }"}' | jq
# MacGuffins (requires authentication)
bin/api-token | xargs -I% curl -s -H 'Content-Type: application/json' \
-H 'Authorization: %' -X POST http://localhost:3000/graphql/demo \
-d '{"query":"{ macGuffins { id name description } }"}' | jqA response will be nicely formatted JSON data:
# POST /graphql/health
{
"data": {
"health": {
"status": "ok"
}
}
}You effectively have Stripe purchases and subscriptions right out of the box! Everything is already wired up from API integrations to webhooks.
A few key points:
- To cover the basics of your average paid app, users are linked to subscriptions with free and paid options. Paid plans can be monthly or yearly.
- Stripe webhook listeners don't run automatically. I mean, what if you don't need them? Use the
--with-stripeargument when starting your development server:
cd /path/to/your/repo
bin/dev --with-stripeIt always starts with API keys. There are placeholders in config/application.yml to replace with your Stripe test keys. Never commit real keys!
stripe_secret_key: sk_test_REPLACE_ME
stripe_publishable_key: pk_test_REPLACE_ME
stripe_signing_secret: whsec_REPLACE_MEYou can obtain your stripe_signing_secret when you run bin/dev --with-stripe for the first time. You'll see terminal output like the following:
22:58:43 stripe.1 | Ready! You are using Stripe API Version [2017-12-14]. Your webhook signing secret is whsec_REPLACE_ME (^C to quit)To allow your users to sign up for paid subscriptions, you only have to do a few things:
- Create two products in the Stripe catalog (one each for monthly and yearly)
- Copy the price ids into
stripe_price_pro_monthlyandstripe_price_pro_yearlyinconfig/application.yml. These aren't product ids! On each product page there's a "Pricing" section with a dropdown menu (...) where you can copy the price id. - Match the
price_monthly_centsandprice_yearly_centsinapp/models/billing/pro_plan.rbto your product prices
That's it! Visit /billing/plans or /settings/billing as a logged-in user, and everything should just work!
Amazingly, you don't need to do ANYTHING to make Stripe purchases. They can be handled entirely programmatically through the Stripe API.
The demo code has "super premium themes" as a fully implemented example. Visit /demo/themes as a logged-user to buy them!
Want to roll your own? There are four relevant files:
app/models/demo/themes/theme_purchase.rb
app/services/demo/themes/complete_purchase_service.rb
app/services/demo/themes/create_checkout_session_service.rb
config/initializers/demo/billing_checkout_handlers.rb
billing_checkout_handlers.rbis used to register the payment webhook handlers that get called when you complete a Stripe purchasecreate_checkout_session_service.rbperforms a Stripe purchasecomplete_purchase_service.rbis called when you complete a Stripe purchasetheme_purchase.rbis the database model linked to the Stripe purchase
Replicate (or edit) these for your own unique Stripe purchases!
When you run RSpec tests, a SimpleCov coverage report is created at coverage/index.html in your repo. This is great! The SimpleCov Tailwind gem makes it look buttery smooth. This is better! But the SimpleCov Badger gem? It lets you add a repo badge to your README. This is BEST.
You can follow the SimpleCov Badger instructions, but it's already configured in Rails Superstack, so you really just need to do three things:
- Get an API token
- Run
bin/rails simplecov_badger:installto get an API token - Set
simplecov_badger_tokeninconfig/application.yml - Add a new GitHub repo secret for
SIMPLECOV_BADGER_TOKEN - Commit to
main(so CI runs) - Check the "Run RSpec tests" console output from GitHub CI
- Copy the badge url
- Update your README
- Add
 - Done!
Dislike the demo code with a passion? Easy! Burn it with 🔥 fire 🔥 by running the cleanup script:
cd /path/to/your/repo
# Get help
script/cleanup.sh --help
# Preview changes
script/cleanup.sh --dry-run
# Run interactively
script/cleanup.sh
# Run without prompts
script/cleanup.sh --no-confirmationThe script removes all trace of demo code from the template. This includes assets, controllers, helpers, models, views, routes, seeds, and specs.
Cleanup also inserts migrations to remove the demo tables and then regenerates the schema by dropping and recreating the local database.
After the script runs successfully, it deletes itself and you’ll be left with a pristine template.
The Rails Superstack logo was crafted from an illustration by Muhammad Afandi on Unsplash.