Phoenix bootstrapping scripts

I’ve been doing a lot of prototypes in Phoenix lately. After doing the same annoying things over and over after each invocation of $ mix phx.new blah I ended up with script to bootstrap a new app the way I like it. I’m sure many have done this and was wondering if others had scripts to share. Or perhaps there is a library I’m missing to better define this stuff? https://phx.new/ does not do it for me. I’d love to see your scripts or get feedback on mine (I’m no shell expert).

The things I always do are:

  • Tell ecto to use utc_datetime_usec for timestamps
  • Use binary ids for primary keys
  • Create a custom Schema module for setting said primary keys as well as use and import the usual stuff
  • Remove page controller and associated files
  • Remove other boilerplate (phoenix css, phoenix logo)
  • Create a HomeLive LiveView (I pretty much always have a HomeLive to start which maybe gets renamed later)

Here’s my script:

#!/usr/bin/env bash

function snake_to_pascal {
  echo $1 | perl -pe 's/(?:\b|_)(\p{Ll})/\u$1/g'
}

mix phx.new "$@" --binary-id

cd "$1"

# Delete page controller
rm "lib/$1_web/controllers/page_controller.ex"
rm "test/$1_web/controllers/page_controller_test.exs"

# Delete templates
rm "lib/$1_web/templates/page/index.html.heex"
rmdir "lib/$1_web/templates/page"

# Delete view
rm "lib/$1_web/views/page_view.ex"

# Remove header from the root layout
sed -I '' '13,27d' "lib/$1_web/templates/layout/root.html.heex"

# Remove getext thing (if it's there)
sed -I '' '10s/.*/      compilers: Mix.compilers(),/' mix.exs

# Remove CSS
rm assets/css/phoenix.css
echo > assets/css/app.css

# Use utc_datetime_usec in migrations
subt="s/pool_size: 10/pool_size: 10,\n  migration_timestamps: \[type: :utc_datetime_usec\]/"
sed -I '' "$subt" "config/dev.exs"
sed -I '' "$subt" "config/test.exs"

# Setup a HomeLive
sed -I '' 's/get "\/", PageController, :index/live "\/", HomeLive, :index/' "lib/$1_web/router.ex"

mkdir "lib/$1_web/live"

module=$(snake_to_pascal "$1")

cat <<EOF > "lib/$1/schema.ex" 
defmodule ${module}.Schema do
  defmacro __using__(_) do
    quote do
      use Ecto.Schema

      import Ecto.Changeset, warn: false

      @timestamps_opts type: :utc_datetime_usec

      @primary_key {:id, :binary_id, autogenerate: true}
      @foreign_key_type :binary_id
    end
  end
end
EOF

cat <<EOF > "lib/$1_web/live/home_live.ex" 
defmodule ${module}Web.HomeLive do
  use ${module}Web, :live_view

  def render(assigns) do
    ~H"""
    <h1>${module}</h1>
    """
  end
end
EOF

# Delete phoenix logo
rm priv/static/images/phoenix.png

# Use the heex formatting plugin
cat <<EOF > ".formatter.exs"
[
  import_deps: [:ecto, :phoenix],
  plugins: [Phoenix.LiveView.HTMLFormatter],
  inputs: ["*.{heex,ex,exs}", "priv/*/seeds.exs", "{config,lib,test}/**/*.{heex,ex,exs}"],
  subdirectories: ["priv/*/migrations"]
]
EOF

I realize this is coming hot on the heels of the next phoenix release so these could end up changing a little. But I’m glad I didn’t take the time to make this thing add tailwind!

12 Likes