julianrubisch/skills · Archived

jr-rails-phlex

>- Write Phlex views and components for Rails: class hierarchy, slots, helpers, custom elements, scaffold generator. Use when building UI with phlex-rails.

First seen Mar 30, 2026

Installation

$ npx skills add julianrubisch/skills --skill jr-rails-phlex

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from julianrubisch/skills.

npx skills add julianrubisch/skills

Browse all from julianrubisch/skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 27
License LICENSE
Default branch main
Open issues 0
Status Archived

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 8,290 B
  • docs SUMMARY.md 174 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 29 installs

SKILL.md

Phlex Views & Components

Components are Ruby objects — no template language, no DSL. Views replace ERB templates (one per controller action). Components are reusable UI building blocks.

Core Workflow

  1. Use the scaffold generator — custom PhlexControllerGenerator produces

Phlex views instead of ERB. See [reference/coding-phlex.md § Scaffolding](reference/coding-phlex.md) for the full generator code and all 5 templates.

  1. Implementation order — models → controllers → views/components → tests.
  2. Forms default to ERB partials — Rails form builders are ergonomic there.

Phlex form helpers exist for simple cases.

Class Hierarchy

Components::Base < Phlex::HTML   (include Components, route helpers, dev comments)
  ├── Views::Base                (+ Debug, ContentFor, caching)
  ├── Components::Layout         (+ Phlex::Rails::Layout)
  └── Components::PageHeader, TitleBar, List, GridCell, ...
# app/components/base.rb
class Components::Base < Phlex::HTML
  include Components
  include Phlex::Rails::Helpers::Routes

  if Rails.env.development?
    def before_template
      comment { "Before #{self.class.name}" }
      super
    end
  end
end

# app/views/base.rb
class Views::Base < Components::Base
  include Phlex::Rails::Helpers::Debug

  def cache_store = Rails.cache
end

Short-form Component Calls

include Components on the base class enables method-style rendering:

# Instead of:
render Components::PageHeader.new(title: "Labels")

# Write:
PageHeader(title: "Labels")

Component Slots via Methods

Public methods on components yield named content areas:

class Components::TitleBar < Components::Base
  def view_template(&) = div(class: "title-bar", &)
  def leading_action(&) = div(class: "leading-action", &)
  def title(&) = h1(&)
  def actions(&) = div(class: "actions", &)
end

# Usage:
render Components::TitleBar.new do |bar|
  bar.leading_action { link_to("Back", labels_path) }
  bar.title { "My Page" }
  bar.actions { button_to("Delete", @label, method: :delete) }
end

Helper Includes

Include only the Phlex::Rails::Helpers::* each view needs — never on Base:

class Views::Labels::Show < Views::Base
  include Phlex::Rails::Helpers::ContentFor
  include Phlex::Rails::Helpers::DOMID
  include Phlex::Rails::Helpers::ButtonTo
  include Phlex::Rails::Helpers::LinkTo
  include Phlex::Rails::Helpers::TurboFrameTag
  # ...
end

Common helpers: Routes, ContentFor, DOMID, ButtonTo, LinkTo, TurboFrameTag, TurboStreamFrom, ImageTag, ClassNames, Request, Notice, Debug, Sanitize, StripTags.

Content Areas

Layout yields named areas; views populate via content_for:

content_for :title, "Labels"

content_for :main_header do
  render Components::PageHeader.new do |header|
    header.title_bar { |bar| bar.title { "Labels" } }
  end
end

content_for :floating_action do
  render Components::FloatingActionMenu.new
end

Standard areas: :title, :mainheader, :floatingaction, :head.

Controller Rendering

Controllers render Phlex views directly, passing data via new:

class LabelsController < ApplicationController
  def index
    @pagy, @labels = pagy(Label.all)
    render Views::Labels::Index.new(@labels, @pagy)
  end

  def show
    render Views::Labels::Show.new(@label)
  end

  def create
    @label = Label.new(label_params)
    if @label.save
      redirect_to @label, notice: "Label was successfully created."
    else
      render Views::Labels::New.new(@label), status: :unprocessable_entity
    end
  end
