madmin_inertia
Renders Madmin resources (index, show, new, edit, filters, search, pagination) as Inertia + React pages.
Requirements
- Rails 7.2+ with Active Storage and Active Job loaded (Madmin needs them)
- Nothing else to run the admin: it ships a prebuilt JS and CSS bundle, so it works in importmap apps with no Node, esbuild or Tailwind.
- To customize views: jsbundling-rails with esbuild. Importmap apps can run the admin but not customize its views.
Install
Add the gem next to Madmin, from RubyGems:
# Gemfile
gem "madmin"
gem "madmin_inertia"or straight from GitHub:
gem "madmin"
gem "madmin_inertia", github: "sethhorsley/madmin-inertia"Then:
bundle install
rails g madmin:install
rails g madmin_inertia:install # checks the app; there is no JS setupVisit /madmin.
Customizing views
Like Madmin's rails g madmin:views, copy a gem component into your app only when you need to change it:
rails g madmin_inertia:views # layout, dashboard, index, show, form
rails g madmin_inertia:views:layout # app/javascript/madmin/layouts/admin-layout.jsx
rails g madmin_inertia:views:dashboard # app/javascript/madmin/pages/dashboard/index.jsx
rails g madmin_inertia:views:index # app/javascript/madmin/pages/resource/index.jsx (all resources)
rails g madmin_inertia:views:index Post # app/javascript/madmin/pages/resource/post/index.jsx (only Post)
rails g madmin_inertia:views:show Post
rails g madmin_inertia:views:form Post # new and editEach generator registers the copied component for you. A model-specific view wins over a generic one, which wins over the gem's.
The first eject runs rails g madmin_inertia:bundle. It creates a six-line app/javascript/madmin.jsx, installs @inertiajs/react, react, react-dom, links the gem's madmin-inertia JS package (pnpm, yarn, bun or npm), patches the esbuild build script, and adds Tailwind @source lines when Tailwind is present. Components are copied as JSX under app/javascript/madmin/. Run yarn build (or pnpm build, npm run build) afterwards; once the app produces madmin.js, the layout loads it instead of the gem's prebuilt bundle (the gem's CSS still loads, so no Tailwind is required).
Ejecting needs a package.json (jsbundling-rails with esbuild). Importmap apps run the admin from the prebuilt bundle but can't customize its views, because there is no compiler for JSX; the generators stop with an error telling you to add jsbundling-rails.
Host contract
- Optionally define a private
admin_user_propsinMadmin::ApplicationControllerreturning{user: {name:, email:}, logout: path}to show the signed-in user in the default layout. - Define your own
Madmin::DashboardController#showto replace the gem's dashboard (the gem only supplies one when the app has none). -
Field,Value,Filters,indexUrl,buttonClassandinputClassare exported frommadmin-inertiafor ejected components. - Override
layouts/madmin/inertiaif your asset names differ (default loadsapplicationCSS and themadminJS bundle).
Without Inertia
Leave the gem out of the Gemfile; Madmin renders its own ERB pages.
Development
The prebuilt bundle in app/assets/builds comes from build/. After changing anything under app/javascript or index.jsx:
cd build && pnpm install && pnpm buildThe UI is shadcn/ui (build/components.json, JSX, in app/javascript/components/ui). Add components from build/ with pnpm dlx shadcn@latest add <name>; the generated @/ imports work as is. The root tsconfig.json maps @/* to app/javascript, which esbuild reads per file, so it holds even when an app bundles this source (the app's own @/ is unaffected). Vite ignores paths: add vite-tsconfig-paths, or alias @ to the gem's app/javascript for files inside the gem. The CLI writes import { cn } from "cn" (shadcn's own cn package); tsconfig.json maps cn to lib/utils (clsx + tailwind-merge) so it builds without that package.
Commit the rebuilt madmin_inertia.js and madmin_inertia.css. build/ has its own node_modules on purpose: apps link the gem root, and a second copy of React there would break hooks.