Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Starter

Your Phoenix starting point, as a workflow.

CI Hex.pm Docs

Every new Phoenix app begins the same way: run mix phx.new, then spend an hour undoing defaults you don't want and wiring in the packages you always use. Starter turns that hour into a workflow — an ordered, flag-aware list of steps that lives in your project — built on Igniter, so every change is applied as a reviewable patch rather than a blind file overwrite.

Your workflow is a plain module in your own project — generated for you by mix starter.new, then edited to taste:

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},                        # get a package into the app
      {:add, :ash},                          # same verb, runs ash's installer
      {:add, :oban, if: :oban},              # optional, behind --oban
      MyApp.Steps.DeployConfig               # or your own step module
    ]
  end
end

…and it runs as a Mix task, with flags derived from your optional steps:

$ mix starter.run --oban

Getting started

Starter is built for freshly generated Phoenix apps (see Compatibility).

1. Create an app and add the dependency

mix phx.new my_app
cd my_app

Add starter to your deps in mix.exs:

def deps do
  [
    {:starter, "~> 0.1", only: :dev},
    # ...
  ]
end
mix deps.get

2. Generate your workflow

mix starter.new

This creates lib/mix/tasks/my_app.workflow.ex — your workflow. It lists every built-in step in a sensible order, each with a one-line description of what it does. Open it and make it yours:

  • Delete any step you don't want — the file is yours.
  • Reorder steps freely; they run top to bottom.
  • Tag a step with if: :flag to make it optional — it then only runs when you pass the matching --flag.

3. Run it

mix starter.run

Nothing is applied blindly. The run prints a plan showing what every step resolved to, then shows all its changes — your steps and any package installers together — as one diff you confirm once. (mix starter.run finds and runs your workflow task; invoking it directly as mix my_app.workflow does the same thing.)

The one thing that happens before that confirmation is dependencies: packages that ship an installer are added to mix.exs and fetched first, because their installers have to be on disk to run at all. That dependency change is shown and confirmed on its own. When everything finishes, set up the database and go:

mix ecto.setup
mix phx.server

Note: the generated workflow enables the vector Postgres extension via the pg_extensions and pgvector steps. If your local Postgres doesn't have pgvector installed, either install it or delete those two steps from your workflow.

Keep the workflow file in your repo: it documents exactly how your app was set up, and it's the file you'll copy into your next project.

Running single steps

Every step also works on its own, no workflow required:

mix starter.add credo,quokka    # install + configure packages
mix starter.remove daisy_ui     # undo a phx.new default
mix starter.gen gitignore       # generate config/code
mix starter.add --list          # see what's available (also: remove, gen)

These run Starter's own steps only. For a package that ships its own installer, use Igniter directly: mix igniter.install oban.

Scripts and CI

All commands are interactive by default (diff, then confirm). In a script or CI, pass Igniter's standard --yes flag to auto-accept:

mix starter.new --yes && mix starter.run --yes

Why not just…

  • mix igniter.new --install a,b,c? Great for installing packages that ship installers, and Starter runs those same installers rather than competing with them. Starter is for everything around that: removing phx.new defaults (nothing else does this), packages that don't ship installers, ordering steps, optional flags, and keeping the whole ritual versioned in your repo.
  • A boilerplate/template repo? Templates fork away from phx.new and rot. A workflow replays your preferences on top of whatever phx.new currently generates.

Built-in steps

{:add, :name} means "get this package into my app, correctly." Starter's own step runs when it has one; otherwise the package is installed and its own installer runs. Which of the two applies is upstream's business, and each run prints a plan telling you which it was:

Starter plan
  starter.add.credo
  oban — oban.install
  nimble_options — dependency only, ships no installer
  starter.gen.sort_deps

Starter deliberately ships no step for packages that provide their own Igniter installeroban, tidewave, ash and friends run upstream's installer, so upstream stays the authority. Built-in add steps exist only where upstream ships nothing, and each does the minimum wiring a missing installer would do. When a package later ships an installer, its step here retires and workflows naming it keep working unchanged — that's the point of the single verb.