end

Custom Element Wrappers

Use register_element for web component custom elements (Web Awesome, Shoelace, etc.):

module Components::MyLibrary
  class MyButton < Phlex::HTML
    register_element :my_button  # renders <my-button>

    def initialize(variant: "neutral", size: "medium", **attributes)
      @attributes = attributes.with_defaults(variant: variant, size: size)
    end

    def view_template(&) = my_button(**@attributes, &)
  end
end

Use phlexcustomelementgenerator to auto-generate wrappers from custom element manifests.

Register Helpers

For Rails helpers that output HTML or return values:

register_output_helper :vite_client_tag       # returns HTML
register_output_helper :vite_javascript_tag
register_output_helper :column_chart          # chartkick
register_value_helper :alert                  # returns a value

ERB Partials for Forms

Phlex views render ERB form partials seamlessly:

# In a Phlex view:
section { render partial("form", label: @label) }

# The ERB partial uses standard form_with / form_for

Fragment Caching

def view_template
  cache("labels/#{@label.id}/card") {
    # expensive rendering
  }
end

Multiple Layouts

class Components::Layout < Components::Base
  include Phlex::Rails::Layout
  # app shell
end

class Components::MarketingLayout < Components::Base
  include Phlex::Rails::Layout
  # landing pages
end

Set in controllers: layout -> { Components::Layout }

Frontend Integration

Stimulus

div(data: {
  controller: "faceted-search",
  action: "input->faceted-search#perform:prevent",
  faceted_search_url_value: labels_path
}) { ... }

Turbo Frames (Lazy Loading)

turbo_frame_tag(album, src: album_path(album), loading: :lazy) {
  render Components::Spinner.new
}

Turbo Streams & Morphing

turbo_stream_from([@budget, :items])

# In layout <head>:
meta name: "turbo-refresh-method", content: "morph"
meta name: "turbo-refresh-scroll", content: "preserve"

Pagy

class Views::Labels::Index < Views::Base
  include Pagy::Frontend

  def initialize(labels, pagy)
    @labels = labels
    @pagy = pagy
  end

  def view_template
    # ... render labels ...
    raw safe(pagy_nav(@pagy))
  end
end

Heuristics

  • Component vs View: reusable UI = component; page-level (one per action) = view
  • When to use ERB: forms with Rails form builder, complex form logic
  • Naming: Components::PageHeader, Views::Labels::Index
  • One view per controller action; views receive data via initialize
  • Composition over inheritance — slot methods, not deep class hierarchies
  • Data flow: controller → view (initialize) → components (render)

Anti-patterns

  • God components — split into smaller, focused components
  • Business logic in views/components — belongs in models
  • Over-including helpers on Base — include per-view
  • Reimplementing form builders — use ERB partials for forms
  • Passing request context into components — components receive data, not request objects

Preferred Stack

Concern Choice
Components phlex-rails 2.x
Bundling vite_rails / importmap / esbuild
Pagination Pagy
Custom elements library of choice + phlexcustomelement_generator
Scaffolding Custom PhlexControllerGenerator
Frontend turbo-rails + stimulus-rails
Feature flags Flipper (inline: if Flipper.enabled?(:feature))

Deep Reference Files

Read these on demand when the task requires deeper guidance:

  • Full Phlex coding guide (generator templates, all examples): [reference/coding-phlex.md](reference/coding-phlex.md)
  • Design patterns (form objects, query objects, strategies): [reference/patterns.md](reference/patterns.md)
  • Testing guide: [reference/shared/testing.md](reference/shared/testing.md)
  • Hotwire (Turbo + Stimulus): [reference/shared/hotwire.md](reference/shared/hotwire.md)
  • Components reference: [reference/shared/components.md](reference/shared/components.md)
  • Architecture layers: [reference/shared/architecture.md](reference/shared/architecture.md)

For frontend patterns (Stimulus controllers, Turbo Frames/Streams), invoke the relevant hwc-* skill alongside this one.