Migrate Phoenix Generated UI To PUI

Copy Markdown

This guide covers the practical migration path from the default phx.new UI layer to PUI components.

What To Replace

  • Generated core_components.ex helpers such as custom flash, button, input, and icon wrappers
  • phx.new layout markup like the topbar, flash area, and generated shell structure
  • App-local sidebar or submenu hooks that can move into bundled PUI hooks

Core Migration Steps

1. Import PUI in shared web entrypoints

def live_view do
  quote do
    use Phoenix.LiveView
    use PUI
  end
end

2. Replace generated flash and loading UI

<PUI.Loading.topbar />
<PUI.Flash.flash_group flash={@flash} />

Use live={true} only inside LiveView-rendered trees. Shared layouts that also render controller templates should use the default non-live flash group.

3. Move app shell markup to PUI.Layout

<.app_layout id="app-shell">
  <:sidebar>
    <.sidebar>
      ...
    </.sidebar>
  </:sidebar>

  <:header>
    <.content_header shell_id="app-shell" breadcrumb_current="Dashboard" />
  </:header>

  ...
</.app_layout>

4. Remove app-local submenu hooks

If you were relying on a colocated sidebar collapse hook, move to sidebar_menu_item/1 and the bundled PUI.Sidebar hook by registering PUIHooks in your LiveSocket.

Notes

  • Migrate incrementally and compile after each phase.
  • Replace generated auth and layout UI with plain HEEx plus PUI primitives rather than re-creating phx.new helper wrappers.
  • Keep app-specific copy and information architecture local; use PUI for behavior and surfaces.