({:install, :name} still exists, and forces upstream's installer even when Starter has a step of that name. You rarely want it.)

Kind Step What it does
add bun Replaces esbuild/tailwind with Bun: dep, package.json, config, watchers, aliases, tsconfig
add credo Dev/test dependency for static analysis
add dotenv_parser Loads .env in runtime config; creates and gitignores .env
add exsync Auto-recompilation on file changes (dev)
add libcluster Node clustering: dep, supervision child, Gossip topology in dev
add mix_test_watch Runs tests on file changes
add oban_pro Oban Pro: Smart engine, dynamic plugins, migration (requires license and an existing oban dep)
add pgvector Vector search: dep, Postgrex types, config, extension migration (merges into existing extensions migration)
add quokka Credo-configured formatter plugin
add remixicons Remix Icons as a Tailwind plugin with remix-* classes and a CoreComponents icon clause
add uuidv7 Time-sortable UUID primary keys; updates your Schema module when present
remove agents_md Removes the generated AGENTS.md
remove daisy_ui Removes the :daisyui Mix dependency and CSS plugin blocks
remove live_title_suffix Removes the " · Phoenix Framework" title suffix
remove theme_toggle Removes the theme scripts, component, and usage
remove topbar Removes the topbar progress indicator
gen base_schema MyApp.Schema module with sensible key/timestamp defaults
gen ecto_force_drop ecto.drop --force-drop in the mix alias
gen generator_defaults Generators default to binary_id + utc_datetime_usec
gen gigalixir Gigalixir deploy: buildpacks, Procfile, release migration scripts, SSL config
gen gigalixir_libcluster Kubernetes clustering strategy for Gigalixir
gen gitignore Adds macOS system files to .gitignore
gen minimal_app_layout Replaces Layouts.app/1 with a minimal header/main layout
gen minimal_home_page Replaces the phx.new marketing page with a minimal home page
gen mix_env_config config :app, env: Mix.env() for runtime environment checks
gen pg_extensions Migration enabling citext, pg_trgm, unaccent, and vector
gen sort_deps Sorts mix.exs dependencies alphabetically
gen tailwind_formatter HEEx formatter that sorts Tailwind classes

Steps that pattern-match against phx.new output warn loudly when they find nothing to change, instead of silently no-oping.

Writing your own steps

A step is any module that implements Igniter.Mix.Task:

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

Reference it directly in your workflow's step list. Starter.Helpers and Starter.Versions provide conveniences for common patterns (app/repo module names, checked file edits, migration timestamps, latest-version lookups).

Sharing workflows

Workflows are modules, so they compose and travel. Keep your personal or team ritual in a small "step pack" — a dev-dep containing custom steps and a shared workflow module — and generate each new app's workflow from it:

mix starter.new --from MyTeam.Workflow

The generated file expands the shared workflow's steps, so the app owns and documents its setup while your pack stays the template. Shared workflows can also be included directly:

def steps do
  [
    {:workflow, MyTeam.Baseline},
    {:add, :pgvector}
  ]
end

Steps apply in list order, package installers included, so a step that patches what an installer wrote just goes after it:

{:add, :oban},
MyTeam.Steps.ObanTweaks

{:queue, "some.task"} is still there for work that genuinely has to run against the applied project on disk, after everything else.

Compatibility

Starter supports only the latest stable Phoenix (currently 1.8) and its phx.new output. Workflows warn when run against an app on an older Phoenix. CI runs the generated workflow against a freshly generated phx.new app on every commit, so generator drift breaks loudly here instead of silently in your project.

Roadmap

  • A community workflow registry

Contributions welcome — a step is a small, self-contained module with tests, and adding one is a great first PR.

License

MIT — see LICENSE.md.

About

Composable setup workflows for Phoenix applications, built on Igniter

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages