jamilabreu
Starter - composable setup workflows for Phoenix apps, built on Igniter
Every new Phoenix app starts the same way: run mix phx.new, then spend time undoing defaults you don’t want and wiring in the packages you always use. Next project, you half-remember what you did last time and do it again.
Starter turns that into an ordered, flag-aware list of steps you can reuse anywhere and is always up to date with the latest Phoenix version.
How it works
mix starter.new generates a workflow module into your app, listing every built-in step with a one-line description of what it does. You open it and delete, reorder, or tag whatever you like — the file is yours:
defmodule Mix.Tasks.MyApp.Workflow do
use Starter.Workflow
@impl Starter.Workflow
def steps do
[
{:remove, :daisy_ui}, # undo a phx.new default
{:remove, :topbar},
{:gen, :gitignore}, # generate project hygiene
{:add, :credo}, # install + configure packages
{:add, :oban, if: :oban}, # optional, behind --oban
{:add, :ash}, # any package's own installer
MyApp.Steps.DeployConfig # or your own step module
]
end
end
Then run it. Optional steps become flags automatically:
$ mix starter.run --oban
Every step also works standalone if you just want one thing:
$ mix starter.add oban,credo
$ mix starter.remove daisy_ui
$ mix starter.gen gitignore
$ mix starter.add --list # see what’s available (also: remove, gen)
Everything’s interactive by default; pass Igniter’s --yes in CI.
What ships with it
About 30 built-in steps:
- remove — undoes phx.new defaults: daisyUI, topbar, the theme toggle, the " · Phoenix Framework" title suffix, AGENTS.md.
- add — installs and configures packages: bun (replacing esbuild/tailwind), credo, quokka, exsync, mix_test_watch, libcluster, pgvector, uuidv7, dotenv_parser, remixicons, oban_pro.
- gen — generates config and code: a base schema module, generator defaults (binary_id + utc_datetime_usec), a Postgres extensions migration, a minimal home page and app layout, Tailwind class sorting in the HEEx formatter, sorted mix.exs deps.
Deliberately, there’s no built-in step for anything that ships its own Igniter installer. oban, ash, tidewave and friends go through {:add, :package}, which runs the package’s own installer so upstream stays the authority. Built-in add steps exist only where upstream ships nothing, and if a package later adds an installer, its step here retires.
Writing your own steps
A step is any module implementing Igniter.Mix.Task, so you can drop one straight into your step list:
defmodule MyApp.Steps.DeployConfig do
use Igniter.Mix.Task
@impl Igniter.Mix.Task
def igniter(igniter) do
Igniter.create_new_file(igniter, "config/deploy.exs", "# ...")
end
end
Workflows are just modules, so they compose. You can keep your team’s ritual in a small dev-dep “step pack” and generate each new app’s workflow from it with mix starter.new --from MyTeam.Workflow, or include a shared workflow inline with {:workflow, MyTeam.Baseline}.
Why not…
- mix igniter.new --install a,b,c? Great for packages with installers, and Starter doesn’t compete with it. Starter’s about everything around that: removing phx.new defaults (I don’t know of anything else that does this), packages without installers, ordering, optional flags, and keeping the ritual versioned in your repo.
- A template repo? Templates fork away from phx.new and rot. A workflow replays your preferences on top of whatever phx.new generates today.
Caveats
It’s 0.1.2 — early, but working. It supports only the latest stable Phoenix (1.8) and its phx.new output; workflows warn when run against an older app.
Huge thanks to @zachdaniel and everyone working on Igniter — Starter is a thin opinionated layer over their work and wouldn’t exist otherwise.
I’d love to hear what’s in your setup ritual that isn’t covered yet, the remove list especially. I only removed the defaults that bug me, and I suspect that list is longer for other people.
Hex: starter | Hex
Docs: starter v0.2.0 — Documentation
Trending in Announcing
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #hex
- #performance










First 3 of 3 Posts
zachdaniel
Looks neat! Great usage of Igniter
I do know of one other project doing this kind of thing, although perhaps slightly different scope and not AFAIK including workflows etc: GitHub - team-alembic/phx_install: Composable Igniter installers for Phoenix · GitHub
In this code, what’s the difference between
{:add, :credo}and{:install, :ash}jamilabreu
Thanks!
:add is used when no official installer exists
:install delegates to an existing
mix igniter.installjamilabreu
it’s a good callout though – updated it so we only use
:add, first using igniter.install if one exists