Backpex builds admin panels in Phoenix LiveView apps. A LiveResource module configures the index, show and form views of one Ecto schema; fields, filters, actions and metrics are modules implementing Backpex behaviours. Docs and guides of the released version: https://hexdocs.pm/backpex (https://hexdocs.pm/backpex/llms.txt lists every guide as Markdown). Read the guide of the area you work in; the module docs list every option.
mix igniter.install backpex(ormix backpex.installonce the dependency is added) runs the steps of the installation guide, except theLiveSocketparams: set those yourself.app.js:import { Hooks as BackpexHooks, backpexParams } from 'backpex', thennew LiveSocket('/live', Socket, { params: backpexParams({ _csrf_token: csrfToken }), hooks: { ...Hooks, ...BackpexHooks } }).backpexParamstakes a params object; for params computed in a function, mergeBackpexPreferences.connectParams()into its result.- Styles need Tailwind CSS 4 and daisyUI 5, with
@source "../../deps/backpex/**/*.*ex";and@source "../../deps/backpex/assets/js/**/*.*js";in the stylesheet.@tailwindcss/formsconflicts with daisyUI. config :backpex, :pubsub_server, MyApp.PubSub, andimport_deps: [:backpex]in.formatter.exs.
import Backpex.Router
scope "/admin", MyAppWeb do
pipe_through [:browser, :require_admin]
backpex_routes()
live_session :admin, on_mount: Backpex.InitAssigns do
live_resources "/posts", PostLive
live_resources "/categories", CategoryLive, only: [:index, :show]
end
endbackpex_routes/0adds the preferences endpoint: once per scope, behind the same authentication plugs as the LiveResources.Backpex.InitAssignsassigns@current_urland the preference assigns the layout reads.live_resources/3takesonly:andexcept:with:index,:new,:edit,:show.
defmodule MyAppWeb.PostLive do
use Backpex.LiveResource,
adapter_config: [
schema: MyApp.Blog.Post,
repo: MyApp.Repo,
update_changeset: &MyApp.Blog.Post.update_changeset/3,
create_changeset: &MyApp.Blog.Post.create_changeset/3
]
@impl Backpex.LiveResource
def layout(_assigns), do: {MyAppWeb.Layouts, :admin}
@impl Backpex.LiveResource
def singular_name, do: "Post"
@impl Backpex.LiveResource
def plural_name, do: "Posts"
@impl Backpex.LiveResource
def fields do
[
title: %{module: Backpex.Fields.Text, label: "Title", searchable: true},
category: %{
module: Backpex.Fields.BelongsTo,
label: "Category",
display_field: :name,
live_resource: MyAppWeb.CategoryLive
}
]
end
end- Return the layout from
c:Backpex.LiveResource.layout/1; thelayout:option is deprecated. The layout wraps its content inBackpex.HTML.Layout.app_shell/1and rendersBackpex.HTML.Layout.flash_messages/1. singular_name/0andplural_name/0have no default. Every other callback has one:fields/0,filters/0(orfilters/1with assigns),panels/0,metrics/0,item_actions/1,resource_actions/0,can?/3, theon_item_*hooks,return_to/5,render_resource_slot/3,translate/1.- The options of
use Backpex.LiveResource(primary_key,init_order,per_page_default,full_text_search,fluid?,persist,context_assigns, …) are validated against the schema in theBackpex.LiveResourcedocs. Setprimary_key:when the key is not:id; Backpex supports one primary key column, not compound keys. adapter_configbelongs toBackpex.Adapters.Ecto:schemaandrepoare required; the changeset functions take(item, attrs, metadata), wheremetadataholds:assignsand:target;item_querytakes(query, live_action, assigns)and builds on the given query (from p in query, where: ...).
fields/0returns a keyword list ofname: %{module: Backpex.Fields.<Type>, label: "..."}. Built-in types:Text,Textarea,Number,Currency,Email,URL,Boolean,Date,DateTime,Time,Select,MultiSelect,Checkgroup,Upload,BelongsTo,HasMany,HasManyThrough,InlineCRUD.- Options shared by all fields are in
Backpex.Field(e.g.searchable,orderable,only/exceptwith:new,:edit,:show,:index,visible,can?,readonly,panel,index_editable,selectfor computed values,help_text,default); options of a type are in its module docs. An unknown or mistyped option raises with the field and LiveResource name. - A custom field does
use Backpex.Field, config_schema: @config_schemawith a NimbleOptions schema and implementsrender_value/1andrender_form/1(custom fields guide).
filters/0returnsfield_name: %{module: MyAppWeb.Filters.Published, label: "Published?"}, optionally withdefault:andpresets:. A filter module uses a built-in base and implements its callbacks:Backpex.Filters.Boolean(options/1returning maps withlabel,keyand adynamicpredicate),Backpex.Filters.SelectandBackpex.Filters.MultiSelect(prompt/0,options/1),Backpex.Filters.Range(type/0::number,:dateor:datetime). A fully custom filter doesuse BackpexWeb, :filterand implementsquery/4,render/1andrender_form/1.item_actions(default_actions)receivesshow:,edit:anddelete:and returns the keyword list to use, e.g.Keyword.delete(default_actions, :delete) ++ [archive: %{module: MyAppWeb.ItemActions.Archive, only: [:row, :show]}]. An item action module doesuse BackpexWeb, :item_actionand implementsicon/2,label/2and eitherhandle/3orlink/2;fields/0andchangeset/3add a form.resource_actions/0returnsinvite: %{module: MyAppWeb.ResourceActions.Invite}; the module doesuse Backpex.ResourceActionand implementstitle/0,label/0,fields/0,changeset/3andhandle/2.metrics/0returnstotal: %{module: Backpex.Metrics.Value, label: "Total", select: dynamic([p], sum(p.amount)), format: &to_string/1}.
can?/3defaults totrue, so a LiveResource allows every action until it overrides the callback:def can?(assigns, action, item)withactionin:index,:new,:show,:edit,:deleteor the key of an item or resource action. Return a boolean; any other value raises.- Backpex checks it before every write and raises
Backpex.ForbiddenErrorfor an unauthorized item;:indexand:showare checked in the views. Fields restrict themselves with thecan?option, filters with thecan?/1callback. Authenticate in the router pipeline.
Backpex passes every text as {msg, opts} to the functions in config :backpex, translator_function: {MyAppWeb.CoreComponents, :translate_backpex}, error_translator_function: {MyAppWeb.CoreComponents, :translate_error}; the msgids are in deps/backpex/priv/gettext/backpex.pot. A LiveResource changes single texts with translate/1. See the translations guide.
Backpex.Testingfinds the paths and elements of a LiveResource forPhoenix.LiveViewTest:path/5,select_item/2,click_item_action/3,confirm_item_action/1,submit_form/2.- Backpex is 0.x and minor versions break APIs: read every upgrade guide between the old and the new version (
https://hexdocs.pm/backpex/v0-<minor>.html) before bumping the dependency. - Claude Code users get skills for LiveResources, fields, filters, actions and upgrades from the Backpex plugin:
/plugin marketplace add naymspace/backpex, then/plugin install backpex@naymspace-backpex.