Ground Control Inertia
An Inertia.js + React Rails engine for managing Active Job queues, jobs, workers, and recurring tasks. Builds on ground_control-api and ships a themeable React component library.
Installation
Add the gem and npm package:
# Gemfile
gem "ground_control-inertia", github: "rarebit-one/ground_control-inertia"
npm install @rarebit-one/ground-control
Setup
1. Mount the engine
# config/routes.rb
mount GroundControl::Inertia::Engine, at: "/jobs"
2. Register pages in your Inertia resolver
The gem's React pages need to be included in your app's page resolver. In your Inertia entrypoint:
import { resolveGroundControlPages } from '@rarebit-one/ground-control'
createInertiaApp({
resolve: async (name) => {
// Your app's pages
const appPages = import.meta.glob('../pages/**/*.tsx')
// Ground Control pages
const gcPages = resolveGroundControlPages()
const allPages = { ...appPages, ...gcPages }
const pageLoader = allPages[`../pages/${name}.tsx`] || gcPages[`./pages/${name}.tsx`]
if (!pageLoader) {
throw new Error(`Missing page: ${name}`)
}
return pageLoader()
},
// ...
})
3. Import the theme CSS
/* In your application stylesheet */
@import '@rarebit-one/ground-control/theme.css';
4. Configure authentication
# config/initializers/ground_control.rb
GroundControl::Api.authenticate_with = ->(controller) do
controller.head :unauthorized unless controller.current_user&.admin?
end
Theming
The UI uses CSS custom properties with a --gc- prefix. Override any variable to match your app's look and feel:
:root {
/* Brand */
--gc-primary: #4f46e5;
--gc-primary-hover: #4338ca;
/* Shape */
--gc-radius: 0.5rem;
/* Surfaces */
--gc-bg: #ffffff;
--gc-fg: #111827;
--gc-border: #e5e7eb;
}
Available variables
| Variable | Default | Description |
|---|---|---|
--gc-bg |
#ffffff |
Page background |
--gc-bg-muted |
#f9fafb |
Muted background (cards, code blocks) |
--gc-bg-subtle |
#f3f4f6 |
Subtle background (hover states) |
--gc-fg |
#111827 |
Primary text |
--gc-fg-muted |
#6b7280 |
Secondary text |
--gc-primary |
#2563eb |
Primary action color |
--gc-primary-fg |
#ffffff |
Text on primary background |
--gc-primary-hover |
#1d4ed8 |
Primary hover state |
--gc-destructive |
#dc2626 |
Destructive action color |
--gc-success |
#16a34a |
Success state |
--gc-warning |
#d97706 |
Warning state |
--gc-border |
#e5e7eb |
Border color |
--gc-radius |
0.375rem |
Border radius |
--gc-radius-lg |
0.5rem |
Large border radius |
--gc-font |
inherit |
Font family (inherits from host) |
--gc-status-pending |
#2563eb |
Pending job badge |
--gc-status-failed |
#dc2626 |
Failed job badge |
--gc-status-in-progress |
#d97706 |
In-progress job badge |
--gc-status-finished |
#16a34a |
Finished job badge |
--gc-status-scheduled |
#7c3aed |
Scheduled job badge |
--gc-status-blocked |
#6b7280 |
Blocked job badge |
Pages
| Page | Path | Description |
|---|---|---|
| Queues index | /jobs/queues |
Queue list with pause/resume controls |
| Queue detail | /jobs/queues/:id |
Queue info with paginated pending jobs |
| Jobs index | /jobs/:status/jobs |
Filterable, paginated job list with bulk actions |
| Job detail | /jobs/jobs/:id |
Job info, error backtrace, retry/discard/dispatch actions |
| Workers index | /jobs/workers |
Worker list with heartbeat status |
| Worker detail | /jobs/workers/:id |
Worker config and assigned jobs |
| Recurring tasks | /jobs/recurring_tasks |
Task list with manual trigger |
| Task detail | /jobs/recurring_tasks/:id |
Task info with execution history |
Architecture
ground_control-inertia
├── app/controllers/ground_control/inertia/ # Inertia controllers
├── config/routes.rb # Engine routes
├── lib/ground_control/inertia/ # Engine, config
└── frontend/ # npm package (@rarebit-one/ground-control)
└── src/
├── pages/ground-control/ # React page components
├── components/ # Shared UI components
├── theme/variables.css # CSS custom property defaults
└── types.ts # TypeScript interfaces
↓ depends on
ground_control-api # Headless JSON API engine
↓ depends on
mission_control-jobs # Adapter layer, query objects
Components
The npm package exports reusable components that you can use in your own pages:
import {
DataTable,
Pagination,
StatusBadge,
CodeBlock,
ConfirmButton,
Filters,
Toolbar,
Layout,
} from '@rarebit-one/ground-control'
Configuration
GroundControl::Api.authenticate_with = ->(controller) { ... } # Auth callback
GroundControl::Api.page_size = 25 # Default: 10
GroundControl::Inertia.page_prefix = "ground-control" # Inertia page namespace
Development
bundle install # Ruby dependencies
cd frontend && npm install # JS dependencies
bundle exec rspec # Ruby tests
bundle exec rubocop # Ruby lint
cd frontend && npx tsc --noEmit # TypeScript check
License
MIT