supabase:install
The main supabase-rails generator — what it writes, what it patches, the options it accepts, and what to do next.
bin/rails generate supabase:install is the one-shot setup generator for supabase-rails. It scaffolds the host-app glue for :web mode — an Authentication concern, five thin controller subclasses, a Current model, and a config/initializers/supabase.rb — and patches config/routes.rb and app/controllers/application_controller.rb so everything is wired up after a single bin/rails server.
Run it once after bundle add supabase-rails. The generator is idempotent: it skips files that already match its templates, runs Thor's standard overwrite prompt for files that have diverged, and no-ops the two file patches when the directives are already present.
bin/rails generate supabase:installExpected output on a fresh Rails 8 app:
create app/controllers/concerns/authentication.rb
create app/controllers/sessions_controller.rb
create app/controllers/registrations_controller.rb
create app/controllers/passwords_controller.rb
create app/controllers/otp_controller.rb
create app/controllers/oauth_controller.rb
create app/models/current.rb
create config/initializers/supabase.rb
insert config/routes.rb
insert app/controllers/application_controller.rbFiles created
Eight files. Each one is small on purpose — the gem ships the real implementation; the host app only owns the override hooks.
| Path | What it is |
|---|---|
app/controllers/concerns/authentication.rb | A 7-line concern that includes Supabase::Rails::Authentication. ApplicationController includes this concern, which is what gives every host controller authenticated?, current_user, require_authentication, and the full supabase_* helper surface. |
app/controllers/sessions_controller.rb | 3-line subclass of Supabase::Rails::SessionsController. Handles GET /session/new, POST /session, DELETE /session. Empty body — override actions here to customise. |
app/controllers/registrations_controller.rb | 3-line subclass of Supabase::Rails::RegistrationsController. Handles GET /registration/new, POST /registration. |
app/controllers/passwords_controller.rb | 3-line subclass of Supabase::Rails::PasswordsController. Handles the "forgot password" / "reset password" flow at /passwords and /passwords/:token. |
app/controllers/otp_controller.rb | 3-line subclass of Supabase::Rails::OtpController. Handles email/SMS one-time codes at /otp/new, /otp, /otp/verify. |
app/controllers/oauth_controller.rb | 3-line subclass of Supabase::Rails::OauthController. Handles /oauth/:provider/authorize (kicks off PKCE) and /oauth/callback (exchanges the code). |
app/models/current.rb | class Current < ActiveSupport::CurrentAttributes with attribute :user, :session. Per-request thread-local store the Authentication concern populates after a successful verify. |
config/initializers/supabase.rb | Sets Rails.application.config.supabase.mode = :web. Ships with commented examples for allowed_redirect_origins, expose_current_user, and the session cookie hash. The framework default is :api, so this file is what flips the gem into cookie-session mode. |
Generated file contents
The concern (app/controllers/concerns/authentication.rb):
# frozen_string_literal: true
module Authentication
extend ActiveSupport::Concern
included do
include Supabase::Rails::Authentication
end
endA controller subclass (app/controllers/sessions_controller.rb — the other four are identical except for the parent class):
# frozen_string_literal: true
class SessionsController < Supabase::Rails::SessionsController
endThe Current model (app/models/current.rb):
# frozen_string_literal: true
class Current < ActiveSupport::CurrentAttributes
attribute :user, :session
endThe initializer (config/initializers/supabase.rb):
# frozen_string_literal: true
Rails.application.config.supabase.mode = :web
# Origins the OAuth + password-reset helpers will accept as redirect targets.
# Path-only redirects are always allowed; absolute URLs must match an entry
# below. Defaults to [request.host] at runtime when this list is empty.
# Rails.application.config.supabase.allowed_redirect_origins = ["https://example.com"]
# Expose `current_user` as a view helper. nil = derive from mode
# (true in :web, false in :api).
# Rails.application.config.supabase.expose_current_user = nil
# Encrypted session cookie defaults. `secure: nil` = auto-detect from Rails.env.
# Rails.application.config.supabase.session = {
# cookie_name: "sb-session",
# same_site: :lax,
# secure: nil,
# domain: nil,
# path: "/"
# }See Configuration for every key the initializer can set, including the ones the template omits (auth, cors, env, supabase_options, oauth_providers, user_model, insert_middleware).
Files modified
Two files in the host app are patched in place. Both patches are guarded by a substring check, so re-running the generator after a successful first run is a no-op on each.
config/routes.rb
A single line is injected on the line directly after Rails.application.routes.draw do:
# config/routes.rb
Rails.application.routes.draw do
+ supabase_authentication_routes
# ... your existing routes
endsupabase_authentication_routes is a DSL helper installed onto ActionDispatch::Routing::Mapper by Supabase::Rails::Engine. One line expands to the full session / registration / passwords / OTP / OAuth route table — see the routes reference for the per-route breakdown, including the only: / except: filters for mounting a subset.
The patch is skipped if config/routes.rb already contains the string supabase_authentication_routes, or when the file does not exist (e.g. an --api-only Rails app without a generated routes file).
app/controllers/application_controller.rb
A single line is injected into the ApplicationController class body via Thor's inject_into_class:
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
+ include Authentication
# ... your existing code
endThis is the one line that activates everything else — every controller that inherits from ApplicationController now gets the supabase_* helpers, the before_action :require_authentication, and the current_user / authenticated? view helpers.
The patch is skipped if the file already contains the string include Authentication, or when app/controllers/application_controller.rb does not exist.
No database migrations
The install generator writes no migrations — Supabase Auth owns the user table, and Current is ActiveSupport::CurrentAttributes (per-request, in-memory). If you want a shadow users row in your own database so belongs_to :user resolves, run bin/rails generate supabase:user_model afterwards.
Diff summary
A complete "what changed" view of a freshly-generated app, by file:
+ app/controllers/concerns/authentication.rb
+ app/controllers/sessions_controller.rb
+ app/controllers/registrations_controller.rb
+ app/controllers/passwords_controller.rb
+ app/controllers/otp_controller.rb
+ app/controllers/oauth_controller.rb
+ app/models/current.rb
+ config/initializers/supabase.rb
config/routes.rb
+ supabase_authentication_routes
app/controllers/application_controller.rb
+ include AuthenticationTotal: 8 files created, 2 files modified, 0 migrations, 0 lines deleted.
Options
The generator declares no custom flags — it inherits Thor's standard generator option set. The flags worth knowing:
| Flag | Effect |
|---|---|
--force, -f | Overwrite every file that already exists, without prompting. Use when re-running the generator after you've intentionally rolled back an earlier version. |
--skip, -s | Keep host copies for every file that already exists. Useful when you want the routes/ApplicationController patches but not to touch existing controller files. |
--pretend, -p | Dry-run. Prints the create/insert log lines without writing anything. |
--quiet, -q | Suppress the create/insert log lines. |
--skip-namespace | Don't include the generator's namespace in generated paths. No-op for this generator — paths are absolute (app/controllers/..., not app/controllers/<namespace>/...). |
--skip-collision-check | Skip Rails' check for filename collisions with existing Ruby constants. |
--help, -h | Print the generator's description and option list. |
When a file already exists and its content differs from the template, Thor prompts interactively with [Ynaqdh]:
| Key | Meaning |
|---|---|
Y (yes) | Overwrite this file. |
n (no) | Keep the existing file. |
a (all) | Overwrite all remaining conflicts (equivalent to --force for the rest of the run). |
q (quit) | Abort the generator. Files already written stay written. |
d (diff) | Show a unified diff of host file vs. template, then re-prompt. |
h (help) | List the keys above. |
After the generator
Three things to do before bin/rails server:
- Set
SUPABASE_URL,SUPABASE_PUBLISHABLE_KEY, andSUPABASE_SECRET_KEY— the gem reads these at request time (not at boot). See the env-var resolution table in Configuration. The full Supabase-dashboard → env-var mapping is in step 4 of the Getting started guide. - Open the initializer and uncomment what you need. The defaults are sensible for local dev (path-only redirects allowed, host-only session cookie,
expose_current_userderived from mode). Setallowed_redirect_originsbefore you ship to production, and setoauth_providersif you want theoauth/_buttonspartial to render anything. - Verify with a sign-up.
/registration/newshould render the gem's default form. After submitting,Current.useris populated from the verified JWT claims — drop<%= Current.user&.email %>anywhere in a view to confirm.
Customising the generated controllers
The five generated controllers exist solely as override points. Add an action and call super — the base class handles the Supabase round-trip, your override handles the host-app-specific behaviour:
# app/controllers/sessions_controller.rb
class SessionsController < Supabase::Rails::SessionsController
def create
super
# Custom analytics, audit log, welcome flash, etc.
AnalyticsJob.perform_later(:signed_in, user_id: Current.user.id) if authenticated?
end
endOverride the entire action by not calling super; the base class's behaviour is documented per-controller in the controllers reference. For overrides of the supabase_* helpers themselves (e.g. custom error formatting), override the corresponding hook on the Authentication concern instead.
To replace the gem's default views with your own ERB, run bin/rails generate supabase:views — it copies the eight default templates into app/views/supabase/rails/ where Rails' view-resolution order picks the host copies ahead of the gem's. See the supabase:views generator page for details.
Re-running and rolling back
The generator is safe to re-run any number of times:
- Files with content identical to the template print
identicaland are not rewritten. - Files that have diverged trigger Thor's
[Ynaqdh]overwrite prompt (unless--forceor--skipis passed). - The two file patches (
routes.rb,application_controller.rb) substring-check before injecting — never duplicated.
There is no supabase:uninstall generator. To roll back manually:
- Remove the eight generated files (the concern, five controllers,
Current, the initializer). - Delete the
supabase_authentication_routesline fromconfig/routes.rb. - Delete
include Authenticationfromapp/controllers/application_controller.rb. bundle remove supabase-rails.
See also
- Getting started — the end-to-end quickstart that invokes this generator as step 3.
- Configuration — every
config.supabase.*key the initializer can set. - Authentication — the
Authenticationconcern's full helper surface and override hooks, plus theCurrent.user/Current.sessionvalue objects. - Controllers — the five base controllers the generated subclasses inherit from, plus the full route table
supabase_authentication_routesproduces. supabase:user_model— opt-in shadow ARUsermodel + migration.supabase:views— copy the default ERB templates into the host app for customisation.