Getting Started
1. Add the gem
# Gemfile
gem "terrazzo"bundle install2. Install Superglue (if you haven't already)
Terrazzo is built on top of Superglue. If your app already uses Superglue, skip to step 3.
rails g superglue:installRun this before installing Terrazzo's npm dependencies in a new app. The Superglue generator may run your package manager and replace node_modules; installing Terrazzo's frontend packages afterwards keeps the final dependency state consistent.
This sets up the core Superglue infrastructure:
- React/Redux application entry point (
app/javascript/application.jsx) - Page-to-page mapping, store, and application visit handler
- Flash message Redux slice
- HTML and JSON layouts
config/initializers/superglue.rb- JS dependencies (
react,react-dom,@reduxjs/toolkit,react-redux,@thoughtbot/superglue)
3. Install Vite Rails for the default Vite setup
If your app uses Rails esbuild instead, skip this step and pass --bundler=esbuild when you run the Terrazzo installer.
bundle add vite_rails
bundle exec vite installIf the Vite installer reports package-manager errors, resolve those before installing Terrazzo. The Terrazzo installer checks that package.json includes the Vite packages generated by vite_rails, including vite and vite-plugin-ruby.
4. Add the npm package
yarn add terrazzo
# or
npm install terrazzoThe terrazzo npm package provides the default React pages/components, utilities (cn, truncate, formatDate/DateTime/Time, csrfToken), hooks (useIsMobile), and the field registry API. The install generator creates app-level barrels that use those package defaults; eject a page, field, component, or UI primitive when you want app-owned source.
5. Install frontend dependencies
Terrazzo's default and ejected components use shadcn/ui patterns, so you'll need these packages. The generated admin CSS uses Tailwind CSS 4 syntax (@source, @theme, and @custom-variant), so install Tailwind 4 or newer:
yarn add @radix-ui/react-avatar @radix-ui/react-dialog @radix-ui/react-dropdown-menu \
@radix-ui/react-label @radix-ui/react-popover @radix-ui/react-select \
@radix-ui/react-separator @radix-ui/react-slot @radix-ui/react-tooltip \
class-variance-authority lucide-react tailwindcss@latestThe install generator also checks package.json and prints the exact package-manager command if any required frontend packages are missing or pinned below Terrazzo's supported versions.
Terrazzo also generates app/assets/stylesheets/admin.css, which the generated layout links as a Rails stylesheet asset. That file must be compiled by Tailwind before it is served. If your app does not already compile that exact file through a package script or Tailwind 4-compatible tailwindcss-rails, install the Tailwind CLI before running the Terrazzo installer:
yarn add -D @tailwindcss/cli@latestWhen @tailwindcss/cli 4 or newer is installed and no Tailwind pipeline is detected, the Terrazzo installer adds this package script for you and includes it in a new build script when the app does not already define one:
{
"scripts": {
"build": "vite build && tailwindcss -i app/assets/stylesheets/admin.css -o app/assets/builds/admin.css --minify",
"build:admin:css": "tailwindcss -i app/assets/stylesheets/admin.css -o app/assets/builds/admin.css --minify"
}
}The install generator warns when it cannot detect a Tailwind build script for app/assets/stylesheets/admin.css or Tailwind 4-compatible tailwindcss-rails. The @tailwindcss/vite plugin is useful for CSS imported through Vite, but by itself it does not compile Terrazzo's Rails-linked admin.css asset. For package.json script setups without compatible Tailwind tooling, the installer prints the matching install command for your package manager.
6. Run the Terrazzo install generator
Make sure your database schema is loaded before installing, because Terrazzo inspects your models' columns and associations to generate dashboards:
bin/rails db:prepareRun the installer after your app has at least one concrete ApplicationRecord model. Terrazzo generates dashboards and admin routes from those models; if none exist yet, add a model first and run the installer afterwards.
rails g terrazzo:installBy default the generator assumes Vite and requires the vite_rails installer output, including config/vite.json, because the generated admin layout uses Vite Rails asset helpers. If your app uses Rails esbuild instead:
rails g terrazzo:install --bundler=esbuildThe generated page mapping resolves resource pages through shared application components by default. Resource-specific pages generated by Terrazzo are registered in generated_page_mapping.js; manual custom pages belong in custom_page_mapping.js.
This creates an isolated admin namespace alongside your existing app — it won't conflict with any existing Superglue pages or controllers:
Admin Superglue infrastructure (namespaced under admin/):
app/javascript/admin/application.jsx— separate Superglue entry point for the adminapp/frontend/entrypoints/admin/application.jsx— default Vite entrypoint shim generated only with--bundler=vite; custom VitesourceCodeDir/entrypointsDirsettings are respectedconfig/vite.json— updated with admin JS/viewwatchAdditionalPathswhen those generated files live outside Vite'ssourceCodeDirProcfile.devandbin/dev— for Vite installs, ensures local development starts Rails andbin/vite devtogether; custombin/devscripts are left untouched with a warningapp/javascript/admin/page_to_page_mapping.js— maps admin pages to React components with shared-page fallbacksapp/javascript/admin/generated_page_mapping.js— resource-specific page manifest maintained by Terrazzo generatorsapp/javascript/admin/custom_page_mapping.js— manual custom page manifest you ownapp/javascript/admin/application_visit.js— visit/remote factoryapp/javascript/admin/slices/flash.js— flash message Redux sliceapp/javascript/admin.js— esbuild root entrypoint generated only with--bundler=esbuildapp/views/layouts/admin/application.html.erb— admin HTML layoutapp/views/layouts/admin/application.json.props— admin JSON props layout
Admin controllers and routes:
app/controllers/admin/application_controller.rb— inherits fromTerrazzo::ApplicationControllerconfig/routes.rb— adds anadminnamespace with a root route
Admin UI components and views:
app/assets/stylesheets/admin.css— Tailwind theme that scans Terrazzo package defaults plus local admin views and JavaScriptcomponents.json— shadcn CLI aliases for admin components and UI primitives; existing configs are left untouchedjsconfig.json— root@/*alias for shadcn-style tooling when no JS/TS config already existsapp/views/admin/application/— shared page stubs and navigation partialapp/views/admin/components/— app component barrel for package defaults and local overridesapp/views/admin/components/ui/— app UI barrel for package defaults and local shadcn-style primitives used by app-owned/ejected filesapp/views/admin/fields/— app field barrel for package defaults and local field overrides
Dashboards — automatically generates a dashboard for each ApplicationRecord model it finds.
7. Generate additional dashboards
The install generator (step 6) automatically creates dashboards for all existing ApplicationRecord models. To add dashboards for new models later:
rails g terrazzo:dashboard Product
rails g terrazzo:dashboard Customer
rails g terrazzo:dashboard OrderEach generates:
app/dashboards/product_dashboard.rb— field definitionsapp/controllers/admin/products_controller.rb— inherits from your adminApplicationController
The shared page mapping fallback handles the standard CRUD pages. Generate a resource-specific view only when you need custom props or custom React for that resource.
8. Start the server
bin/devFor Vite installs, Terrazzo adds vite: bin/vite dev to Procfile.dev and replaces the stock Rails-only bin/dev with a Foreman runner. If your app already had a custom bin/dev, the generator leaves it in place and warns you to start Vite alongside Rails.
Visit http://localhost:3000/admin to see your admin panel.