A self-hostable children's ministry portal built as a Rails Engine gem. Family profiles, children management, event registration, and Planning Center sync — all in a single deployable package.
Part of the 5stones Software suite. MIT licensed. No dependency on any hosted platform.
| Repo | What it is |
|---|---|
kidspire (this repo) |
Kids ministry portal. Standalone. Self-hostable. MIT. |
churchcred |
Standalone points/badges gem. Self-hostable. MIT. Works alongside Kidspire. |
| More coming | Youthspire, Seniorspire — built on the same Inspire framework |
Built by 5stones Software — open source tools churches can actually own.
- Family profiles — parents create accounts, add children, manage contact info
- Children management — name, birthdate, grade, allergies/notes per child
- Event registration — public event listings with per-child signup forms
- Planning Center sync — connect your PCO account; family and child records sync automatically
- Passwordless auth — email magic link via Rodauth — no password required
| Layer | Technology |
|---|---|
| Backend | Ruby on Rails (API + Engine) |
| Frontend | React + Vite + TypeScript |
| Styling | Tailwind CSS + shadcn/ui |
| Auth | Rodauth (passwordless email magic link) |
| Database | PostgreSQL |
| Background jobs | Sidekiq + Redis |
| Deployment | Railway (Procfile + railway.toml included) |
The fastest path is one-click Railway deploy:
- Click Deploy on Railway above
- Fill in the required environment variables in the Railway template form
- Railway provisions PostgreSQL, Redis, and both services automatically
- Once deployed, open a Railway shell and grant admin to your account:
railway run bundle exec rails console # then: Account.find_by(email: 'you@yourchurch.org').update!(admin: true)
Prerequisites: PostgreSQL, Redis, Node.js, and overmind running locally.
git clone https://github.com/5stones-io/kidspire
cd kidspire
cp .env.example .envEdit .env and set at minimum:
DATABASE_URL— replaceyour_pg_usernamewith your local Postgres username (whoamion Mac/Linux)SECRET_KEY_BASE— generate withopenssl rand -hex 64ENCRYPTION_KEY— generate withopenssl rand -hex 32
bundle install
bun install
npx playwright install chromium # for UI testing
bundle exec rails db:create db:migrate db:seed
overmind start -f Procfile.dev # Rails :3000, Vite :3036, SidekiqAdd to your Gemfile:
gem 'kidspire'Mount in config/routes.rb:
mount Kidspire::Engine => '/'Run the engine migrations:
bundle exec rails kidspire:install:migrations
bundle exec rails db:migrateConfigure in an initializer:
# config/initializers/kidspire.rb
Kidspire.configure do |config|
config.pco_client_id = ENV['PCO_CLIENT_ID'] # optional
config.pco_client_secret = ENV['PCO_CLIENT_SECRET'] # optional
config.pco_redirect_uri = ENV['PCO_REDIRECT_URI'] # optional
config.encryption_key = ENV['ENCRYPTION_KEY']
config.frontend_base_url = ENV['FRONTEND_BASE_URL']
end| Variable | Description |
|---|---|
DATABASE_URL |
Postgres connection string. Auto-set by Railway PostgreSQL plugin. |
REDIS_URL |
Redis connection string. Auto-set by Railway Redis plugin. |
SECRET_KEY_BASE |
Rails secret key. Generate: openssl rand -hex 64 |
ENCRYPTION_KEY |
32-byte hex key for encrypting PCO tokens. Generate: openssl rand -hex 32 |
FRONTEND_BASE_URL |
Public URL of your deployment. e.g. https://your-app.up.railway.app |
VITE_API_BASE_URL |
API base URL baked into the frontend at build time. e.g. https://your-app.up.railway.app/api/v1 |
| Variable | Description |
|---|---|
SMTP_ADDRESS |
SMTP host. e.g. smtp.resend.com (Resend recommended — free tier) |
SMTP_PORT |
SMTP port. 465 for Resend. |
SMTP_USERNAME |
SMTP username. resend for Resend. |
SMTP_PASSWORD |
SMTP password / API key. |
SMTP_DOMAIN |
Your verified sending domain. |
MAILER_FROM |
From address. e.g. noreply@yourchurch.org |
| Variable | Description |
|---|---|
PCO_CLIENT_ID |
Planning Center OAuth client ID. Required for PCO sync. |
PCO_CLIENT_SECRET |
Planning Center OAuth client secret. Required for PCO sync. |
PCO_REDIRECT_URI |
e.g. https://your-app.up.railway.app/auth/pco/callback |
PCO_KIDS_MINISTRY_TAG |
PCO tag name to filter events. Defaults to pulling all events. |
TWILIO_ACCOUNT_SID |
Twilio SID for SMS invite links. |
TWILIO_AUTH_TOKEN |
Twilio auth token. |
TWILIO_FROM_NUMBER |
Twilio phone number. |
CORS_ORIGINS |
Allowed CORS origins. Defaults to FRONTEND_BASE_URL. |
RAILS_LOG_LEVEL |
Defaults to info. |
DEBUG_PCO_SYNC |
Set true for verbose PCO sync logs. |
- Go to api.planningcenteronline.com/oauth/applications
- Click New Application
- Set redirect URIs:
https://your-app.up.railway.app/auth/pco/callback https://your-app.up.railway.app/auth/pco/login/callback - Select scopes:
people,check_ins,services - Copy the Client ID and Client Secret
- Log in as admin
- Navigate to PCO Sync → PCO API Configuration
- Paste Client ID and Client Secret → Save
Click Connect PCO — approve the PCO consent screen. Kidspire stores your access and refresh tokens automatically.
| Service | Command |
|---|---|
web |
bundle exec rails db:migrate && bundle exec puma -C config/puma.rb |
worker |
bundle exec sidekiq |
Railway runs one process per service. Sidekiq needs its own service:
- In your Railway project, click + New → GitHub Repo → select this same repo
- Name it
worker - Override Start Command to:
bundle exec sidekiq - Override Build Command to:
bundle install - Share the same
DATABASE_URLandREDIS_URLenvironment variables from the PostgreSQL and Redis plugins
Without the worker service, background PCO sync jobs will not run. The web app still functions — sync must be triggered manually via the admin panel.
Configure in config/environments/production.rb:
config.hosts = [
"your-app.up.railway.app",
"your-custom-domain.com"
]Rails default /up endpoint. Railway health checks hit this automatically.
Kidspire and churchcred are designed to run alongside each other. Kidspire handles family identity and event management. churchcred handles points, badges, and check-in rewards. They share the same PCO connection and the same family/child data model.
To run both:
# Gemfile
gem 'kidspire'
gem 'churchcred'# config/routes.rb
mount Kidspire::Engine => '/'
mount Churchcred::Engine => '/churchcred'Kidspire follows Semantic Versioning. See CHANGELOG.md for the full release history.
| Bump | When |
|---|---|
| MAJOR | Breaking API, mount interface, or schema changes requiring manual intervention |
| MINOR | New features or endpoints (backwards compatible) |
| PATCH | Bug fixes, security patches, dependency updates |
Pre-1.0 (
0.x.y): minor bumps may include breaking changes while the API stabilises.
Uses gem-release to bump, tag, and push in one step.
1. Update CHANGELOG.md — move entries from [Unreleased] into a new versioned section and update the diff links at the bottom.
2. Bump the version and release:
# Patch release (0.1.0 → 0.1.1) — bug fixes only
gem bump --version patch --tag --push && gem release
# Minor release (0.1.0 → 0.2.0) — new features
gem bump --version minor --tag --push && gem release
# Major release (0.1.0 → 1.0.0) — breaking changes
gem bump --version major --tag --push && gem releaseThis will:
- Update
lib/kidspire/version.rb - Commit and tag
v0.x.y - Push the commit and tag to GitHub
- Build and push the gem to RubyGems
3. Create a GitHub release — go to github.com/5stones-io/kidspire/releases and publish release notes from the CHANGELOG entry.
Open issues before large PRs. See 5stones.io for the broader suite roadmap.
MIT — see LICENSE
5stones Software · Open source tools for the local church