Back to list
radioactive-labs

plutonium-assets

by radioactive-labs

Build production-ready Rails apps in minutes, not days. Convention-driven, fully customizable, AI-ready.

52🍴 7📅 Jan 23, 2026

SKILL.md


name: plutonium-assets description: Plutonium asset setup - TailwindCSS configuration, Stimulus controllers, and Phlexi component themes

Plutonium Assets & Setup

Plutonium uses TailwindCSS 4 for styling with a customizable theme system for components.

Note: For CSS design tokens (--pu-* variables) and component classes (.pu-btn, .pu-input, etc.), see the plutonium-theming skill.

Asset Configuration

Configure assets in the initializer:

# config/initializers/plutonium.rb
Plutonium.configure do |config|
  config.load_defaults 1.0

  # Custom assets
  config.assets.stylesheet = "application"    # Your CSS file
  config.assets.script = "application"        # Your JS file
  config.assets.logo = "my_logo.png"          # Logo image
  config.assets.favicon = "my_favicon.ico"    # Favicon
end

Setup Custom Assets

Run the assets generator to set up your own TailwindCSS build:

rails generate pu:core:assets

This:

  1. Installs required npm packages (@radioactive-labs/plutonium, TailwindCSS plugins)
  2. Creates tailwind.config.js that extends Plutonium's config
  3. Imports Plutonium CSS into your application.tailwind.css
  4. Registers Plutonium's Stimulus controllers
  5. Updates Plutonium config to use your assets

TailwindCSS Configuration

Generated Config

// tailwind.config.js
const { execSync } = require('child_process');
const plutoniumGemPath = execSync("bundle show plutonium").toString().trim();
const plutoniumTailwindConfig = require(`${plutoniumGemPath}/tailwind.options.js`)

module.exports = {
  darkMode: plutoniumTailwindConfig.darkMode,
  plugins: [
    // Add your plugins here
  ].concat(plutoniumTailwindConfig.plugins),
  theme: plutoniumTailwindConfig.merge(
    plutoniumTailwindConfig.theme,
    {
      // Your custom theme overrides
    },
  ),
  content: [
    `${__dirname}/app/**/*.{erb,haml,html,slim,rb}`,
    `${__dirname}/app/javascript/**/*.js`,
    `${__dirname}/packages/**/app/**/*.{erb,haml,html,slim,rb}`,
  ].concat(plutoniumTailwindConfig.content),
}

Customizing Colors

Override Plutonium's color palette:

// tailwind.config.js
theme: plutoniumTailwindConfig.merge(
  plutoniumTailwindConfig.theme,
  {
    extend: {
      colors: {
        primary: {
          50: '#eff6ff',
          100: '#dbeafe',
          200: '#bfdbfe',
          300: '#93c5fd',
          400: '#60a5fa',
          500: '#3b82f6',  // Your brand color
          600: '#2563eb',
          700: '#1d4ed8',
          800: '#1e40af',
          900: '#1e3a8a',
          950: '#172554',
        },
        secondary: {
          // Your secondary palette
        },
      },
    },
  },
),

Default Color Palette

Plutonium includes these semantic colors:

ColorUsage
primaryPrimary brand color (turquoise by default)
secondarySecondary color (navy by default)
successSuccess states (green)
infoInformational states (blue)
warningWarning states (amber)
dangerError/danger states (red)
accentAccent highlights (coral pink)

Dark Mode

Plutonium uses selector strategy for dark mode:

darkMode: "selector"

Toggle dark mode by adding/removing the dark class on <html>:

// Toggle dark mode
document.documentElement.classList.toggle('dark');

Plutonium includes a color mode selector component that handles this automatically.

CSS Imports

Application Stylesheet

/* app/assets/stylesheets/application.tailwind.css */
@import "gem:plutonium/src/css/plutonium.css";

@import "tailwindcss";
@config '../../../tailwind.config.js';

/* Your custom styles */

What Plutonium CSS Includes

  • Core utility classes
  • EasyMDE (markdown editor) styles
  • Slim Select styles
  • International telephone input styles
  • Flatpickr (date picker) styles

Component Themes (Phlexi)

Plutonium components use a theme system based on Phlexi for customizing Form, Display, and Table components. Each component type has a theme class with named style tokens.

Note: This is different from the CSS design token system (.pu-* classes). For pre-built component classes, see plutonium-theming.

Form Theme

class PostDefinition < ResourceDefinition
  class Form < Form
    class Theme < Plutonium::UI::Form::Theme
      def self.theme
        super.merge({
          # Container
          base: "bg-white dark:bg-gray-800 shadow-md rounded-lg p-6",
          fields_wrapper: "grid grid-cols-2 gap-6",
          actions_wrapper: "flex justify-end mt-6 space-x-2",

          # Labels
          label: "block mb-2 text-base font-bold",
          invalid_label: "text-red-700 dark:text-red-500",
          valid_label: "text-green-700 dark:text-green-500",
          neutral_label: "text-gray-500 dark:text-gray-400",

          # Inputs
          input: "w-full p-2 border rounded-md shadow-sm",
          invalid_input: "bg-red-50 border-red-500 text-red-900",
          valid_input: "bg-green-50 border-green-500 text-green-900",
          neutral_input: "border-gray-300 dark:border-gray-600",

          # Hints & Errors
          hint: "mt-2 text-sm text-gray-500",
          error: "mt-2 text-sm text-red-600",

          # Buttons
          button: "px-4 py-2 bg-primary-600 text-white rounded-md hover:bg-primary-700",
        })
      end
    end
  end
