0.0
The project is in a healthy, maintained state
Studio Engine is a non-isolated Rails engine that ships an opinionated authentication + SSO contract, a polymorphic ErrorLog model, a Sluggable concern, a 7-role dynamic theme system with CSS-custom-property generation, and an S3-backed ImageCache. Used in production across the McRitchie Studio + Turf Monster apps.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

 Project Readme

Studio Engine

Shared Rails engine for McRitchie apps. Provides authentication, error handling, dynamic theming, and common concerns used by McRitchie Studio and Turf Monster.

Part of the McRitchie ecosystem — see ECOSYSTEM.md for the 5-repo map; house-burn-down.md for fresh-Mac recovery.

Installation

# Gemfile — install from RubyGems (recommended)
gem "studio-engine", "~> 0.4.0"

Then bundle install. The current release is v0.4.10; see CHANGELOG.md for the history.

Published to RubyGems as of v0.4.0 (2026-05-17). Earlier consumers used a git: ref pinned to a tag; that pattern is preserved here for reference but new installs should use the RubyGems form, which the consumer Rails apps (mcritchie-studio, turf-monster, tax-studio) already use.

What It Provides

  • Authentication: Session-based login/signup controllers and views, Google OAuth via OmniAuth, one-way SSO (hub to satellite)
  • Error handling: Studio::ErrorHandling concern with rescue_and_log, ErrorLog model with capture!, error log viewer at /error_logs
  • Theme system: Dynamic CSS custom properties generated from 7 role colors (primary, dark, light, success, accent, warning, danger). Dark/light mode toggle. Admin theme editor at /admin/theme.
  • Sluggable concern: before_save :set_slug with to_param for human-readable URLs
  • ThemeSetting model: Per-app DB overrides with fallback to config defaults

Configuration

Each consuming app configures the engine in config/initializers/studio.rb:

Studio.configure do |config|
  config.app_name = "My App"
  config.session_key = :my_app_user_id
  config.sso_logo = "/logo.svg"
  config.welcome_message = ->(user) { "Welcome, #{user.display_name}!" }
  config.registration_params = [:name, :email, :password, :password_confirmation]
  config.theme_primary = "#4BAF50"   # Override default violet
  config.theme_logos = ["logo.svg"]
end

Routes

In the consuming app's config/routes.rb:

Rails.application.routes.draw do
  Studio.routes(self)
  # ... app routes
end

This draws: /login, /signup, /logout, /sso_continue, /sso_login, /auth/:provider/callback, /auth/failure, /error_logs, /admin/theme (GET, PATCH), /admin/theme/regenerate.

Overriding Views

This is a non-isolated engine -- app views at the same path automatically override engine views. For example, placing app/views/sessions/new.html.erb in the consuming app replaces the engine's login page.

Releasing

Engine releases are git tags (semver: MAJOR.MINOR.PATCH). Both consumer apps pin to a tag in their Gemfile — bumping the tag is the release.

  1. Make + commit changes on main.
  2. Update CHANGELOG.md with the new version + a ### Added / ### Changed / ### Removed summary. Keep entries terse.
  3. Bump lib/studio/version.rb to match.
  4. Commit the version bump + CHANGELOG together (v0.X.Y: <summary>).
  5. Tag: git tag -a v0.X.Y -m "<one-line summary>".
  6. Push: git push origin main --tags.
  7. In each consumer app's Gemfile, update the tag: field. Commit + push.
  8. On consumer prod: bundle install runs as part of the deploy buildpack.

Semver guide

  • PATCH: bug fix; no API change. Consumers can bump tag with zero diff elsewhere.
  • MINOR: backward-compatible feature add. Consumers may opt in to new APIs.
  • MAJOR: breaking change. Consumers will need code changes alongside the tag bump.

Local development (against an unreleased engine)

When iterating on engine code from a consumer app, point bundler at the local path so you don't need to push + tag for every edit:

# in the consumer app
bundle config set --local local.studio /Users/alex/projects/studio-engine
bundle install
# ... iterate in both repos ...
bundle config unset --local local.studio  # restore tag-pinned resolution

Note: bundle config local.studio requires branch: in the Gemfile entry. If you frequently develop locally, change the Gemfile to gem "studio-engine", git: "...", branch: "main" during dev and back to tag: before merging.

Development Notes

See CLAUDE.md for detailed development context including the theme architecture, SSO protocol, color scale system, and code conventions.