Answers · Keys & Services

Do I need API keys to run a Rails starter kit locally?

No. Billing, email, bot checking and error reporting each sit behind an adapter that returns a real client when its credential is present and a deterministic local fake when it is not. A fresh clone runs bin/setup and bin/dev with no keys, and checkout, sign-in and gated features all work end to end.

Prove it in two commands

bin/setup
bin/dev

No .env to fill in first. The database is SQLite, so there is no Postgres to install and no Redis to run. Sign in with a magic code, which opens in a browser tab rather than sending. Buy a subscription, which completes against the local fake. Open a gated feature, which unlocks.

How the seam works

app/adapters/billing.rb is the reference implementation, and the others copy its shape:

Billing.for(account)

One method, two possible implementations, and nothing else in the app knows which it received. Both live under app/adapters/billing, and the fake is short enough to read in a minute, which is the point: it documents what the real one is expected to do.

app/adapters/bot_check.rb and app/adapters/error_reporter.rb follow the same pattern.

What the fakes do not cover

They are deterministic, not simulations. Card declines, real webhook timing, actual email deliverability and real bot traffic all need the real service. So the fakes are right for development and for the test suite, and wrong as a substitute for one round of testing against test mode before you launch.

The one key production needs

RAILS_MASTER_KEY, and nothing else. Every other variable in docs/BRING_YOUR_OWN_KEYS.md is optional, and an app missing one runs on that integration's fake rather than raising. That is what makes it reasonable to deploy before you have decided on a payment provider.

Adding your own integration

Use the add-integration skill. It builds the same adapter and fake pair for a new service, which keeps the "works with no accounts" property true as the app grows. Calling a third-party API directly from a controller is the thing that breaks it.

Related questions

How do I stop bot signups on a Rails sign-up form?

Set TURNSTILE_SITE_KEY and TURNSTILE_SECRET_KEY. app/adapters/bot_check.rb returns a real Cloudflare Turnstile verifier when both are present and a pass-everything fake when they are not, so the form works in development with no account and starts blocking bots in production without a code change.

How do I store uploaded files on S3 instead of local disk?

Set S3_BUCKET, S3_REGION, AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, plus S3_ENDPOINT for a non-AWS provider. config/storage.yml already defines the service, so production uses object storage instead of the container's disk. Existing files on local disk do not move by themselves.

How do I tell which integrations are live in production?

Ask the adapters at runtime rather than reading environment variables. Each one chooses a real client or a local fake based on whether its credential is present, so querying the adapter tells you what the app is actually doing. A variable that is set but misspelled looks configured and behaves like a fake.