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