end

Display Theme

class PostDefinition < ResourceDefinition
  class Display < Display
    class Theme < Plutonium::UI::Display::Theme
      def self.theme
        super.merge({
          fields_wrapper: "grid grid-cols-3 gap-8",
          label: "text-sm font-bold text-gray-500 mb-1",
          string: "text-lg text-gray-900 dark:text-white",
          link: "text-primary-600 hover:underline",
          markdown: "prose dark:prose-invert max-w-none",
        })
      end
    end
  end
end

Table Theme

class PostDefinition < ResourceDefinition
  class Table < Table
    class Theme < Plutonium::UI::Table::Theme
      def self.theme
        super.merge({
          wrapper: "overflow-x-auto shadow-md rounded-lg",
          base: "w-full text-sm text-gray-500",
          header: "text-xs uppercase bg-gray-100 dark:bg-gray-700",
          header_cell: "px-6 py-3",
          body_row: "bg-white border-b dark:bg-gray-800",
          body_cell: "px-6 py-4",
        })
      end
    end
  end
end

Theme Keys Reference

Form Theme Keys

KeyDescription
baseForm container
fields_wrapperGrid wrapper for fields
actions_wrapperSubmit button container
wrapperIndividual field wrapper
inner_wrapperInner field wrapper
labelLabel base styles
invalid_labelLabel when field invalid
valid_labelLabel when field valid
neutral_labelLabel default state
inputInput base styles
invalid_inputInput when invalid
valid_inputInput when valid
neutral_inputInput default state
hintHint text
errorError message
buttonSubmit button
checkboxCheckbox input
selectSelect dropdown

Display Theme Keys

KeyDescription
fields_wrapperGrid wrapper
labelField label
descriptionField description
stringString values
textText values
linkURL links
emailEmail links
phonePhone links
markdownMarkdown content
jsonJSON display

Table Theme Keys

KeyDescription
wrapperTable container
baseTable element
headerHeader row
header_cellHeader cell
body_rowBody row
body_cellBody cell
sort_iconSort indicator

Using Tokens in Components

The tokens Helper

Conditionally apply classes:

class MyComponent < Plutonium::UI::Component::Base
  def initialize(active:)
    @active = active
  end

  def view_template
    div(class: tokens(
      "base-class",
      active?: "bg-primary-500 text-white",
      inactive?: "bg-gray-200 text-gray-700"
    )) {
      "Content"
    }
  end

  private

  def active? = @active
  def inactive? = !@active
end

The classes Helper

Returns a hash suitable for splatting:

div(**classes("p-4", "rounded", active?: "ring-2")) { }
# => <div class="p-4 rounded ring-2">

Conditional Tokens with Hash

tokens(
  "base",
  condition?: { then: "if-true", else: "if-false" }
)

Stimulus Controllers

Plutonium includes Stimulus controllers. Register them in your application:

// app/javascript/controllers/index.js
import { application } from "./application"

import { registerControllers } from "@radioactive-labs/plutonium"
registerControllers(application)

// Your custom controllers...

Available Controllers

  • color-mode - Dark/light mode toggle
  • form - Form handling (pre-submit, etc.)
  • nested-resource-form-fields - Nested form management
  • slim-select - Enhanced select boxes
  • flatpickr - Date/time pickers
  • easymde - Markdown editor
  • Various UI controllers

Custom Stimulus Controllers

Add your own controllers alongside Plutonium's:

// app/javascript/controllers/custom_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  connect() {
    console.log("Custom controller connected")
  }
}

Register in your index:

import CustomController from "./custom_controller"
application.register("custom", CustomController)

Typography

Plutonium uses Lato font by default. The layout loads it from Google Fonts.

Override in your layout:

class MyLayout < Plutonium::UI::Layout::ResourceLayout
  def render_fonts
    # Your custom fonts
    link(rel: "preconnect", href: "https://fonts.googleapis.com")
    link(href: "https://fonts.googleapis.com/css2?family=Inter&display=swap", rel: "stylesheet")
  end
end

Update Tailwind config:

theme: {
  fontFamily: {
    'body': ['Inter', 'sans-serif'],
    'sans': ['Inter', 'sans-serif'],
  }
}
  • plutonium-theming - CSS design tokens and component classes (.pu-*)
  • plutonium-views - Layout customization
  • plutonium-forms - Form theming
  • plutonium-installation - Initial setup

Score

Total Score

75/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon