Form-first UI components for Phoenix LiveView (1.1+) on Phoenix 1.8+: rich select, date picker, OTP input, dialogs, menus, tables, toasts and top-layer panels — server-authoritative, viewport-aware, themeable from 12 CSS tokens, with zero third-party JavaScript (one JS import, ~9 KB min+gzip).
A daisyUI replacement you install and manage through mix tasks built on
Igniter — including --strip-daisy to remove Phoenix 1.8's bundled daisyUI.
Install
One command — Igniter adds the dep and wires everything (CSS, JS hooks,
component imports, flash → Skua toasts, strips the default Phoenix navbar, and
scaffolds an editable starter home at /):
# existing app
mix igniter.install skua
# brand-new app — one-time: install the project-generator archive first
mix archive.install hex igniter_new
mix igniter.new my_app --with phx.new --install skua
(igniter.new and phx.new are Mix archives, not built-in tasks — if either
reports "could not be found", install it once with mix archive.install hex igniter_new / mix archive.install hex phx_new. Or skip archives entirely and
use the plain-Mix path below.)
Skua replaces daisyUI, so the installer removes Phoenix 1.8's bundled daisyUI
by default — it deletes the vendored files and bridges daisy's color utilities
(bg-base-100, text-error, …) to Skua tokens so existing markup keeps
resolving. Keep daisyUI instead with --no-strip-daisy:
mix igniter.install skua --no-strip-daisy
(If your daisyUI config was customized with nested rules, the installer leaves it alone and prints a manual step rather than risk mangling it.)
Without Igniter — add the dep and run the plain Mix task (Igniter is optional; the task still works):
# mix.exs
{:skua, "~> 0.7.0"}mix deps.get
mix skua.install # --strip-daisy optional
mix phx.server # open /
Every step is idempotent — re-run any time after mix deps.update skua. The
installer degrades to printed manual steps if your app diverges from the default
layout. Local-testing notes in guides/local-testing.md.
Authentication
mix skua.gen.auth runs mix phx.gen.auth and then applies a flow on top. The
generated code is yours to edit.
mix skua.gen.auth --auth magic_link # default — Phoenix's passwordless flow
mix skua.gen.auth --auth otp # one-time-code login (no passwords)
mix skua.gen.auth --auth password_otp # password + OTP on one login screen
mix skua.gen.auth --auth custom # stock phx.gen.auth, nothing added
The otp and password_otp flows ship a production-grade one-time-code
login: CSPRNG codes (unique every time, never :rand), SHA-256-hashed storage,
single-use under concurrency (FOR UPDATE + transaction), constant-time compare,
a session-fixation guard, enumeration-safe responses, and built-in
Hammer rate limiting on both the request and verify
steps — all tunable in the generated config/config.exs. Code length and expiry
are flags:
mix skua.gen.auth --auth otp --otp-length 8 --otp-expiry 5
All three login flows (magic_link, otp, password_otp) wire a Resend
production mailer so the link/code actually delivers off-box (dev/test keep
Swoosh's local mailbox; prod reads RESEND_API_KEY at runtime — see the
generated .env.example).
Two dev conveniences are wired automatically: the OTP login/verify screens show
a dev-only "Open mailbox ↗" link to Swoosh's local mailbox so the sign-in code is
one click away, and the generated app creates + migrates its database on first
boot in dev — so mix deps.get && mix phx.server just works, no manual
mix ecto.create && mix ecto.migrate. Both are strictly dev-gated (no effect in
test or prod).
Pages
mix skua.gen.pages scaffolds editable starter pages and wires their routes (run
it after skua.install, and after skua.gen.auth for the auth-aware nav and the
dashboard's auth gate):
mix skua.gen.pages
- a shared, auth-aware
SiteNav— section links plus Register (ghost button) / Sign in (primary button), or a signed-in user's email + Settings + Log out. It replaces the stockphx.gen.authnav, so there's no duplicate top bar. HomeLiveat/— a full-height hero with the live Phoenix + Skua version badges above the app name, and a full-height interactive showcase: buttons that fire each toast kind and open a dialog/drawer/popover/menu/tooltip, plus cards, badges, an alert, tabs, a table, a list, an accordion, and a form.DashboardLiveat/dashboard— an authenticated page with a sidebar (Dashboard / Settings + Log out) and Skua stat cards.
Everything generated is yours to edit; re-running overwrites the pages and leaves the routes and the nav injection in place.
SEO & discovery
mix skua.gen.seo scaffolds two editable, public-facing discovery files and
wires them to be served:
mix skua.gen.seo
priv/static/robots.txt— public crawl rules. The conventional scoped/authenticated prefixes a Skua app generates (/users,/dashboard,/dev) are Disallowed by default, plus a commentedSitemap:line to fill in. A stock phx.new robots.txt is replaced; one this task already wrote is left alone so your edits survive re-runs.priv/static/llms.txt— an llms.txt template (name, summary, link sections) describing your public content for LLMs and agents. Never overwritten once it exists.
Both are served by Plug.Static, which sits above the router — so they bypass
your :browser/auth pipelines entirely and can't leak scoped or authenticated
routes. Public-only by default; point them at real content by editing the two
files. Serves at /robots.txt and /llms.txt.
Themes
Skua ships 100 prepackaged themes — each a coherent token set (dark + light, contrast-checked, with its own radius/spacing/fonts/body-size). Bake one in:
mix skua.install --theme greenfield
mix skua.themes # list all 100
--theme <name> writes that theme's tokens into your assets/css/app.css
(:root for dark, :root[data-theme="light"] for light), so the whole component
kit re-skins from one place — and it stays yours to edit. Plain mix skua.install
(no flag) keeps Skua's built-in palette; themes are opt-in, and re-running with a
different --theme swaps the block.
The set spans refined originals (greenfield, midnight, brutalist,
terminal, paper, nord, mono, sunset, solar, contrast), community
palettes (dracula, gruvbox, tokyo-night, catppuccin, rose-pine,
monokai, one-dark, ayu, everforest, cobalt…), retro / print /
design-movement / nature / bold sets, and 50 app-style homages under fictional
names (potion, discordia, gabgpt, notify, strapped, staycation,
dualingo…). Run mix skua.themes for the full list.
Repository layout
PLAN.md— the full project plan (architecture decisions, installer spec, strip-daisy design, release pipeline, roadmap).assets/css/skua.css— the token + component CSS layer (the stable artifact).lib/— components, the install mix tasks (Skua.Install.Patchesholds the shared install logic), and supporting modules._component_defaults/— reference prototypes the library is being built from (styled-layer HTML demo, LiveView hook/component prototypes, and the skua.sh brand system). Not shipped in the hex package.
License
MIT — see LICENSE.md.