Backpex's own idioms for the library code in lib/, assets/js/, guides/ and the tests. mix lint already enforces formatting and Credo in strict mode with every check that .credo.exs leaves on; this file holds what the linters cannot see. Where an upstream rule linked below disagrees with this file, this file wins.
- Fields, filters, metrics and adapters describe data or return conditions and expressions; the adapter places them in the query it builds. Examples:
c:Backpex.Field.search_condition/3returns adynamic, the:selectfield option is adynamic,c:Backpex.Metric.data/2returns the data from the assigns. A new option or callback takes this shape: it receives values or assigns and returns a condition, an expression or data. - These still receive the adapter's query and return it changed:
c:Backpex.Filter.query/4,c:Backpex.Metric.query/3, theitem_queryoption ofBackpex.Adapters.Ectoand theoptions_queryoption ofBelongsTo,HasManyandHasManyThrough. They are the old shape; new code follows the one above. - Options are a NimbleOptions schema in
@config_schema, defined above@moduledoc, rendered into it with#{NimbleOptions.docs(@config_schema)}and passed touse Backpex.Field, config_schema: @config_schema(adapters:use Backpex.Adapter), which validates the configuration against it. The options ofuse Backpex.LiveResourcelive in@options_schemainlib/backpex/live_resource.ex.
- A public function without
@doc falseis API. Public functions that only other Backpex modules call get@doc false(e.g.Backpex.__/2,validate_config!/2). - CI builds the docs with
mix docs --warnings-as-errors, whichmix lintleaves out (mix ciruns it): every reference in@doc,@moduledocand the guides must resolve. A new guide goes intoextrasinmix.exs.
Backpex is 0.x: when the cleaner design breaks the API, take the cleaner design. A breaking PR gets the breaking-change label and a section in the upgrade guide of the next minor version. @version in mix.exs is the latest release; if guides/upgrading/v<next>.md does not exist yet, create it with the "Bump Your Deps" section of the previous guide and add it to the top of the upgrade guides in extras in mix.exs. Each section names the change in its heading, says why it changed and shows the code users change, as in guides/upgrading/v0.23.md.
Wrap every user-facing string in Backpex.__/2, with the LiveResource as second argument when one is in scope (@live_resource, socket.assigns.live_resource). Interpolate with a tuple: Backpex.__({"New %{resource}", %{resource: name}}, live_resource). Then run mix gettext.extract to update priv/gettext/backpex.pot; CI checks it with mix gettext.extract --check-up-to-date.
Build on the components in lib/backpex/html/, compose daisyUI components with Tailwind utilities, and use theme colors (primary, base-content, …). Look up daisyUI and Tailwind in the Context7 MCP.
Required for every markup change. integration_test/e2e/a11y_test.exs audits every view of the test app's LiveResources: list a new fixture there, and audit other new UI states with assert_a11y/1 from Backpex.E2ECase.
Solve interaction in HEEx and LiveView first; a phx-hook is for behaviour that needs the client. Hooks live in assets/js/hooks/_<name>.js and are exported from assets/js/hooks/index.js as Backpex<Name>. After any change in assets/js, follow CONTRIBUTING.md › JavaScript.
- CONTRIBUTING.md › Testing has the commands, the test app and its fixtures.
- A bug fix starts with a test that fails on
developfor that reason, in the existing test module of the area; then the fix. A purely visual fix (spacing, colour, alignment) shows before/after screenshots in the PR instead of a test. - Test at the lowest layer that fails:
test/when the logic runs without a LiveView or the database,integration_test/when it needs them,:e2eonly for what needs a browser (hooks, keyboard, accessibility, themes). - Browser tests (
Backpex.E2ECase) run on PhoenixTest.Playwright; readdeps/phoenix_test_playwright/usage-rules.mdbefore writing one. The generated block below cannot link it, since the package is a test-only dependency. - Library tests live in parallel directories, e.g.
test/html/(Backpex.HTML.FormTest) andtest/backpex/html/(Backpex.HTML.LayoutTest). Rungrep -rn "defmodule <Name>" test integration_testbefore adding a test file and extend the module that exists: a second module of the same name makesmix testfail depending on load order.
Generated by mix usage_rules.sync from the usage_rules: config in mix.exs: change the config, never the block. Read a package's file before working in its area: Ecto, HEEx, LiveView or the router (phoenix:*), the installer task in lib/mix/ (igniter), Sobelow findings (sobelow).
A code generation and project patching framework
Security-focused static analysis for Elixir & the Phoenix framework