Repository: phoenixframework/phoenix
Pull request #4820 (2022-05-07 14:06:45)

Fix and format all templates files
- Format template files, ref https://github.com/phoenixframework/phoenix/pull/4793#issuecomment-1119687158
- Fix what's currently broken to make CI pass
- ~Auto-format .ex and .exs on demand~ that would require more changes on tests, I'll work on #4939 later


Depends on:
- https://github.com/phoenixframework/phoenix/pull/4977
- https://github.com/phoenixframework/phoenix/pull/4976
- https://github.com/phoenixframework/phoenix/pull/4981
- https://github.com/phoenixframework/phoenix/issues/4998

leandrocp: Pinging @chrismccord and @josevalim to let you know it's ready for review, and @feliperenan may wanna review the PR and templates too.
leandrocp: Should we change installer templates to support https://github.com/phoenixframework/phoenix_live_view/commit/b3aacfbd0d645836b5ca7feb09f5b22dfbf6d1ba on this PR?
chrismccord: @leandrocp you are my hero for taking this on! Now that we have merged #4872 , do you have bandwidth to take another pass and get things ready for merge? Thanks!
leandrocp: > @leandrocp you are my hero for taking this on! Now that we have merged #4872 , do you have bandwidth to take another pass and get things ready for merge? Thanks!

Yeah sure! I'm gonna resume working on it this week.
chrismccord: ping @leandrocp ! LV 0.18 is now out and the new component generators merged, so we can proceed with this work if you are still available?
leandrocp: > ping @leandrocp ! LV 0.18 is now out and the new component generators merged, so we can proceed with this work if you are still available?

Hey @chrismccord can you please take a look at https://github.com/phoenixframework/phoenix/pull/4939? I believe that's a better solution.
leandrocp: Hey @chrismccord seems like we're getting closer to finish this PR.

Some tests are failing due to:

```
1) test phx.gen.live has no compilation or formatter warnings (Phoenix.Integration.CodeGeneration.AppWithDefaultsTest)
     test/code_generation/app_with_defaults_test.exs:120
     ** (RuntimeError) mix command failed with exit code: 1
     
     mix do clean, compile --warnings-as-errors
     
     Compiling 19 files (.ex)
     warning: attribute "type" in component PhxBlogWeb.Components.input/1 must be one of ["checkbox", "color", "date", "datetime-local", "email", "file", "hidden", "month", "number", "password", "range", "radio", "search", "tel", "text", "time", "url", "week"], got: "select"
       lib/phx_blog_web/live/post_live/form_component.ex:26: (file)
     
     Compilation failed due to warnings while using the --warnings-as-errors option
     
     
     Options
     cd: /Users/leandro/code/github/leandrocp/phoenix/installer/tmp/_hyIfrcmO7/app_with_defaults/phx_blog
     env: []
     
     code: with_installer_tmp("app_with_defaults", fn tmp_dir ->
     stacktrace:
       (phoenix_integration 0.1.0) test/support/code_generator_case.ex:36: Phoenix.Integration.CodeGeneratorCase.mix_run!/3
       test/code_generation/app_with_defaults_test.exs:142: anonymous fn/1 in Phoenix.Integration.CodeGeneration.AppWithDefaultsTest."test phx.gen.live has no compilation or formatter warnings"/1
       (phoenix_integration 0.1.0) test/support/code_generator_case.ex:108: Phoenix.Integration.CodeGeneratorCase.with_installer_tmp/3
       test/code_generation/app_with_defaults_test.exs:121: (test)
```

I guess that's an easy fix but I haven't had the time to inspect.

Besides that I had to temporarily override phoenix dep on umbrella root just to make tests pass: https://github.com/phoenixframework/phoenix/blob/80de4092cd1c70126ba0acb3d9ee54cdf0b1b892/installer/templates/phx_umbrella/mix.exs#L28 

Otherwise I get the following error and I'm not sure what's the best solution here:

```
1) test new umbrella app has no compilation or formatter warnings (Phoenix.Integration.CodeGeneration.UmbrellaAppWithDefaultsTest)
     test/code_generation/umbrella_app_with_defaults_test.exs:5
     ** (RuntimeError) mix command failed with exit code: 1
     
     mix format --check-formatted
     
     Unchecked dependencies for environment dev:
     * phoenix (../../../../../../..)
       different specs were given for the phoenix app:
     
       > In apps/phx_blog_web/mix.exs:
         {:phoenix, [env: :prod, path: "../../../../../../..", override: true]}
     
       > In deps/phoenix_live_view/mix.exs:
         {:phoenix, "~> 1.6 or ~> 1.7", [env: :prod, hex: "phoenix", repo: "hexpm", optional: false]}
     
       Ensure they match or specify one of the above in your deps and set "override: true"
     ** (Mix) Can't continue due to errors on dependencies
     
     
     Options
     cd: /Users/leandro/code/github/leandrocp/phoenix/installer/tmp/jmMN3-KlPk/umbrella_app_with_defaults/phx_blog_umbrella
     env: []
     
     code: with_installer_tmp("umbrella_app_with_defaults", fn tmp_dir ->
     stacktrace:
       (phoenix_integration 0.1.0) test/support/code_generator_case.ex:36: Phoenix.Integration.CodeGeneratorCase.mix_run!/3
       (phoenix_integration 0.1.0) test/support/code_generator_case.ex:108: Phoenix.Integration.CodeGeneratorCase.with_installer_tmp/3
       test/code_generation/umbrella_app_with_defaults_test.exs:6: (test)
```
josevalim: > Besides that I had to temporarily override phoenix dep on umbrella root just to make tests pass: 

That makes sense, yes.
chrismccord: @leandrocp I just pushed a fix for the missing select type. Let me know how things look now! Thanks!

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6c1657dd0..db85d2427 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -16,7 +16,7 @@ jobs:
           - elixir: 1.12.0
             otp: 22.3
 
-          - elixir: 1.14.0
+          - elixir: 1.14.0 # TODO: bump to 1.15 to leverage format diffs https://github.com/elixir-lang/elixir/pull/12109
             otp: 24.3.4
             lint: true
             installer: true
diff --git a/installer/lib/phx_new/generator.ex b/installer/lib/phx_new/generator.ex
index f5f339831..b03452cd4 100644
--- a/installer/lib/phx_new/generator.ex
+++ b/installer/lib/phx_new/generator.ex
@@ -171,7 +171,8 @@ defmodule Phx.New.Generator do
     assets = Keyword.get(opts, :assets, true)
     mailer = Keyword.get(opts, :mailer, true)
     dev = Keyword.get(opts, :dev, false)
-    phoenix_path = phoenix_path(project, dev)
+    phoenix_path = phoenix_path(project, dev, false)
+    phoenix_path_umbrella_root = phoenix_path(project, dev, true)
 
     # We lowercase the database name because according to the
     # SQL spec, they are case insensitive unless quoted, which
@@ -201,6 +202,7 @@ defmodule Phx.New.Generator do
       web_namespace: inspect(project.web_namespace),
       phoenix_github_version_tag: "v#{version.major}.#{version.minor}",
       phoenix_dep: phoenix_dep(phoenix_path, version),
+      phoenix_dep_umbrella_root: phoenix_dep(phoenix_path_umbrella_root, version),
       phoenix_js_path: phoenix_js_path(phoenix_path),
       pubsub_server: pubsub_server,
       secret_key_base_dev: random_string(64),
@@ -220,7 +222,8 @@ defmodule Phx.New.Generator do
       adapter_module: adapter_module,
       adapter_config: adapter_config,
       generators: nil_if_empty(project.generators ++ adapter_generators(adapter_config)),
-      namespaced?: namespaced?(project)
+      namespaced?: namespaced?(project),
+      dev: dev
     ]
 
     %Project{project | binding: binding}
@@ -374,7 +377,7 @@ defmodule Phx.New.Generator do
   defp nil_if_empty([]), do: nil
   defp nil_if_empty(other), do: other
 
-  defp phoenix_path(%Project{} = project, true) do
+  defp phoenix_path(%Project{} = project, true = _dev, umbrella_root?) do
     absolute = Path.expand(project.project_path)
     relative = Path.relative_to(absolute, @phoenix)
 
@@ -383,19 +386,20 @@ defmodule Phx.New.Generator do
     end
 
     project
-    |> phoenix_path_prefix()
+    |> phoenix_path_prefix(umbrella_root?)
     |> Path.join(relative)
     |> Path.split()
     |> Enum.map(fn _ -> ".." end)
     |> Path.join()
   end
 
-  defp phoenix_path(%Project{}, false) do
+  defp phoenix_path(%Project{}, false = _dev, _umbrella_root?) do
     "deps/phoenix"
   end
 
-  defp phoenix_path_prefix(%Project{in_umbrella?: true}), do: "../../../"
-  defp phoenix_path_prefix(%Project{in_umbrella?: false}), do: ".."
+  defp phoenix_path_prefix(%Project{in_umbrella?: false}, _), do: ".."
+  defp phoenix_path_prefix(%Project{in_umbrella?: true}, true = _umbrella_root?), do: ".."
+  defp phoenix_path_prefix(%Project{in_umbrella?: true}, false = _umbrella_root?), do: "../../../"
 
   defp phoenix_dep("deps/phoenix", %{pre: ["dev"]}),
     do: ~s[{:phoenix, github: "phoenixframework/phoenix", override: true}]
diff --git a/installer/templates/phx_single/formatter.exs b/installer/templates/phx_single/formatter.exs
index ba5dc1aef..373998b6c 100644
--- a/installer/templates/phx_single/formatter.exs
+++ b/installer/templates/phx_single/formatter.exs
@@ -1,5 +1,5 @@
 [
-  import_deps: [<%= if @ecto do %>:ecto, <% end %>:phoenix],<%= if @ecto do %>
+  import_deps: [<%= if @ecto do %>:ecto, :ecto_sql, <% end %>:phoenix],<%= if @ecto do %>
   subdirectories: ["priv/*/migrations"],<% end %><%= if @html and Version.match?(System.version(), ">= 1.13.4") do %>
   plugins: [Phoenix.LiveView.HTMLFormatter],<% end %>
   inputs: [<%= if @html and Version.match?(System.version(), ">= 1.13.4") do %>"*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}"<% else %>"*.{ex,exs}", "{config,lib,test}/**/*.{ex,exs}"<% end %><%= if @ecto do %>, "priv/*/seeds.exs"<% end %>]
diff --git a/installer/templates/phx_single/lib/app_name_web.ex b/installer/templates/phx_single/lib/app_name_web.ex
index 99fcc17f0..36f19eda7 100644
--- a/installer/templates/phx_single/lib/app_name_web.ex
+++ b/installer/templates/phx_single/lib/app_name_web.ex
@@ -36,8 +36,8 @@ defmodule <%= @web_namespace %> do
         root: "lib/<%= @lib_web_name %>/templates",
         namespace: <%= @web_namespace %><%= if @html do %>
 
-      use Phoenix.Component
-<% end %>
+      use Phoenix.Component<% end %>
+
       # Import convenience functions from controllers
       import Phoenix.Controller,
         only: [get_csrf_token: 0, view_module: 1, view_template: 1]
@@ -99,8 +99,7 @@ defmodule <%= @web_namespace %> do
       alias Phoenix.LiveView.JS
 <% end %>
       # Import basic rendering functionality (render, render_layout, etc)
-      import Phoenix.View
-      <%= if @gettext do %>
+      import Phoenix.View<%= if @gettext do %>
       import <%= @web_namespace %>.Gettext<% end %>
       unquote(verified_routes())
     end
diff --git a/installer/templates/phx_umbrella/apps/app_name/formatter.exs b/installer/templates/phx_umbrella/apps/app_name/formatter.exs
index c02688e3d..cc40446b9 100644
--- a/installer/templates/phx_umbrella/apps/app_name/formatter.exs
+++ b/installer/templates/phx_umbrella/apps/app_name/formatter.exs
@@ -1,5 +1,5 @@
 [<%= if @ecto do %>
-  import_deps: [:ecto],
+  import_deps: [:ecto, :ecto_sql],
   subdirectories: ["priv/*/migrations"],<% end %><%= if @html and Version.match?(System.version(), ">= 1.13.4") do %>
   plugins: [Phoenix.LiveView.HTMLFormatter],<% end %>
   inputs: [<%= if @html and Version.match?(System.version(), ">= 1.13.4") do %>"*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}"<% else %>"*.{ex,exs}", "{config,lib,test}/**/*.{ex,exs}"<% end %><%= if @ecto do %>, "priv/*/seeds.exs"<% end %>]
diff --git a/installer/templates/phx_umbrella/apps/app_name_web/lib/app_name.ex b/installer/templates/phx_umbrella/apps/app_name_web/lib/app_name.ex
index a93c55c46..a920e3e58 100644
--- a/installer/templates/phx_umbrella/apps/app_name_web/lib/app_name.ex
+++ b/installer/templates/phx_umbrella/apps/app_name_web/lib/app_name.ex
@@ -99,14 +99,12 @@ defmodule <%= @web_namespace %> do
       alias Phoenix.LiveView.JS
 <% end %>
       # Import basic rendering functionality (render, render_layout, etc)
-      import Phoenix.View
-      <%= if @gettext do %>
+      import Phoenix.View<%= if @gettext do %>
       import <%= @web_namespace %>.Gettext<% end %>
       unquote(verified_routes())
     end
   end
 
-
   @doc """
   When used, dispatch to the appropriate controller/view/etc.
   """
diff --git a/installer/templates/phx_umbrella/mix.exs b/installer/templates/phx_umbrella/mix.exs
index e08018159..6233e0f33 100644
--- a/installer/templates/phx_umbrella/mix.exs
+++ b/installer/templates/phx_umbrella/mix.exs
@@ -26,7 +26,8 @@ defmodule <%= @root_app_module %>.MixProject do
   defp deps do<%= if @html and Version.match?(System.version(), ">= 1.13.4") do %>
     [
       # required to run "mix format" on ~H/.heex files from the umbrella root
-      {:phoenix_live_view, ">= 0.0.0"}
+      <%= if @dev do %><%= @phoenix_dep_umbrella_root %>,
+      <% end %>{:phoenix_live_view, ">= 0.0.0"}
     ]<% else %>
     []<% end %>
   end
diff --git a/installer/templates/phx_web/components.ex b/installer/templates/phx_web/components.ex
index abe0a881f..8de8bae71 100644
--- a/installer/templates/phx_web/components.ex
+++ b/installer/templates/phx_web/components.ex
@@ -9,10 +9,8 @@ defmodule <%= @web_namespace %>.Components do
   Icons are provided by [heroicons](https://heroicons.com), using the
   [heroicons_elixir](https://github.com/mveytsman/heroicons_elixir) project.
   """
-  use Phoenix.Component
-
-  <%= if @gettext do %>import <%= @web_namespace %>.Gettext, warn: false
-  <% end %>
+  use Phoenix.Component<%= if @gettext do %>
+  import <%= @web_namespace %>.Gettext, warn: false<% end %>
   alias Phoenix.LiveView.JS
 
   @doc """
@@ -27,7 +25,7 @@ defmodule <%= @web_namespace %>.Components do
       </.modal>
 
   JS commands may be passed to the `:on_cancel` and `on_confirm` attributes
-  for the caller to reactor to each button press, for example:
+  for the caller to react to each button press, for example:
 
       <.modal id="confirm" on_confirm={JS.push("delete")} on_cancel={JS.navigate(~p"/posts")}>
         Are you sure you?
@@ -126,10 +124,10 @@ defmodule <%= @web_namespace %>.Components do
   attr :id, :string, default: "flash", doc: "the optional id of flash container"
   attr :flash, :map, default: %{}, doc: "the map of flash messages to display"
   attr :title, :string, default: nil
-  attr :kind, :atom, values: [:info, :error], doc: "Used for styling and flash lookup"
+  attr :kind, :atom, values: [:info, :error], doc: "used for styling and flash lookup"
   attr :autoshow, :boolean, default: true, doc: "whether to auto show the flash on mount"
   attr :close, :boolean, default: true, doc: "whether the flash can be closed"
-  attr :rest, :global, doc: "the aribtrary HTML attributes to add to the flash container"
+  attr :rest, :global, doc: "the arbitrary HTML attributes to add to the flash container"
 
   slot :inner_block, doc: "the optional inner block that renders the flash message"
 
@@ -176,6 +174,7 @@ defmodule <%= @web_namespace %>.Components do
   """
   attr :for, :any, default: nil, doc: "the datastructure for the form"
   attr :as, :any, default: nil, doc: "the server side parameter to collect all input under"
+
   attr :rest, :global,
     include: ~w(autocomplete name rel action enctype method novalidate target),
     doc: "the arbitrary HTML attributes to apply to the form tag"
@@ -253,6 +252,7 @@ defmodule <%= @web_namespace %>.Components do
   attr :rest, :global, include: ~w(autocomplete checked disabled form max maxlength min minlength
                                    multiple pattern placeholder readonly required size step)
   slot :inner_block
+
   slot :option, doc: "the slot for select input options" do
     attr :value, :any
   end
diff --git a/installer/templates/phx_web/templates/layout/root.html.heex b/installer/templates/phx_web/templates/layout/root.html.heex
index 28909b57b..4ebd234da 100644
--- a/installer/templates/phx_web/templates/layout/root.html.heex
+++ b/installer/templates/phx_web/templates/layout/root.html.heex
@@ -1,14 +1,30 @@
 <!DOCTYPE html>
 <html lang="en">
   <head>
-    <meta charset="utf-8"/>
-    <meta name="viewport" content="width=device-width, initial-scale=1"/>
-    <meta name="csrf-token" content={get_csrf_token()}>
-    <.live_title suffix=" · Phoenix Framework"><%%= assigns[:page_title] || "<%= @app_module %>" %></.live_title>
-    <link phx-track-static rel="stylesheet" href={~p"/assets/app.css"}/>
-    <script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}></script>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1" />
+    <meta name="csrf-token" content={get_csrf_token()} />
+    <.live_title suffix=" · Phoenix Framework">
+      <%%= assigns[:page_title] || "<%= @app_module %>" %>
+    </.live_title>
+    <link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} />
+    <script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
+    </script>
   </head>
   <body class="bg-white antialiased">
+    <.flash kind={:info} title="Success!" flash={@flash} />
+    <.flash kind={:error} title="Error!" flash={@flash} />
+    <.flash
+      id="disconnected"
+      kind={:error}
+      title="We can't find the internet"
+      close={false}
+      autoshow={false}
+      phx-disconnected={show("#disconnected")}
+      phx-connected={hide("#disconnected")}
+    >
+      Attempting to reconnect <Heroicons.arrow_path class="ml-1 w-3 h-3 inline animate-spin" />
+    </.flash>
     <%%= @inner_content %>
   </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/installer/templates/phx_web/templates/page/index.html.heex b/installer/templates/phx_web/templates/page/index.html.heex
index 8a47f4ae2..a00a2a613 100644
--- a/installer/templates/phx_web/templates/page/index.html.heex
+++ b/installer/templates/phx_web/templates/page/index.html.heex
@@ -1,53 +1,129 @@
 <div class="fixed inset-y-0 right-0 left-[40rem] hidden lg:block xl:left-[50rem]">
-  <svg viewBox="0 0 1480 957" fill="none" aria-hidden="true" class="absolute inset-0 h-full w-full" preserveAspectRatio="xMinYMid slice">
+  <svg
+    viewBox="0 0 1480 957"
+    fill="none"
+    aria-hidden="true"
+    class="absolute inset-0 h-full w-full"
+    preserveAspectRatio="xMinYMid slice"
+  >
     <path fill="#EE7868" d="M0 0h1480v957H0z" />
-    <path d="M137.542 466.27c-582.851-48.41-988.806-82.127-1608.412 658.2l67.39 810 3083.15-256.51L1535.94-49.622l-98.36 8.183C1269.29 281.468 734.115 515.799 146.47 467.012l-8.928-.742Z" fill="#FF9F92" />
-    <path d="M371.028 528.664C-169.369 304.988-545.754 149.198-1361.45 665.565l-182.58 792.025 3014.73 694.98 389.42-1689.25-96.18-22.171C1505.28 697.438 924.153 757.586 379.305 532.09l-8.277-3.426Z" fill="#FA8372" />
-    <path d="M359.326 571.714C-104.765 215.795-428.003-32.102-1349.55 255.554l-282.3 1224.596 3047.04 722.01 312.24-1354.467C1411.25 1028.3 834.355 935.995 366.435 577.166l-7.109-5.452Z" fill="#E96856" fill-opacity=".6" />
-    <path d="M1593.87 1236.88c-352.15 92.63-885.498-145.85-1244.602-613.557l-5.455-7.105C-12.347 152.31-260.41-170.8-1225-131.458l-368.63 1599.048 3057.19 704.76 130.31-935.47Z" fill="#C42652" fill-opacity=".2" />
-    <path d="M1411.91 1526.93c-363.79 15.71-834.312-330.6-1085.883-863.909l-3.822-8.102C72.704 125.95-101.074-242.476-1052.01-408.907l-699.85 1484.267 2837.75 1338.01 326.02-886.44Z" fill="#A41C42" fill-opacity=".2" />
-    <path d="M1116.26 1863.69c-355.457-78.98-720.318-535.27-825.287-1115.521l-1.594-8.816C185.286 163.833 112.786-237.016-762.678-643.898L-1822.83 608.665 571.922 2635.55l544.338-771.86Z" fill="#A41C42" fill-opacity=".2" />
+    <path
+      d="M137.542 466.27c-582.851-48.41-988.806-82.127-1608.412 658.2l67.39 810 3083.15-256.51L1535.94-49.622l-98.36 8.183C1269.29 281.468 734.115 515.799 146.47 467.012l-8.928-.742Z"
+      fill="#FF9F92"
+    />
+    <path
+      d="M371.028 528.664C-169.369 304.988-545.754 149.198-1361.45 665.565l-182.58 792.025 3014.73 694.98 389.42-1689.25-96.18-22.171C1505.28 697.438 924.153 757.586 379.305 532.09l-8.277-3.426Z"
+      fill="#FA8372"
+    />
+    <path
+      d="M359.326 571.714C-104.765 215.795-428.003-32.102-1349.55 255.554l-282.3 1224.596 3047.04 722.01 312.24-1354.467C1411.25 1028.3 834.355 935.995 366.435 577.166l-7.109-5.452Z"
+      fill="#E96856"
+      fill-opacity=".6"
+    />
+    <path
+      d="M1593.87 1236.88c-352.15 92.63-885.498-145.85-1244.602-613.557l-5.455-7.105C-12.347 152.31-260.41-170.8-1225-131.458l-368.63 1599.048 3057.19 704.76 130.31-935.47Z"
+      fill="#C42652"
+      fill-opacity=".2"
+    />
+    <path
+      d="M1411.91 1526.93c-363.79 15.71-834.312-330.6-1085.883-863.909l-3.822-8.102C72.704 125.95-101.074-242.476-1052.01-408.907l-699.85 1484.267 2837.75 1338.01 326.02-886.44Z"
+      fill="#A41C42"
+      fill-opacity=".2"
+    />
+    <path
+      d="M1116.26 1863.69c-355.457-78.98-720.318-535.27-825.287-1115.521l-1.594-8.816C185.286 163.833 112.786-237.016-762.678-643.898L-1822.83 608.665 571.922 2635.55l544.338-771.86Z"
+      fill="#A41C42"
+      fill-opacity=".2"
+    />
   </svg>
 </div>
 <div class="px-4 py-10 sm:py-28 sm:px-6 lg:px-8 xl:py-32 xl:px-28">
   <div class="mx-auto max-w-xl lg:mx-0">
     <svg viewBox="0 0 71 48" class="h-12" aria-hidden="true">
-      <path d="m26.371 33.477-.552-.1c-3.92-.729-6.397-3.1-7.57-6.829-.733-2.324.597-4.035 3.035-4.148 1.995-.092 3.362 1.055 4.57 2.39 1.557 1.72 2.984 3.558 4.514 5.305 2.202 2.515 4.797 4.134 8.347 3.634 3.183-.448 5.958-1.725 8.371-3.828.363-.316.761-.592 1.144-.886l-.241-.284c-2.027.63-4.093.841-6.205.735-3.195-.16-6.24-.828-8.964-2.582-2.486-1.601-4.319-3.746-5.19-6.611-.704-2.315.736-3.934 3.135-3.6.948.133 1.746.56 2.463 1.165.583.493 1.143 1.015 1.738 1.493 2.8 2.25 6.712 2.375 10.265-.068-5.842-.026-9.817-3.24-13.308-7.313-1.366-1.594-2.7-3.216-4.095-4.785-2.698-3.036-5.692-5.71-9.79-6.623C12.8-.623 7.745.14 2.893 2.361 1.926 2.804.997 3.319 0 4.149c.494 0 .763.006 1.032 0 2.446-.064 4.28 1.023 5.602 3.024.962 1.457 1.415 3.104 1.761 4.798.513 2.515.247 5.078.544 7.605.761 6.494 4.08 11.026 10.26 13.346 2.267.852 4.591 1.135 7.172.555ZM10.751 3.852c-.976.246-1.756-.148-2.56-.962 1.377-.343 2.592-.476 3.897-.528-.107.848-.607 1.306-1.336 1.49Zm32.002 37.924c-.085-.626-.62-.901-1.04-1.228-1.857-1.446-4.03-1.958-6.333-2-1.375-.026-2.735-.128-4.031-.61-.595-.22-1.26-.505-1.244-1.272.015-.78.693-1 1.31-1.184.505-.15 1.026-.247 1.6-.382-1.46-.936-2.886-1.065-4.787-.3-2.993 1.202-5.943 1.06-8.926-.017-1.684-.608-3.179-1.563-4.735-2.408l-.043.03a2.96 2.96 0 0 0 .04-.029c-.038-.117-.107-.12-.197-.054l.122.107c1.29 2.115 3.034 3.817 5.004 5.271 3.793 2.8 7.936 4.471 12.784 3.73A66.714 66.714 0 0 1 37 40.877c1.98-.16 3.866.398 5.753.899Zm-9.14-30.345c-.105-.076-.206-.266-.42-.069 1.745 2.36 3.985 4.098 6.683 5.193 4.354 1.767 8.773 2.07 13.293.51 3.51-1.21 6.033-.028 7.343 3.38.19-3.955-2.137-6.837-5.843-7.401-2.084-.318-4.01.373-5.962.94-5.434 1.575-10.485.798-15.094-2.553Zm27.085 15.425c.708.059 1.416.123 2.124.185-1.6-1.405-3.55-1.517-5.523-1.404-3.003.17-5.167 1.903-7.14 3.972-1.739 1.824-3.31 3.87-5.903 4.604.043.078.054.117.066.117.35.005.699.021 1.047.005 3.768-.17 7.317-.965 10.14-3.7.89-.86 1.685-1.817 2.544-2.71.716-.746 1.584-1.159 2.645-1.07Zm-8.753-4.67c-2.812.246-5.254 1.409-7.548 2.943-1.766 1.18-3.654 1.738-5.776 1.37-.374-.066-.75-.114-1.124-.17l-.013.156c.135.07.265.151.405.207.354.14.702.308 1.07.395 4.083.971 7.992.474 11.516-1.803 2.221-1.435 4.521-1.707 7.013-1.336.252.038.503.083.756.107.234.022.479.255.795.003-2.179-1.574-4.526-2.096-7.094-1.872Zm-10.049-9.544c1.475.051 2.943-.142 4.486-1.059-.452.04-.643.04-.827.076-2.126.424-4.033-.04-5.733-1.383-.623-.493-1.257-.974-1.889-1.457-2.503-1.914-5.374-2.555-8.514-2.5.05.154.054.26.108.315 3.417 3.455 7.371 5.836 12.369 6.008Zm24.727 17.731c-2.114-2.097-4.952-2.367-7.578-.537 1.738.078 3.043.632 4.101 1.728.374.388.763.768 1.182 1.106 1.6 1.29 4.311 1.352 5.896.155-1.861-.726-1.861-.726-3.601-2.452Zm-21.058 16.06c-1.858-3.46-4.981-4.24-8.59-4.008a9.667 9.667 0 0 1 2.977 1.39c.84.586 1.547 1.311 2.243 2.055 1.38 1.473 3.534 2.376 4.962 2.07-.656-.412-1.238-.848-1.592-1.507Zm17.29-19.32c0-.023.001-.045.003-.068l-.006.006.006-.006-.036-.004.021.018.012.053Zm-20 14.744a7.61 7.61 0 0 0-.072-.041.127.127 0 0 0 .015.043c.005.008.038 0 .058-.002Zm-.072-.041-.008-.034-.008.01.008-.01-.022-.006.005.026.024.014Z" fill="#FD4F00" />
+      <path
+        d="m26.371 33.477-.552-.1c-3.92-.729-6.397-3.1-7.57-6.829-.733-2.324.597-4.035 3.035-4.148 1.995-.092 3.362 1.055 4.57 2.39 1.557 1.72 2.984 3.558 4.514 5.305 2.202 2.515 4.797 4.134 8.347 3.634 3.183-.448 5.958-1.725 8.371-3.828.363-.316.761-.592 1.144-.886l-.241-.284c-2.027.63-4.093.841-6.205.735-3.195-.16-6.24-.828-8.964-2.582-2.486-1.601-4.319-3.746-5.19-6.611-.704-2.315.736-3.934 3.135-3.6.948.133 1.746.56 2.463 1.165.583.493 1.143 1.015 1.738 1.493 2.8 2.25 6.712 2.375 10.265-.068-5.842-.026-9.817-3.24-13.308-7.313-1.366-1.594-2.7-3.216-4.095-4.785-2.698-3.036-5.692-5.71-9.79-6.623C12.8-.623 7.745.14 2.893 2.361 1.926 2.804.997 3.319 0 4.149c.494 0 .763.006 1.032 0 2.446-.064 4.28 1.023 5.602 3.024.962 1.457 1.415 3.104 1.761 4.798.513 2.515.247 5.078.544 7.605.761 6.494 4.08 11.026 10.26 13.346 2.267.852 4.591 1.135 7.172.555ZM10.751 3.852c-.976.246-1.756-.148-2.56-.962 1.377-.343 2.592-.476 3.897-.528-.107.848-.607 1.306-1.336 1.49Zm32.002 37.924c-.085-.626-.62-.901-1.04-1.228-1.857-1.446-4.03-1.958-6.333-2-1.375-.026-2.735-.128-4.031-.61-.595-.22-1.26-.505-1.244-1.272.015-.78.693-1 1.31-1.184.505-.15 1.026-.247 1.6-.382-1.46-.936-2.886-1.065-4.787-.3-2.993 1.202-5.943 1.06-8.926-.017-1.684-.608-3.179-1.563-4.735-2.408l-.043.03a2.96 2.96 0 0 0 .04-.029c-.038-.117-.107-.12-.197-.054l.122.107c1.29 2.115 3.034 3.817 5.004 5.271 3.793 2.8 7.936 4.471 12.784 3.73A66.714 66.714 0 0 1 37 40.877c1.98-.16 3.866.398 5.753.899Zm-9.14-30.345c-.105-.076-.206-.266-.42-.069 1.745 2.36 3.985 4.098 6.683 5.193 4.354 1.767 8.773 2.07 13.293.51 3.51-1.21 6.033-.028 7.343 3.38.19-3.955-2.137-6.837-5.843-7.401-2.084-.318-4.01.373-5.962.94-5.434 1.575-10.485.798-15.094-2.553Zm27.085 15.425c.708.059 1.416.123 2.124.185-1.6-1.405-3.55-1.517-5.523-1.404-3.003.17-5.167 1.903-7.14 3.972-1.739 1.824-3.31 3.87-5.903 4.604.043.078.054.117.066.117.35.005.699.021 1.047.005 3.768-.17 7.317-.965 10.14-3.7.89-.86 1.685-1.817 2.544-2.71.716-.746 1.584-1.159 2.645-1.07Zm-8.753-4.67c-2.812.246-5.254 1.409-7.548 2.943-1.766 1.18-3.654 1.738-5.776 1.37-.374-.066-.75-.114-1.124-.17l-.013.156c.135.07.265.151.405.207.354.14.702.308 1.07.395 4.083.971 7.992.474 11.516-1.803 2.221-1.435 4.521-1.707 7.013-1.336.252.038.503.083.756.107.234.022.479.255.795.003-2.179-1.574-4.526-2.096-7.094-1.872Zm-10.049-9.544c1.475.051 2.943-.142 4.486-1.059-.452.04-.643.04-.827.076-2.126.424-4.033-.04-5.733-1.383-.623-.493-1.257-.974-1.889-1.457-2.503-1.914-5.374-2.555-8.514-2.5.05.154.054.26.108.315 3.417 3.455 7.371 5.836 12.369 6.008Zm24.727 17.731c-2.114-2.097-4.952-2.367-7.578-.537 1.738.078 3.043.632 4.101 1.728.374.388.763.768 1.182 1.106 1.6 1.29 4.311 1.352 5.896.155-1.861-.726-1.861-.726-3.601-2.452Zm-21.058 16.06c-1.858-3.46-4.981-4.24-8.59-4.008a9.667 9.667 0 0 1 2.977 1.39c.84.586 1.547 1.311 2.243 2.055 1.38 1.473 3.534 2.376 4.962 2.07-.656-.412-1.238-.848-1.592-1.507Zm17.29-19.32c0-.023.001-.045.003-.068l-.006.006.006-.006-.036-.004.021.018.012.053Zm-20 14.744a7.61 7.61 0 0 0-.072-.041.127.127 0 0 0 .015.043c.005.008.038 0 .058-.002Zm-.072-.041-.008-.034-.008.01.008-.01-.022-.006.005.026.024.014Z"
+        fill="#FD4F00"
+      />
     </svg>
     <h1 class="mt-10 flex items-center text-sm font-semibold leading-6 text-brand">
-      <%%= gettext("Phoenix Framework") %>
-      <small class="ml-3 rounded-full bg-brand/5 px-2 text-[0.8125rem] font-medium leading-6"><%= @phoenix_github_version_tag %></small>
+      Phoenix Framework
+      <small class="ml-3 rounded-full bg-brand/5 px-2 text-[0.8125rem] font-medium leading-6">
+        <%= @phoenix_github_version_tag %>
+      </small>
     </h1>
-    <p class="mt-4 text-[2rem] font-semibold leading-10 tracking-tighter text-zinc-900">Peace of mind from prototype to production.</p>
-    <p class="mt-4 text-base leading-7 text-zinc-600">Build rich, interactive web applications quickly, with less code and fewer moving parts. Join our growing community of developers using Phoenix to craft APIs, HTML5 apps and more, for fun or at scale.</p>
+    <p class="mt-4 text-[2rem] font-semibold leading-10 tracking-tighter text-zinc-900">
+      Peace of mind from prototype to production.
+    </p>
+    <p class="mt-4 text-base leading-7 text-zinc-600">
+      Build rich, interactive web applications quickly, with less code and fewer moving parts. Join our growing community of developers using Phoenix to craft APIs, HTML5 apps and more, for fun or at scale.
+    </p>
     <div class="flex">
       <div class="w-full sm:w-auto">
         <div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-4 sm:grid-cols-3">
-          <a href="https://hexdocs.pm/phoenix/overview.html" class="group relative rounded-2xl px-6 py-4 text-sm font-semibold leading-6 text-zinc-900 sm:py-6">
-            <span class="absolute inset-0 rounded-2xl bg-zinc-50 transition group-hover:bg-zinc-100 sm:group-hover:scale-105"></span>
+          <a
+            href="https://hexdocs.pm/phoenix/overview.html"
+            class="group relative rounded-2xl px-6 py-4 text-sm font-semibold leading-6 text-zinc-900 sm:py-6"
+          >
+            <span class="absolute inset-0 rounded-2xl bg-zinc-50 transition group-hover:bg-zinc-100 sm:group-hover:scale-105">
+            </span>
             <span class="relative flex items-center gap-4 sm:flex-col">
               <svg viewBox="0 0 24 24" fill="none" aria-hidden="true" class="h-6 w-6">
                 <path d="m12 4 10-2v18l-10 2V4Z" fill="#18181B" fill-opacity=".15" />
-                <path d="M12 4 2 2v18l10 2m0-18v18m0-18 10-2v18l-10 2" stroke="#18181B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
+                <path
+                  d="M12 4 2 2v18l10 2m0-18v18m0-18 10-2v18l-10 2"
+                  stroke="#18181B"
+                  stroke-width="2"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                />
               </svg>
               Guides &amp; Docs
             </span>
           </a>
-          <a href="https://github.com/phoenixframework/phoenix" class="group relative rounded-2xl px-6 py-4 text-sm font-semibold leading-6 text-zinc-900 sm:py-6">
-            <span class="absolute inset-0 rounded-2xl bg-zinc-50 transition group-hover:bg-zinc-100 sm:group-hover:scale-105"></span>
+          <a
+            href="https://github.com/phoenixframework/phoenix"
+            class="group relative rounded-2xl px-6 py-4 text-sm font-semibold leading-6 text-zinc-900 sm:py-6"
+          >
+            <span class="absolute inset-0 rounded-2xl bg-zinc-50 transition group-hover:bg-zinc-100 sm:group-hover:scale-105">
+            </span>
             <span class="relative flex items-center gap-4 sm:flex-col">
               <svg viewBox="0 0 24 24" aria-hidden="true" class="h-6 w-6">
-                <path fill-rule="evenodd" clip-rule="evenodd" d="M12 0C5.37 0 0 5.506 0 12.303c0 5.445 3.435 10.043 8.205 11.674.6.107.825-.262.825-.585 0-.292-.015-1.261-.015-2.291C6 21.67 5.22 20.346 4.98 19.654c-.135-.354-.72-1.446-1.23-1.738-.42-.23-1.02-.8-.015-.815.945-.015 1.62.892 1.845 1.261 1.08 1.86 2.805 1.338 3.495 1.015.105-.8.42-1.338.765-1.645-2.67-.308-5.46-1.37-5.46-6.075 0-1.338.465-2.446 1.23-3.307-.12-.308-.54-1.569.12-3.26 0 0 1.005-.323 3.3 1.26.96-.276 1.98-.415 3-.415s2.04.139 3 .416c2.295-1.6 3.3-1.261 3.3-1.261.66 1.691.24 2.952.12 3.26.765.861 1.23 1.953 1.23 3.307 0 4.721-2.805 5.767-5.475 6.075.435.384.81 1.122.81 2.276 0 1.645-.015 2.968-.015 3.383 0 .323.225.707.825.585a12.047 12.047 0 0 0 5.919-4.489A12.536 12.536 0 0 0 24 12.304C24 5.505 18.63 0 12 0Z" fill="#18181B" />
+                <path
+                  fill-rule="evenodd"
+                  clip-rule="evenodd"
+                  d="M12 0C5.37 0 0 5.506 0 12.303c0 5.445 3.435 10.043 8.205 11.674.6.107.825-.262.825-.585 0-.292-.015-1.261-.015-2.291C6 21.67 5.22 20.346 4.98 19.654c-.135-.354-.72-1.446-1.23-1.738-.42-.23-1.02-.8-.015-.815.945-.015 1.62.892 1.845 1.261 1.08 1.86 2.805 1.338 3.495 1.015.105-.8.42-1.338.765-1.645-2.67-.308-5.46-1.37-5.46-6.075 0-1.338.465-2.446 1.23-3.307-.12-.308-.54-1.569.12-3.26 0 0 1.005-.323 3.3 1.26.96-.276 1.98-.415 3-.415s2.04.139 3 .416c2.295-1.6 3.3-1.261 3.3-1.261.66 1.691.24 2.952.12 3.26.765.861 1.23 1.953 1.23 3.307 0 4.721-2.805 5.767-5.475 6.075.435.384.81 1.122.81 2.276 0 1.645-.015 2.968-.015 3.383 0 .323.225.707.825.585a12.047 12.047 0 0 0 5.919-4.489A12.536 12.536 0 0 0 24 12.304C24 5.505 18.63 0 12 0Z"
+                  fill="#18181B"
+                />
               </svg>
               Source Code
             </span>
           </a>
-          <a href="https://github.com/phoenixframework/phoenix/blob/<%= @phoenix_github_version_tag %>/CHANGELOG.md" class="group relative rounded-2xl px-6 py-4 text-sm font-semibold leading-6 text-zinc-900 sm:py-6">
-            <span class="absolute inset-0 rounded-2xl bg-zinc-50 transition group-hover:bg-zinc-100 sm:group-hover:scale-105"></span>
+          <a
+            href="https://github.com/phoenixframework/phoenix/blob/<%= @phoenix_github_version_tag %>/CHANGELOG.md"
+            class="group relative rounded-2xl px-6 py-4 text-sm font-semibold leading-6 text-zinc-900 sm:py-6"
+          >
+            <span class="absolute inset-0 rounded-2xl bg-zinc-50 transition group-hover:bg-zinc-100 sm:group-hover:scale-105">
+            </span>
             <span class="relative flex items-center gap-4 sm:flex-col">
               <svg viewBox="0 0 24 24" fill="none" aria-hidden="true" class="h-6 w-6">
-                <path d="M12 1v6M12 17v6" stroke="#18181B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
-                <circle cx="12" cy="12" r="4" fill="#18181B" fill-opacity=".15" stroke="#18181B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
+                <path
+                  d="M12 1v6M12 17v6"
+                  stroke="#18181B"
+                  stroke-width="2"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                />
+                <circle
+                  cx="12"
+                  cy="12"
+                  r="4"
+                  fill="#18181B"
+                  fill-opacity=".15"
+                  stroke="#18181B"
+                  stroke-width="2"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                />
               </svg>
               Changelog
             </span>
@@ -55,49 +131,99 @@
         </div>
         <div class="mt-10 grid grid-cols-1 gap-y-4 text-sm leading-6 text-zinc-700 sm:grid-cols-2">
           <div>
-            <a href="https://twitter.com/elixirphoenix" class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900">
-              <svg viewBox="0 0 16 16" aria-hidden="true" class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600">
+            <a
+              href="https://twitter.com/elixirphoenix"
+              class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900"
+            >
+              <svg
+                viewBox="0 0 16 16"
+                aria-hidden="true"
+                class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600"
+              >
                 <path d="M5.403 14c5.283 0 8.172-4.617 8.172-8.62 0-.131 0-.262-.008-.391A6.033 6.033 0 0 0 15 3.419a5.503 5.503 0 0 1-1.65.477 3.018 3.018 0 0 0 1.263-1.676 5.579 5.579 0 0 1-1.824.736 2.832 2.832 0 0 0-1.63-.916 2.746 2.746 0 0 0-1.821.319A2.973 2.973 0 0 0 8.076 3.78a3.185 3.185 0 0 0-.182 1.938 7.826 7.826 0 0 1-3.279-.918 8.253 8.253 0 0 1-2.64-2.247 3.176 3.176 0 0 0-.315 2.208 3.037 3.037 0 0 0 1.203 1.836A2.739 2.739 0 0 1 1.56 6.22v.038c0 .7.23 1.377.65 1.919.42.54 1.004.912 1.654 1.05-.423.122-.866.14-1.297.052.184.602.541 1.129 1.022 1.506a2.78 2.78 0 0 0 1.662.598 5.656 5.656 0 0 1-2.007 1.074A5.475 5.475 0 0 1 1 12.64a7.827 7.827 0 0 0 4.403 1.358" />
               </svg>
               Follow on Twitter
             </a>
           </div>
           <div>
-            <a href="https://elixirforum.com" class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900">
-              <svg viewBox="0 0 16 16" aria-hidden="true" class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600">
+            <a
+              href="https://elixirforum.com"
+              class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900"
+            >
+              <svg
+                viewBox="0 0 16 16"
+                aria-hidden="true"
+                class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600"
+              >
                 <path d="M8 13.833c3.866 0 7-2.873 7-6.416C15 3.873 11.866 1 8 1S1 3.873 1 7.417c0 1.081.292 2.1.808 2.995.606 1.05.806 2.399.086 3.375l-.208.283c-.285.386-.01.905.465.85.852-.098 2.048-.318 3.137-.81a3.717 3.717 0 0 1 1.91-.318c.263.027.53.041.802.041Z" />
               </svg>
               Discuss on the Elixir forum
             </a>
           </div>
           <div>
-            <a href="https://elixir-slackin.herokuapp.com" class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900">
-              <svg viewBox="0 0 16 16" aria-hidden="true" class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600">
+            <a
+              href="https://elixir-slackin.herokuapp.com"
+              class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900"
+            >
+              <svg
+                viewBox="0 0 16 16"
+                aria-hidden="true"
+                class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600"
+              >
                 <path d="M3.95 9.85a1.47 1.47 0 1 1-2.94 0 1.47 1.47 0 0 1 1.47-1.472h1.47v1.471Zm.735 0a1.47 1.47 0 1 1 2.94 0v3.678a1.47 1.47 0 1 1-2.94 0V9.85ZM6.156 3.942a1.47 1.47 0 0 1-1.47-1.472 1.47 1.47 0 1 1 2.94 0v1.472h-1.47Zm0 .747c.813 0 1.47.658 1.47 1.471a1.47 1.47 0 0 1-1.47 1.472H2.47A1.47 1.47 0 0 1 1 6.16 1.47 1.47 0 0 1 2.47 4.69h3.686ZM12.048 6.16a1.47 1.47 0 1 1 2.94 0 1.47 1.47 0 0 1-1.47 1.472h-1.47V6.16Zm-.735 0a1.47 1.47 0 1 1-2.94 0V2.47a1.47 1.47 0 1 1 2.94 0v3.69ZM9.843 12.057c.813 0 1.47.657 1.47 1.471a1.47 1.47 0 1 1-2.94 0v-1.471h1.47Zm0-.736a1.47 1.47 0 0 1-1.47-1.472 1.47 1.47 0 0 1 1.47-1.471h3.686c.813 0 1.47.658 1.47 1.471a1.47 1.47 0 0 1-1.47 1.472H9.843Z" />
               </svg>
               Join our Slack channel
             </a>
           </div>
           <div>
-            <a href="https://web.libera.chat/#elixir" class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900">
-              <svg viewBox="0 0 16 16" aria-hidden="true" class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600">
-                <path fill-rule="evenodd" clip-rule="evenodd" d="M6.356 2.007a.75.75 0 0 1 .637.849l-1.5 10.5a.75.75 0 1 1-1.485-.212l1.5-10.5a.75.75 0 0 1 .848-.637ZM11.356 2.008a.75.75 0 0 1 .637.848l-1.5 10.5a.75.75 0 0 1-1.485-.212l1.5-10.5a.75.75 0 0 1 .848-.636Z" />
-                <path fill-rule="evenodd" clip-rule="evenodd" d="M14 5.25a.75.75 0 0 1-.75.75h-9.5a.75.75 0 0 1 0-1.5h9.5a.75.75 0 0 1 .75.75ZM13 10.75a.75.75 0 0 1-.75.75h-9.5a.75.75 0 0 1 0-1.5h9.5a.75.75 0 0 1 .75.75Z" />
+            <a
+              href="https://web.libera.chat/#elixir"
+              class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900"
+            >
+              <svg
+                viewBox="0 0 16 16"
+                aria-hidden="true"
+                class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600"
+              >
+                <path
+                  fill-rule="evenodd"
+                  clip-rule="evenodd"
+                  d="M6.356 2.007a.75.75 0 0 1 .637.849l-1.5 10.5a.75.75 0 1 1-1.485-.212l1.5-10.5a.75.75 0 0 1 .848-.637ZM11.356 2.008a.75.75 0 0 1 .637.848l-1.5 10.5a.75.75 0 0 1-1.485-.212l1.5-10.5a.75.75 0 0 1 .848-.636Z"
+                />
+                <path
+                  fill-rule="evenodd"
+                  clip-rule="evenodd"
+                  d="M14 5.25a.75.75 0 0 1-.75.75h-9.5a.75.75 0 0 1 0-1.5h9.5a.75.75 0 0 1 .75.75ZM13 10.75a.75.75 0 0 1-.75.75h-9.5a.75.75 0 0 1 0-1.5h9.5a.75.75 0 0 1 .75.75Z"
+                />
               </svg>
               Chat on Libera IRC
             </a>
           </div>
           <div>
-            <a href="https://discord.gg/elixir" class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900">
-              <svg viewBox="0 0 16 16" aria-hidden="true" class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600">
+            <a
+              href="https://discord.gg/elixir"
+              class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900"
+            >
+              <svg
+                viewBox="0 0 16 16"
+                aria-hidden="true"
+                class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600"
+              >
                 <path d="M13.545 2.995c-1.02-.46-2.114-.8-3.257-.994a.05.05 0 0 0-.052.024c-.141.246-.297.567-.406.82a12.377 12.377 0 0 0-3.658 0 8.238 8.238 0 0 0-.412-.82.052.052 0 0 0-.052-.024 13.315 13.315 0 0 0-3.257.994.046.046 0 0 0-.021.018C.356 6.063-.213 9.036.066 11.973c.001.015.01.029.02.038a13.353 13.353 0 0 0 3.996 1.987.052.052 0 0 0 .056-.018c.308-.414.582-.85.818-1.309a.05.05 0 0 0-.028-.069 8.808 8.808 0 0 1-1.248-.585.05.05 0 0 1-.005-.084c.084-.062.168-.126.248-.191a.05.05 0 0 1 .051-.007c2.619 1.176 5.454 1.176 8.041 0a.05.05 0 0 1 .053.006c.08.065.164.13.248.192a.05.05 0 0 1-.004.084c-.399.23-.813.423-1.249.585a.05.05 0 0 0-.027.07c.24.457.514.893.817 1.307a.051.051 0 0 0 .056.019 13.31 13.31 0 0 0 4.001-1.987.05.05 0 0 0 .021-.037c.334-3.396-.559-6.345-2.365-8.96a.04.04 0 0 0-.021-.02Zm-8.198 7.19c-.789 0-1.438-.712-1.438-1.587 0-.874.637-1.586 1.438-1.586.807 0 1.45.718 1.438 1.586 0 .875-.637 1.587-1.438 1.587Zm5.316 0c-.788 0-1.438-.712-1.438-1.587 0-.874.637-1.586 1.438-1.586.807 0 1.45.718 1.438 1.586 0 .875-.63 1.587-1.438 1.587Z" />
               </svg>
               Join our Discord server
             </a>
           </div>
           <div>
-            <a href="https://fly.io/docs/getting-started/elixir/" class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900">
-              <svg viewBox="0 0 20 20" aria-hidden="true" class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600">
+            <a
+              href="https://fly.io/docs/getting-started/elixir/"
+              class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900"
+            >
+              <svg
+                viewBox="0 0 20 20"
+                aria-hidden="true"
+                class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600"
+              >
                 <path d="M1 12.5A4.5 4.5 0 005.5 17H15a4 4 0 001.866-7.539 3.504 3.504 0 00-4.504-4.272A4.5 4.5 0 004.06 8.235 4.502 4.502 0 001 12.5z" />
               </svg>
               Deploy your application
@@ -107,4 +233,4 @@
       </div>
     </div>
   </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/lib/mix/tasks/phx.digest.ex b/lib/mix/tasks/phx.digest.ex
index 7e5546791..689ffcf31 100644
--- a/lib/mix/tasks/phx.digest.ex
+++ b/lib/mix/tasks/phx.digest.ex
@@ -65,6 +65,7 @@ defmodule Mix.Tasks.Phx.Digest do
         Mix.shell().info [:green, "Check your digested files at #{inspect output_path}"]
       {:error, :invalid_path} ->
         Mix.shell().error "The input path #{inspect input_path} does not exist"
+        exit({:shutdown, 1})
     end
   end
 end
diff --git a/lib/mix/tasks/phx.gen.auth/injector.ex b/lib/mix/tasks/phx.gen.auth/injector.ex
index d309a2e84..98d2bebd3 100644
--- a/lib/mix/tasks/phx.gen.auth/injector.ex
+++ b/lib/mix/tasks/phx.gen.auth/injector.ex
@@ -165,12 +165,22 @@ defmodule Mix.Tasks.Phx.Gen.Auth.Injector do
     template = """
     <ul>
       <%= if @current_#{schema.singular} do %>
-        <li><%= @current_#{schema.singular}.email %></li>
-        <li><.link href={~p"#{schema.route_prefix}/settings"}>Settings</.link></li>
-        <li><.link href={~p"#{schema.route_prefix}/log_out"} method="delete">Log out</.link></li>
+        <li>
+          <%= @current_#{schema.singular}.email %>
+        </li>
+        <li>
+          <.link href={~p"#{schema.route_prefix}/settings"}>Settings</.link>
+        </li>
+        <li>
+          <.link href={~p"#{schema.route_prefix}/log_out"} method="delete">Log out</.link>
+        </li>
       <% else %>
-        <li><.link href={~p"#{schema.route_prefix}/register"}>Register</.link></li>
-        <li><.link href={~p"#{schema.route_prefix}/log_in"}>Log in</.link></li>
+        <li>
+          <.link href={~p"#{schema.route_prefix}/register"}>Register</.link>
+        </li>
+        <li>
+          <.link href={~p"#{schema.route_prefix}/log_in"}>Log in</.link>
+        </li>
       <% end %>
     </ul>\
     """
diff --git a/lib/mix/tasks/phx.gen.html.ex b/lib/mix/tasks/phx.gen.html.ex
index 8710d2c37..4749d3e57 100644
--- a/lib/mix/tasks/phx.gen.html.ex
+++ b/lib/mix/tasks/phx.gen.html.ex
@@ -206,4 +206,24 @@ defmodule Mix.Tasks.Phx.Gen.Html do
   end
 
   defp label(key), do: to_string(key)
+
+  @doc false
+  def indent_inputs(inputs, column_padding) do
+    columns = String.duplicate(" ", column_padding)
+
+    inputs
+    |> Enum.map(fn input ->
+      lines = input |> String.split("\n") |> Enum.reject(& &1 == "")
+
+      case lines do
+        [line] ->
+          [columns, line]
+
+        [first_line | rest] ->
+          rest = Enum.map_join(rest, "\n", &(columns <> &1))
+          [columns, first_line, "\n", rest]
+      end
+    end)
+    |> Enum.intersperse("\n")
+  end
 end
diff --git a/priv/templates/phx.gen.auth/confirmation_edit.html.heex b/priv/templates/phx.gen.auth/confirmation_edit.html.heex
index 9cd20070e..9e4128f2b 100644
--- a/priv/templates/phx.gen.auth/confirmation_edit.html.heex
+++ b/priv/templates/phx.gen.auth/confirmation_edit.html.heex
@@ -7,6 +7,7 @@
 </.simple_form>
 
 <p>
-  <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link> |
+  <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link>
+  |
   <.link href={~p"<%= schema.route_prefix %>/log_in"}>Log in</.link>
 </p>
diff --git a/priv/templates/phx.gen.auth/confirmation_instructions_live.ex b/priv/templates/phx.gen.auth/confirmation_instructions_live.ex
index 65e5b30ee..948921907 100644
--- a/priv/templates/phx.gen.auth/confirmation_instructions_live.ex
+++ b/priv/templates/phx.gen.auth/confirmation_instructions_live.ex
@@ -7,7 +7,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
     ~H"""
     <.header>Resend confirmation instructions</.header>
 
-    <.simple_form id="resend_confirmation_form" :let={f} for={:<%= schema.singular %>} phx-submit="send_instructions">
+    <.simple_form :let={f} for={:<%= schema.singular %>} id="resend_confirmation_form" phx-submit="send_instructions">
       <.input field={{f, :email}} type="email" label="Email" required />
       <:actions>
         <.button phx-disable-with="Sending...">Resend confirmation instructions</.button>
@@ -15,7 +15,8 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
     </.simple_form>
 
     <p>
-      <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link> |
+      <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link>
+      |
       <.link href={~p"<%= schema.route_prefix %>/log_in"}>Log in</.link>
     </p>
     """
diff --git a/priv/templates/phx.gen.auth/confirmation_live.ex b/priv/templates/phx.gen.auth/confirmation_live.ex
index f9924f2db..b6196baf3 100644
--- a/priv/templates/phx.gen.auth/confirmation_live.ex
+++ b/priv/templates/phx.gen.auth/confirmation_live.ex
@@ -7,7 +7,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
     ~H"""
     <.header>Confirm Account</.header>
 
-    <.simple_form id="confirmation_form" :let={f} for={:<%= schema.singular %>} phx-submit="confirm_account">
+    <.simple_form :let={f} for={:<%= schema.singular %>} id="confirmation_form" phx-submit="confirm_account">
       <.input field={{f, :token}} type="hidden" value={@token} />
       <:actions>
         <.button phx-disable-with="Confirming...">Confirm my account</.button>
@@ -15,7 +15,8 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
     </.simple_form>
 
     <p>
-      <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link> |
+      <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link>
+      |
       <.link href={~p"<%= schema.route_prefix %>/log_in"}>Log in</.link>
     </p>
     """
diff --git a/priv/templates/phx.gen.auth/confirmation_new.html.heex b/priv/templates/phx.gen.auth/confirmation_new.html.heex
index 9908a490f..c6b403597 100644
--- a/priv/templates/phx.gen.auth/confirmation_new.html.heex
+++ b/priv/templates/phx.gen.auth/confirmation_new.html.heex
@@ -8,6 +8,7 @@
 </.simple_form>
 
 <p>
-  <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link> |
+  <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link>
+  |
   <.link href={~p"<%= schema.route_prefix %>/log_in"}>Log in</.link>
 </p>
diff --git a/priv/templates/phx.gen.auth/forgot_password_live.ex b/priv/templates/phx.gen.auth/forgot_password_live.ex
index 4d9c9ac10..ebed73e15 100644
--- a/priv/templates/phx.gen.auth/forgot_password_live.ex
+++ b/priv/templates/phx.gen.auth/forgot_password_live.ex
@@ -11,10 +11,12 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         <:subtitle>We'll send a password reset link to your inbox</:subtitle>
       </.header>
 
-      <.simple_form id="reset_password_form" :let={f} for={:<%= schema.singular %>} phx-submit="send_email">
+      <.simple_form :let={f} id="reset_password_form" for={:<%= schema.singular %>} phx-submit="send_email">
         <.input field={{f, :email}} type="email" placeholder="Email" required />
         <:actions>
-          <.button phx-disable-with="Sending..." class="w-full">Send password reset instructions</.button>
+          <.button phx-disable-with="Sending..." class="w-full">
+            Send password reset instructions
+          </.button>
         </:actions>
       </.simple_form>
     </div>
diff --git a/priv/templates/phx.gen.auth/reset_password_edit.html.heex b/priv/templates/phx.gen.auth/reset_password_edit.html.heex
index f13b4b564..f8bf19945 100644
--- a/priv/templates/phx.gen.auth/reset_password_edit.html.heex
+++ b/priv/templates/phx.gen.auth/reset_password_edit.html.heex
@@ -10,7 +10,9 @@
     <%% end %>
     <.input field={{f, :email}} type="email" placeholder="Email" required />
     <:actions>
-      <.button phx-disable-with="Sending..." class="w-full">Send password reset instructions</.button>
+      <.button phx-disable-with="Sending..." class="w-full">
+        Send password reset instructions
+      </.button>
     </:actions>
   </.simple_form>
-</div>
\ No newline at end of file
+</div>
diff --git a/priv/templates/phx.gen.auth/reset_password_live.ex b/priv/templates/phx.gen.auth/reset_password_live.ex
index 640e2a93f..f6a3cbf6a 100644
--- a/priv/templates/phx.gen.auth/reset_password_live.ex
+++ b/priv/templates/phx.gen.auth/reset_password_live.ex
@@ -7,7 +7,13 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
     ~H"""
     <.header>Reset Password</.header>
 
-    <.simple_form id="reset_password_form" :let={f} for={@changeset} phx-submit="reset_password" phx-change="validate">
+    <.simple_form
+      :let={f}
+      for={@changeset}
+      id="reset_password_form"
+      phx-submit="reset_password"
+      phx-change="validate"
+    >
       <%%= if @changeset.action == :insert do %>
         <.error message="Oops, something went wrong! Please check the errors below." />
       <%% end %>
@@ -31,7 +37,8 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
     </.simple_form>
 
     <p>
-      <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link> |
+      <.link href={~p"<%= schema.route_prefix %>/register"}>Register</.link>
+      |
       <.link href={~p"<%= schema.route_prefix %>/log_in"}>Log in</.link>
     </p>
     """
diff --git a/priv/templates/phx.gen.auth/reset_password_new.html.heex b/priv/templates/phx.gen.auth/reset_password_new.html.heex
index e6b4e3049..e2badda06 100644
--- a/priv/templates/phx.gen.auth/reset_password_new.html.heex
+++ b/priv/templates/phx.gen.auth/reset_password_new.html.heex
@@ -7,7 +7,9 @@
   <.simple_form :let={f} for={:<%= schema.singular %>} action={~p"<%= schema.route_prefix %>/reset_password"}>
     <.input field={{f, :email}} type="email" placeholder="Email" required />
     <:actions>
-      <.button phx-disable-with="Sending..." class="w-full">Send password reset instructions</.button>
+      <.button phx-disable-with="Sending..." class="w-full">
+        Send password reset instructions
+      </.button>
     </:actions>
   </.simple_form>
 </div>
diff --git a/priv/templates/phx.gen.auth/routes.ex b/priv/templates/phx.gen.auth/routes.ex
index ed3747ebf..60ced3360 100644
--- a/priv/templates/phx.gen.auth/routes.ex
+++ b/priv/templates/phx.gen.auth/routes.ex
@@ -42,6 +42,7 @@
     pipe_through [:browser]
 
     delete "/<%= schema.plural %>/log_out", <%= inspect schema.alias %>SessionController, :delete<%= if live? do %>
+
     live_session :current_<%= schema.singular %>,
       on_mount: [{<%= inspect auth_module %>, :mount_current_<%= schema.singular %>}] do
       live "/<%= schema.plural %>/confirm/:token", <%= inspect schema.alias %>ConfirmationLive, :edit
diff --git a/priv/templates/phx.gen.auth/session_new.html.heex b/priv/templates/phx.gen.auth/session_new.html.heex
index 41865eda4..6ad32e6d8 100644
--- a/priv/templates/phx.gen.auth/session_new.html.heex
+++ b/priv/templates/phx.gen.auth/session_new.html.heex
@@ -29,4 +29,4 @@
       </.button>
     </:actions>
   </.simple_form>
-</div>
\ No newline at end of file
+</div>
diff --git a/priv/templates/phx.gen.auth/settings_edit.html.heex b/priv/templates/phx.gen.auth/settings_edit.html.heex
index b2767e01b..63c6abbcf 100644
--- a/priv/templates/phx.gen.auth/settings_edit.html.heex
+++ b/priv/templates/phx.gen.auth/settings_edit.html.heex
@@ -27,7 +27,12 @@
     </.simple_form>
   </div>
   <div>
-    <.simple_form :let={f} for={@password_changeset} action={~p"<%= schema.route_prefix %>/settings"} id="update_password">
+    <.simple_form
+      :let={f}
+      for={@password_changeset}
+      action={~p"<%= schema.route_prefix %>/settings"}
+      id="update_password"
+    >
       <%%= if @password_changeset.action do %>
         <.error message="Oops, something went wrong! Please check the errors below." />
       <%% end %>
@@ -35,7 +40,12 @@
       <.input field={{f, :action}} type="hidden" name="action" value="update_password" />
 
       <.input field={{f, :password}} type="password" label="New password" required />
-      <.input field={{f, :password_confirmation}} type="password" label="Confirm new password" required />
+      <.input
+        field={{f, :password_confirmation}}
+        type="password"
+        label="Confirm new password"
+        required
+      />
 
       <.input
         field={{f, :current_password}}
@@ -50,4 +60,4 @@
       </:actions>
     </.simple_form>
   </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/priv/templates/phx.gen.auth/settings_live.ex b/priv/templates/phx.gen.auth/settings_live.ex
index f3f1beaef..5367271ed 100644
--- a/priv/templates/phx.gen.auth/settings_live.ex
+++ b/priv/templates/phx.gen.auth/settings_live.ex
@@ -8,8 +8,8 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
     <.header>Change Email</.header>
 
     <.simple_form
-      id="email_form"
       :let={f}
+      id="email_form"
       for={@email_changeset}
       phx-submit="update_email"
       phx-change="validate_email"
@@ -37,8 +37,8 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
     <.header>Change Password</.header>
 
     <.simple_form
-      id="password_form"
       :let={f}
+      id="password_form"
       for={@password_changeset}
       action={~p"<%= schema.route_prefix %>/log_in?_action=password_updated"}
       method="post"
@@ -69,7 +69,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         field={{f, :current_password}}
         name="current_password"
         type="password"
-        label="Confirm new password"
+        label="Current password"
         id="current_password_for_password"
         value={@current_password}
         required
diff --git a/priv/templates/phx.gen.html/edit.html.heex b/priv/templates/phx.gen.html/edit.html.heex
index b9c5c5eec..382fc3e97 100644
--- a/priv/templates/phx.gen.html/edit.html.heex
+++ b/priv/templates/phx.gen.html/edit.html.heex
@@ -8,9 +8,8 @@
     :if={@changeset.action}
     message="Oops, something went wrong! Please check the errors below."
   />
-
-  <%= for input <- inputs, input do %><%= input %>
-  <% end %><:actions>
+<%= Mix.Tasks.Phx.Gen.Html.indent_inputs(inputs, 2) %>
+  <:actions>
     <.button>Save <%= schema.human_singular %></.button>
   </:actions>
 </.simple_form>
diff --git a/priv/templates/phx.gen.html/index.html.heex b/priv/templates/phx.gen.html/index.html.heex
index 68fd251a1..b6273d48a 100644
--- a/priv/templates/phx.gen.html/index.html.heex
+++ b/priv/templates/phx.gen.html/index.html.heex
@@ -20,4 +20,4 @@
       Delete
     </.link>
   </:action>
-</.table>
\ No newline at end of file
+</.table>
diff --git a/priv/templates/phx.gen.html/new.html.heex b/priv/templates/phx.gen.html/new.html.heex
index 3a7563b1b..b1a73b2bb 100644
--- a/priv/templates/phx.gen.html/new.html.heex
+++ b/priv/templates/phx.gen.html/new.html.heex
@@ -8,11 +8,10 @@
     :if={@changeset.action}
     message="Oops, something went wrong! Please check the errors below."
   />
-
-  <%= for input <- inputs, input do %><%= input %>
-  <% end %><:actions>
+<%= Mix.Tasks.Phx.Gen.Html.indent_inputs(inputs, 2) %>
+  <:actions>
     <.button>Save <%= schema.human_singular %></.button>
   </:actions>
 </.simple_form>
 
-<.back navigate={~p"<%= schema.route_prefix %>"}>Back to <%= schema.plural %></.back>
\ No newline at end of file
+<.back navigate={~p"<%= schema.route_prefix %>"}>Back to <%= schema.plural %></.back>
diff --git a/priv/templates/phx.gen.html/show.html.heex b/priv/templates/phx.gen.html/show.html.heex
index 085aae74c..344289278 100644
--- a/priv/templates/phx.gen.html/show.html.heex
+++ b/priv/templates/phx.gen.html/show.html.heex
@@ -12,4 +12,4 @@
   <:item title="<%= Phoenix.Naming.humanize(Atom.to_string(k)) %>"><%%= @<%= schema.singular %>.<%= k %> %></:item><% end %>
 </.list>
 
-<.back navigate={~p"<%= schema.route_prefix %>"}>Back to <%= schema.plural %></.back>
\ No newline at end of file
+<.back navigate={~p"<%= schema.route_prefix %>"}>Back to <%= schema.plural %></.back>
diff --git a/priv/templates/phx.gen.live/components.ex b/priv/templates/phx.gen.live/components.ex
index abe0a881f..8de8bae71 100644
--- a/priv/templates/phx.gen.live/components.ex
+++ b/priv/templates/phx.gen.live/components.ex
@@ -9,10 +9,8 @@ defmodule <%= @web_namespace %>.Components do
   Icons are provided by [heroicons](https://heroicons.com), using the
   [heroicons_elixir](https://github.com/mveytsman/heroicons_elixir) project.
   """
-  use Phoenix.Component
-
-  <%= if @gettext do %>import <%= @web_namespace %>.Gettext, warn: false
-  <% end %>
+  use Phoenix.Component<%= if @gettext do %>
+  import <%= @web_namespace %>.Gettext, warn: false<% end %>
   alias Phoenix.LiveView.JS
 
   @doc """
@@ -27,7 +25,7 @@ defmodule <%= @web_namespace %>.Components do
       </.modal>
 
   JS commands may be passed to the `:on_cancel` and `on_confirm` attributes
-  for the caller to reactor to each button press, for example:
+  for the caller to react to each button press, for example:
 
       <.modal id="confirm" on_confirm={JS.push("delete")} on_cancel={JS.navigate(~p"/posts")}>
         Are you sure you?
@@ -126,10 +124,10 @@ defmodule <%= @web_namespace %>.Components do
   attr :id, :string, default: "flash", doc: "the optional id of flash container"
   attr :flash, :map, default: %{}, doc: "the map of flash messages to display"
   attr :title, :string, default: nil
-  attr :kind, :atom, values: [:info, :error], doc: "Used for styling and flash lookup"
+  attr :kind, :atom, values: [:info, :error], doc: "used for styling and flash lookup"
   attr :autoshow, :boolean, default: true, doc: "whether to auto show the flash on mount"
   attr :close, :boolean, default: true, doc: "whether the flash can be closed"
-  attr :rest, :global, doc: "the aribtrary HTML attributes to add to the flash container"
+  attr :rest, :global, doc: "the arbitrary HTML attributes to add to the flash container"
 
   slot :inner_block, doc: "the optional inner block that renders the flash message"
 
@@ -176,6 +174,7 @@ defmodule <%= @web_namespace %>.Components do
   """
   attr :for, :any, default: nil, doc: "the datastructure for the form"
   attr :as, :any, default: nil, doc: "the server side parameter to collect all input under"
+
   attr :rest, :global,
     include: ~w(autocomplete name rel action enctype method novalidate target),
     doc: "the arbitrary HTML attributes to apply to the form tag"
@@ -253,6 +252,7 @@ defmodule <%= @web_namespace %>.Components do
   attr :rest, :global, include: ~w(autocomplete checked disabled form max maxlength min minlength
                                    multiple pattern placeholder readonly required size step)
   slot :inner_block
+
   slot :option, doc: "the slot for select input options" do
     attr :value, :any
   end
diff --git a/priv/templates/phx.gen.live/form_component.ex b/priv/templates/phx.gen.live/form_component.ex
index cd48ec445..ed4976706 100644
--- a/priv/templates/phx.gen.live/form_component.ex
+++ b/priv/templates/phx.gen.live/form_component.ex
@@ -20,8 +20,8 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         phx-change="validate"
         phx-submit="save"
       >
-        <%= for input <- inputs, input do %><%= input %>
-        <% end %><:actions>
+<%= Mix.Tasks.Phx.Gen.Html.indent_inputs(inputs, 8) %>
+        <:actions>
           <.button phx-disable-with="Saving...">Save <%= schema.human_singular %></.button>
         </:actions>
       </.simple_form>
diff --git a/priv/templates/phx.gen.live/show.html.heex b/priv/templates/phx.gen.live/show.html.heex
index 2888e7c3c..846b77a28 100644
--- a/priv/templates/phx.gen.live/show.html.heex
+++ b/priv/templates/phx.gen.live/show.html.heex
@@ -26,4 +26,3 @@
     />
   </.modal>
 <%% end %>
-


Test patch:
diff --git a/installer/test/mix_helper.exs b/installer/test/mix_helper.exs
index 5dfd7a068..89e7d8745 100644
--- a/installer/test/mix_helper.exs
+++ b/installer/test/mix_helper.exs
@@ -35,6 +35,12 @@ defmodule MixHelper do
       File.mkdir_p!(path)
       File.cd!(path, fn ->
         File.touch!("mix.exs")
+        File.write!(".formatter.exs", """
+        [
+          import_deps: [:phoenix, :ecto, :ecto_sql],
+          inputs: ["*.exs"]
+        ]
+        """)
         function.()
       end)
     after
diff --git a/installer/test/phx_new_test.exs b/installer/test/phx_new_test.exs
index 483c79650..e902e655c 100644
--- a/installer/test/phx_new_test.exs
+++ b/installer/test/phx_new_test.exs
@@ -39,14 +39,14 @@ defmodule Mix.Tasks.Phx.NewTest do
 
       if Version.match?(System.version(), ">= 1.13.4") do
         assert_file "phx_blog/.formatter.exs", fn file ->
-          assert file =~ "import_deps: [:ecto, :phoenix]"
+          assert file =~ "import_deps: [:ecto, :ecto_sql, :phoenix]"
           assert file =~ "subdirectories: [\"priv/*/migrations\"]"
           assert file =~ "plugins: [Phoenix.LiveView.HTMLFormatter]"
           assert file =~ "inputs: [\"*.{heex,ex,exs}\", \"{config,lib,test}/**/*.{heex,ex,exs}\", \"priv/*/seeds.exs\"]"
         end
       else
         assert_file "phx_blog/.formatter.exs", fn file ->
-          assert file =~ "import_deps: [:ecto, :phoenix]"
+          assert file =~ "import_deps: [:ecto, :ecto_sql, :phoenix]"
           assert file =~ "subdirectories: [\"priv/*/migrations\"]"
           assert file =~ "inputs: [\"*.{ex,exs}\", \"{config,lib,test}/**/*.{ex,exs}\", \"priv/*/seeds.exs\"]"
           refute file =~ "plugins:"
@@ -113,7 +113,7 @@ defmodule Mix.Tasks.Phx.NewTest do
       end
 
       assert_file "phx_blog/lib/phx_blog_web/templates/layout/root.html.heex", fn file ->
-        assert file =~ ~s|<meta name="csrf-token" content={get_csrf_token()}>|
+        assert file =~ ~s|<meta name="csrf-token" content={get_csrf_token()} />|
       end
 
       assert_file "phx_blog/lib/phx_blog_web/templates/layout/app.html.heex"
@@ -421,7 +421,7 @@ defmodule Mix.Tasks.Phx.NewTest do
       end
 
       assert_file "phx_blog/.formatter.exs", fn file ->
-        assert file =~ "import_deps: [:ecto, :phoenix]"
+        assert file =~ "import_deps: [:ecto, :ecto_sql, :phoenix]"
         assert file =~ "subdirectories: [\"priv/*/migrations\"]"
         assert file =~ "inputs: [\"*.{ex,exs}\", \"{config,lib,test}/**/*.{ex,exs}\", \"priv/*/seeds.exs\"]"
         refute file =~ "plugins:"
diff --git a/installer/test/phx_new_umbrella_test.exs b/installer/test/phx_new_umbrella_test.exs
index 5f704dc65..7a9769cec 100644
--- a/installer/test/phx_new_umbrella_test.exs
+++ b/installer/test/phx_new_umbrella_test.exs
@@ -95,7 +95,7 @@ defmodule Mix.Tasks.Phx.New.UmbrellaTest do
         end
 
         assert_file app_path(@app, ".formatter.exs"), fn file ->
-          assert file =~ "import_deps: [:ecto]"
+          assert file =~ "import_deps: [:ecto, :ecto_sql]"
           assert file =~ "subdirectories: [\"priv/*/migrations\"]"
           assert file =~ "plugins: [Phoenix.LiveView.HTMLFormatter]"
           assert file =~ "inputs: [\"*.{heex,ex,exs}\", \"{config,lib,test}/**/*.{heex,ex,exs}\", \"priv/*/seeds.exs\"]"
@@ -171,7 +171,7 @@ defmodule Mix.Tasks.Phx.New.UmbrellaTest do
       assert_file web_path(@app, "lib/#{@app}_web/router.ex"), "defmodule PhxUmbWeb.Router"
 
       assert_file web_path(@app, "lib/#{@app}_web/templates/layout/root.html.heex"), fn file ->
-        assert file =~ ~s|<meta name="csrf-token" content={get_csrf_token()}>|
+        assert file =~ ~s|<meta name="csrf-token" content={get_csrf_token()} />|
       end
 
       assert_file web_path(@app, "lib/#{@app}_web/templates/layout/app.html.heex")
diff --git a/integration_test/config/config.exs b/integration_test/config/config.exs
index d86450ae8..1c69651b7 100644
--- a/integration_test/config/config.exs
+++ b/integration_test/config/config.exs
@@ -3,3 +3,5 @@ import Config
 config :phoenix, :json_library, Jason
 
 config :swoosh, api_client: false
+
+config :tailwind, :version, "3.1.6"
diff --git a/integration_test/mix.exs b/integration_test/mix.exs
index 75efac0f5..39f2d946d 100644
--- a/integration_test/mix.exs
+++ b/integration_test/mix.exs
@@ -40,11 +40,11 @@ defmodule Phoenix.Integration.MixProject do
       {:myxql, ">= 0.0.0"},
       {:tds, ">= 0.0.0"},
       {:ecto_sqlite3, ">= 0.0.0"},
-      # TODO bump to 0.18 on release
-      {:phoenix_live_view, github: "phoenixframework/phoenix_live_view", override: true},
+      {:phoenix_html, "~> 3.0"},
+      {:phoenix_live_view, "~> 0.18.1"},
       {:floki, ">= 0.30.0"},
       {:phoenix_live_reload, "~> 1.2"},
-      {:phoenix_live_dashboard, "~> 0.6"},
+      {:phoenix_live_dashboard, "~> 0.7"},
       {:telemetry_metrics, "~> 0.6"},
       {:telemetry_poller, "~> 1.0"},
       {:gettext, "~> 0.20"},
@@ -53,7 +53,9 @@ defmodule Phoenix.Integration.MixProject do
       {:plug_cowboy, "~> 2.5"},
       {:bcrypt_elixir, "~> 3.0"},
       {:argon2_elixir, "~> 3.0"},
-      {:pbkdf2_elixir, "~> 2.0"}
+      {:pbkdf2_elixir, "~> 2.0"},
+      {:heroicons, "~> 0.5"},
+      {:tailwind, "~> 0.1"}
     ]
   end
 end
diff --git a/integration_test/mix.lock b/integration_test/mix.lock
index 06a60461d..eff47f6d0 100644
--- a/integration_test/mix.lock
+++ b/integration_test/mix.lock
@@ -18,24 +18,26 @@
   "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
   "floki": {:hex, :floki, "0.32.1", "dfe3b8db3b793939c264e6f785bca01753d17318d144bd44b407fb3493acaa87", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "d4b91c713e4a784a3f7b1e3cc016eefc619f6b1c3898464222867cafd3c681a3"},
   "gettext": {:hex, :gettext, "0.20.0", "75ad71de05f2ef56991dbae224d35c68b098dd0e26918def5bb45591d5c8d429", [:mix], [], "hexpm", "1c03b177435e93a47441d7f681a7040bd2a816ece9e2666d1c9001035121eb3d"},
+  "heroicons": {:hex, :heroicons, "0.5.0", "4ae690b2808246cd67f8a0e1a8b81f22ed35ec4ba25039c87f02e6caa5e07142", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "cc3633d161c096f98a1fa6ca2f1361cd75da6804457c33116c8388c16d5ca141"},
   "html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
-  "jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"},
-  "mime": {:hex, :mime, "2.0.2", "0b9e1a4c840eafb68d820b0e2158ef5c49385d17fb36855ac6e7e087d4b1dcc5", [:mix], [], "hexpm", "e6a3f76b4c277739e36c2e21a2c640778ba4c3846189d5ab19f97f126df5f9b7"},
+  "jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
+  "mime": {:hex, :mime, "2.0.3", "3676436d3d1f7b81b5a2d2bd8405f412c677558c81b1c92be58c00562bb59095", [:mix], [], "hexpm", "27a30bf0db44d25eecba73755acf4068cbfe26a4372f9eb3e4ea3a45956bff6b"},
   "myxql": {:hex, :myxql, "0.6.2", "7346246e73035d6853c189d0478537a347d6e380a7227a5695ac9ecf4eb39959", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:geo, "~> 3.4", [hex: :geo, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "88094d5c90765fd93f2888a60285077fb937b8e5917570f7be2a3a6bf45e0e2a"},
   "pbkdf2_elixir": {:hex, :pbkdf2_elixir, "2.0.0", "fa10cf0a61e263e5bdcd6353d96cdd1f4c593fd0f8d734ba8f3e048832fd5f06", [:mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}], "hexpm", "a9bcb808583e63893d42a843669c0e9cdcc9183053b9984582281a8947393086"},
   "phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"},
   "phoenix_html": {:hex, :phoenix_html, "3.2.0", "1c1219d4b6cb22ac72f12f73dc5fad6c7563104d083f711c3fcd8551a1f4ae11", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "36ec97ba56d25c0136ef1992c37957e4246b649d620958a1f9fa86165f8bc54f"},
-  "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.6.5", "1495bb014be12c9a9252eca04b9af54246f6b5c1e4cd1f30210cd00ec540cf8e", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.3", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.17.7", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "ef4fa50dd78364409039c99cf6f98ab5209b4c5f8796c17f4db118324f0db852"},
+  "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.7.0", "9b5ab242e52c33596b132beaf97dccb9e59f7af941f41a22d0fa2465d0b63ab1", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "374d65e87e1e83528ea30852e34d4ad3022ddb92d642d43ec0b4e3c112046036"},
   "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.3.3", "3a53772a6118d5679bf50fc1670505a290e32a1d195df9e069d8c53ab040c054", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "766796676e5f558dbae5d1bdb066849673e956005e3730dfd5affd7a6da4abac"},
-  "phoenix_live_view": {:git, "https://github.com/phoenixframework/phoenix_live_view.git", "3fd6852d82ad00614ad5ac5b6bd3e5a475094734", []},
+  "phoenix_live_view": {:hex, :phoenix_live_view, "0.18.1", "1e1703e26d0580dbd84e9b668e6da164a368f125dfa3d813c9a098da508e2a72", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6 or ~> 1.7", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b785e1cc13b05e6d9482d3ca1eedfb24e8113fd6421b47996ba16b9d20869706"},
   "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"},
   "phoenix_view": {:hex, :phoenix_view, "1.1.2", "1b82764a065fb41051637872c7bd07ed2fdb6f5c3bd89684d4dca6e10115c95a", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "7ae90ad27b09091266f6adbb61e1d2516a7c3d7062c6789d46a7554ec40f3a56"},
   "plug": {:hex, :plug, "1.13.6", "187beb6b67c6cec50503e940f0434ea4692b19384d47e5fdfd701e93cadb4cc2", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "02b9c6b9955bce92c829f31d6284bf53c591ca63c4fb9ff81dfd0418667a34ff"},
   "plug_cowboy": {:hex, :plug_cowboy, "2.5.2", "62894ccd601cf9597e2c23911ff12798a8a18d237e9739f58a6b04e4988899fe", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ea6e87f774c8608d60c8d34022a7d073bd7680a0a013f049fc62bf35efea1044"},
-  "plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"},
+  "plug_crypto": {:hex, :plug_crypto, "1.2.3", "8f77d13aeb32bfd9e654cb68f0af517b371fb34c56c9f2b58fe3df1235c1251a", [:mix], [], "hexpm", "b5672099c6ad5c202c45f5a403f21a3411247f164e4a8fab056e5cd8a290f4a2"},
   "postgrex": {:hex, :postgrex, "0.16.3", "fac79a81a9a234b11c44235a4494d8565303fa4b9147acf57e48978a074971db", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "aeaae1d2d1322da4e5fe90d241b0a564ce03a3add09d7270fb85362166194590"},
   "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
   "swoosh": {:hex, :swoosh, "1.7.1", "53bb5b8efaf5577bbad1480fb057d8bcb7b16097aa015ab9f369a01592c961ec", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "8206d7da5038f0e11292b775b7e588fcd5dc74ac4dd8b661fe72f58207234747"},
+  "tailwind": {:hex, :tailwind, "0.1.9", "25ba09d42f7bfabe170eb67683a76d6ec2061952dc9bd263a52a99ba3d24bd4d", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "9213f87709c458aaec313bb5f2df2b4d2cedc2b630e4ae821bf3c54c47a56d0b"},
   "tds": {:hex, :tds, "2.3.0", "a8089e6af21152bbc96250638be17e6fd5f3deae1a0715cff6cc6313b2fae4d7", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.9 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "dc2ee23af1a7ee05bdc65fd75585e00ad2b8200e00daf9358dde5e385ee135af"},
   "telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"},
   "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"},
diff --git a/integration_test/test/code_generation/app_with_defaults_test.exs b/integration_test/test/code_generation/app_with_defaults_test.exs
index 7609a8e67..9796a983e 100644
--- a/integration_test/test/code_generation/app_with_defaults_test.exs
+++ b/integration_test/test/code_generation/app_with_defaults_test.exs
@@ -102,7 +102,7 @@ defmodule Phoenix.Integration.CodeGeneration.AppWithDefaultsTest do
         modify_file(Path.join(app_root_path, "lib/phx_blog_web/router.ex"), fn file ->
           inject_before_final_end(file, """
 
-            scope "/", PhxBlogWeb do
+            scope "/api", PhxBlogWeb do
               pipe_through [:api]
 
               resources "/posts", PostController, except: [:new, :edit]
diff --git a/integration_test/test/code_generation/app_with_mssql_adapter_test.exs b/integration_test/test/code_generation/app_with_mssql_adapter_test.exs
index d144f1892..7d6126dd5 100644
--- a/integration_test/test/code_generation/app_with_mssql_adapter_test.exs
+++ b/integration_test/test/code_generation/app_with_mssql_adapter_test.exs
@@ -39,7 +39,7 @@ defmodule Phoenix.Integration.CodeGeneration.AppWithMSSQLAdapterTest do
         modify_file(Path.join(app_root_path, "lib/default_mssql_app_web/router.ex"), fn file ->
           inject_before_final_end(file, """
 
-            scope "/", DefaultMssqlAppWeb do
+            scope "/api", DefaultMssqlAppWeb do
               pipe_through [:api]
 
               resources "/posts", PostController, except: [:new, :edit]
diff --git a/integration_test/test/code_generation/app_with_mysql_adapter_test.exs b/integration_test/test/code_generation/app_with_mysql_adapter_test.exs
index 9dc601df4..f349bee77 100644
--- a/integration_test/test/code_generation/app_with_mysql_adapter_test.exs
+++ b/integration_test/test/code_generation/app_with_mysql_adapter_test.exs
@@ -39,7 +39,7 @@ defmodule Phoenix.Integration.CodeGeneration.AppWithMySqlAdapterTest do
         modify_file(Path.join(app_root_path, "lib/default_mysql_app_web/router.ex"), fn file ->
           inject_before_final_end(file, """
 
-            scope "/", DefaultMysqlAppWeb do
+            scope "/api", DefaultMysqlAppWeb do
               pipe_through [:api]
 
               resources "/posts", PostController, except: [:new, :edit]
diff --git a/integration_test/test/code_generation/app_with_sqlite3_adapter.exs b/integration_test/test/code_generation/app_with_sqlite3_adapter.exs
index 94f397192..d748d81bd 100644
--- a/integration_test/test/code_generation/app_with_sqlite3_adapter.exs
+++ b/integration_test/test/code_generation/app_with_sqlite3_adapter.exs
@@ -39,7 +39,7 @@ defmodule Phoenix.Integration.CodeGeneration.AppWithSQLite3AdapterTest do
         modify_file(Path.join(app_root_path, "lib/default_sqlite3_app_web/router.ex"), fn file ->
           inject_before_final_end(file, """
 
-            scope "/", DefaultMysqlAppWeb do
+            scope "/api", DefaultMysqlAppWeb do
               pipe_through [:api]
 
               resources "/posts", PostController, except: [:new, :edit]
diff --git a/integration_test/test/code_generation/umbrella_app_with_defaults_test.exs b/integration_test/test/code_generation/umbrella_app_with_defaults_test.exs
index 5f81443fb..ee7148db3 100644
--- a/integration_test/test/code_generation/umbrella_app_with_defaults_test.exs
+++ b/integration_test/test/code_generation/umbrella_app_with_defaults_test.exs
@@ -83,7 +83,7 @@ defmodule Phoenix.Integration.CodeGeneration.UmbrellaAppWithDefaultsTest do
         modify_file(Path.join(web_root_path, "lib/rainy_day_web/router.ex"), fn file ->
           inject_before_final_end(file, """
 
-            scope "/", RainyDayWeb do
+            scope "/api", RainyDayWeb do
               pipe_through [:api]
 
               resources "/posts", PostController, except: [:new, :edit]
@@ -107,7 +107,7 @@ defmodule Phoenix.Integration.CodeGeneration.UmbrellaAppWithDefaultsTest do
         modify_file(Path.join(web_root_path, "lib/rainy_day_web/router.ex"), fn file ->
           inject_before_final_end(file, """
 
-            scope "/", RainyDayWeb do
+            scope "/api", RainyDayWeb do
               pipe_through [:api]
 
               resources "/posts", PostController, except: [:new, :edit]
diff --git a/priv/templates/phx.gen.auth/auth_test.exs b/priv/templates/phx.gen.auth/auth_test.exs
index 34ddce1f3..0ada665e4 100644
--- a/priv/templates/phx.gen.auth/auth_test.exs
+++ b/priv/templates/phx.gen.auth/auth_test.exs
@@ -230,9 +230,11 @@ defmodule <%= inspect auth_module %>Test do
     test "redirects if <%= schema.singular %> is not authenticated", %{conn: conn} do
       conn = conn |> fetch_flash() |> <%= inspect schema.alias %>Auth.require_authenticated_<%= schema.singular %>([])
       assert conn.halted
+
       assert redirected_to(conn) == ~p"<%= schema.route_prefix %>/log_in"
+
       assert Phoenix.Flash.get(conn.assigns.flash, :error) ==
-        "You must log in to access this page."
+               "You must log in to access this page."
     end
 
     test "stores the path to redirect to on GET", %{conn: conn} do
diff --git a/priv/templates/phx.gen.auth/confirmation_controller_test.exs b/priv/templates/phx.gen.auth/confirmation_controller_test.exs
index 84a0e8219..09390630f 100644
--- a/priv/templates/phx.gen.auth/confirmation_controller_test.exs
+++ b/priv/templates/phx.gen.auth/confirmation_controller_test.exs
@@ -26,8 +26,9 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         })
 
       assert redirected_to(conn) == ~p"/"
+
       assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
-        "If your email is in our system"
+               "If your email is in our system"
 
       assert Repo.get_by!(<%= inspect context.alias %>.<%= inspect schema.alias %>Token, <%= schema.singular %>_id: <%= schema.singular %>.id).context == "confirm"
     end
@@ -41,8 +42,9 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         })
 
       assert redirected_to(conn) == ~p"/"
+
       assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
-        "If your email is in our system"
+               "If your email is in our system"
 
       refute Repo.get_by(<%= inspect context.alias %>.<%= inspect schema.alias %>Token, <%= schema.singular %>_id: <%= schema.singular %>.id)
     end
@@ -54,8 +56,9 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         })
 
       assert redirected_to(conn) == ~p"/"
+
       assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
-        "If your email is in our system"
+               "If your email is in our system"
 
       assert Repo.all(<%= inspect context.alias %>.<%= inspect schema.alias %>Token) == []
     end
@@ -64,7 +67,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
   describe "GET <%= schema.route_prefix %>/confirm/:token" do
     test "renders the confirmation page", %{conn: conn} do
       token_path = ~p"<%= schema.route_prefix %>/confirm/some-token"
-      conn = get(conn, path)
+      conn = get(conn, token_path)
       response = html_response(conn, 200)
       assert response =~ "Confirm account"
 
@@ -81,8 +84,9 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
 
       conn = post(conn, ~p"<%= schema.route_prefix %>/confirm/#{token}")
       assert redirected_to(conn) == ~p"/"
+
       assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
-        "<%= schema.human_singular %> confirmed successfully"
+               "<%= schema.human_singular %> confirmed successfully"
 
       assert <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id).confirmed_at
       refute get_session(conn, :<%= schema.singular %>_token)
@@ -91,9 +95,9 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
       # When not logged in
       conn = post(conn, ~p"<%= schema.route_prefix %>/confirm/#{token}")
       assert redirected_to(conn) == ~p"/"
-      assert Phoenix.Flash.get(conn.assigns.flash, :error) =~
-        "<%= schema.human_singular %> confirmation link is invalid or it has expired"
 
+      assert Phoenix.Flash.get(conn.assigns.flash, :error) =~
+               "<%= schema.human_singular %> confirmation link is invalid or it has expired"
 
       # When logged in
       conn =
@@ -103,15 +107,14 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
 
       assert redirected_to(conn) == ~p"/"
       refute Phoenix.Flash.get(conn.assigns.flash, :error)
-    en
-
-
+    end
 
     test "does not confirm email with invalid token", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
       conn = post(conn, ~p"<%= schema.route_prefix %>/confirm/oops")
       assert redirected_to(conn) == ~p"/"
+
       assert Phoenix.Flash.get(conn.assigns.flash, :error) =~
-        "<%= schema.human_singular %> confirmation link is invalid or it has expired"
+               "<%= schema.human_singular %> confirmation link is invalid or it has expired"
 
       refute <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id).confirmed_at
     end
diff --git a/priv/templates/phx.gen.auth/confirmation_instructions_live_test.exs b/priv/templates/phx.gen.auth/confirmation_instructions_live_test.exs
index 1a59489db..4a9488d02 100644
--- a/priv/templates/phx.gen.auth/confirmation_instructions_live_test.exs
+++ b/priv/templates/phx.gen.auth/confirmation_instructions_live_test.exs
@@ -27,7 +27,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         |> follow_redirect(conn, ~p"/")
 
       assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
-        "If your email is in our system"
+               "If your email is in our system"
 
       assert Repo.get_by!(<%= inspect context.alias %>.<%= inspect schema.alias %>Token, <%= schema.singular %>_id: <%= schema.singular %>.id).context == "confirm"
     end
@@ -44,7 +44,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         |> follow_redirect(conn, ~p"/")
 
       assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
-        "If your email is in our system"
+               "If your email is in our system"
 
       refute Repo.get_by(<%= inspect context.alias %>.<%= inspect schema.alias %>Token, <%= schema.singular %>_id: <%= schema.singular %>.id)
     end
@@ -59,7 +59,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         |> follow_redirect(conn, ~p"/")
 
       assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
-        "If your email is in our system"
+               "If your email is in our system"
 
       assert Repo.all(<%= inspect context.alias %>.<%= inspect schema.alias %>Token) == []
     end
diff --git a/priv/templates/phx.gen.auth/confirmation_live_test.exs b/priv/templates/phx.gen.auth/confirmation_live_test.exs
index 22abeb500..421102141 100644
--- a/priv/templates/phx.gen.auth/confirmation_live_test.exs
+++ b/priv/templates/phx.gen.auth/confirmation_live_test.exs
@@ -32,8 +32,9 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         |> follow_redirect(conn, "/")
 
       assert {:ok, conn} = result
+
       assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
-        "<%= inspect schema.alias %> confirmed successfully"
+               "<%= inspect schema.alias %> confirmed successfully"
 
       assert <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id).confirmed_at
       refute get_session(conn, :<%= schema.singular %>_token)
@@ -49,9 +50,9 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         |> follow_redirect(conn, "/")
 
       assert {:ok, conn} = result
-      assert Phoenix.Flash.get(conn.assigns.flash, :error) =~
-        "<%= inspect schema.alias %> confirmation link is invalid or it has expired"
 
+      assert Phoenix.Flash.get(conn.assigns.flash, :error) =~
+               "<%= inspect schema.alias %> confirmation link is invalid or it has expired"
 
       # when logged in
       {:ok, lv, _html} =
@@ -69,8 +70,6 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
       refute Phoenix.Flash.get(conn.assigns.flash, :error)
     end
 
-
-
     test "does not confirm email with invalid token", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
       {:ok, lv, _html} = live(conn, ~p"<%= schema.route_prefix %>/confirm/invalid-token")
 
@@ -81,7 +80,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         |> follow_redirect(conn, ~p"/")
 
       assert Phoenix.Flash.get(conn.assigns.flash, :error) =~
-        "<%= inspect schema.alias %> confirmation link is invalid or it has expired"
+               "<%= inspect schema.alias %> confirmation link is invalid or it has expired"
 
       refute <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id).confirmed_at
     end
diff --git a/priv/templates/phx.gen.auth/registration_controller_test.exs b/priv/templates/phx.gen.auth/registration_controller_test.exs
index f691d31b2..c1a769084 100644
--- a/priv/templates/phx.gen.auth/registration_controller_test.exs
+++ b/priv/templates/phx.gen.auth/registration_controller_test.exs
@@ -13,7 +13,8 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
     end
 
     test "redirects if already logged in", %{conn: conn} do
-      conn = conn |> log_in_<%= schema.singular %>(<%= schema.singular %>_fixture()) |> get(Routes.<%= schema.route_helper %>_registration_path(conn, :new))
+      conn = conn |> log_in_<%= schema.singular %>(<%= schema.singular %>_fixture()) |> get(~p"<%= schema.route_prefix %>/register")
+
       assert redirected_to(conn) == ~p"/"
     end
   end
diff --git a/priv/templates/phx.gen.auth/reset_password_controller_test.exs b/priv/templates/phx.gen.auth/reset_password_controller_test.exs
index 522bdd223..8ce98ab98 100644
--- a/priv/templates/phx.gen.auth/reset_password_controller_test.exs
+++ b/priv/templates/phx.gen.auth/reset_password_controller_test.exs
@@ -26,8 +26,9 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         })
 
       assert redirected_to(conn) == ~p"/"
+
       assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
-        "If your email is in our system"
+               "If your email is in our system"
 
       assert Repo.get_by!(<%= inspect context.alias %>.<%= inspect schema.alias %>Token, <%= schema.singular %>_id: <%= schema.singular %>.id).context == "reset_password"
     end
@@ -39,8 +40,9 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         })
 
       assert redirected_to(conn) == ~p"/"
+
       assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
-        "If your email is in our system"
+               "If your email is in our system"
 
       assert Repo.all(<%= inspect context.alias %>.<%= inspect schema.alias %>Token) == []
     end
@@ -58,15 +60,15 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
 
     test "renders reset password", %{conn: conn, token: token} do
       conn = get(conn, ~p"<%= schema.route_prefix %>/reset_password/#{token}")
-      assert html_response(conn, 200) =~ "Reset password"
+      assert html_response(conn, 200) =~ "Send password reset instructions"
     end
 
     test "does not render reset password with invalid token", %{conn: conn} do
       conn = get(conn, ~p"<%= schema.route_prefix %>/reset_password/oops")
       assert redirected_to(conn) == ~p"/"
-      assert Phoenix.Flash.get(conn.assigns.flash, :error) =~
-        "Reset password link is invalid or it has expired"
 
+      assert Phoenix.Flash.get(conn.assigns.flash, :error) =~
+               "Reset password link is invalid or it has expired"
     end
   end
 
@@ -91,8 +93,9 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
 
       assert redirected_to(conn) == ~p"<%= schema.route_prefix %>/log_in"
       refute get_session(conn, :<%= schema.singular %>_token)
+
       assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
-        "Password reset successfully"
+               "Password reset successfully"
 
       assert <%= inspect context.alias %>.get_<%= schema.singular %>_by_email_and_password(<%= schema.singular %>.email, "new valid password")
     end
@@ -106,18 +109,15 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
           }
         })
 
-      response = html_response(conn, 200)
-      assert response =~ "Reset password"
-      assert response =~ "should be at least 12 character(s)"
-      assert response =~ "does not match password"
+      assert html_response(conn, 200) =~ "something went wrong"
     end
 
     test "does not reset password with invalid token", %{conn: conn} do
       conn = put(conn, ~p"<%= schema.route_prefix %>/reset_password/oops")
       assert redirected_to(conn) == ~p"/"
-      assert Phoenix.Flash.get(conn.assigns.flash, :error) =~
-        "Reset password link is invalid or it has expired"
 
+      assert Phoenix.Flash.get(conn.assigns.flash, :error) =~
+               "Reset password link is invalid or it has expired"
     end
   end
 end
diff --git a/priv/templates/phx.gen.auth/session_controller_test.exs b/priv/templates/phx.gen.auth/session_controller_test.exs
index 8348baa47..18fe5bfef 100644
--- a/priv/templates/phx.gen.auth/session_controller_test.exs
+++ b/priv/templates/phx.gen.auth/session_controller_test.exs
@@ -13,7 +13,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
       response = html_response(conn, 200)
       assert response =~ "Log in"
       assert response =~ "Register</a>"
-      assert response =~ "Forgot your password?</a>"
+      assert response =~ "Forgot your password?"
     end
 
     test "redirects if already logged in", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
diff --git a/priv/templates/phx.gen.auth/settings_controller_test.exs b/priv/templates/phx.gen.auth/settings_controller_test.exs
index 053025ac6..7c83ed554 100644
--- a/priv/templates/phx.gen.auth/settings_controller_test.exs
+++ b/priv/templates/phx.gen.auth/settings_controller_test.exs
@@ -33,9 +33,11 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         })
 
       assert redirected_to(new_password_conn) == ~p"<%= schema.route_prefix %>/settings"
+
       assert get_session(new_password_conn, :<%= schema.singular %>_token) != get_session(conn, :<%= schema.singular %>_token)
+
       assert Phoenix.Flash.get(new_password_conn.assigns.flash, :info) =~
-        "Password updated successfully"
+               "Password updated successfully"
 
       assert <%= inspect context.alias %>.get_<%= schema.singular %>_by_email_and_password(<%= schema.singular %>.email, "new valid password")
     end
@@ -72,8 +74,9 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
         })
 
       assert redirected_to(conn) == ~p"<%= schema.route_prefix %>/settings"
+
       assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
-        "A link to confirm your email"
+               "A link to confirm your email"
 
       assert <%= inspect context.alias %>.get_<%= schema.singular %>_by_email(<%= schema.singular %>.email)
     end
@@ -108,24 +111,27 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
     test "updates the <%= schema.singular %> email once", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>, token: token, email: email} do
       conn = get(conn, ~p"<%= schema.route_prefix %>/settings/confirm_email/#{token}")
       assert redirected_to(conn) == ~p"<%= schema.route_prefix %>/settings"
+
       assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
-        "Email changed successfully"
+               "Email changed successfully"
 
       refute <%= inspect context.alias %>.get_<%= schema.singular %>_by_email(<%= schema.singular %>.email)
       assert <%= inspect context.alias %>.get_<%= schema.singular %>_by_email(email)
 
       conn = get(conn, ~p"<%= schema.route_prefix %>/settings/confirm_email/#{token}")
+
       assert redirected_to(conn) == ~p"<%= schema.route_prefix %>/settings"
-      assert Phoenix.Flash.get(conn.assigns.flash, :error) =~
-        "Email change link is invalid or it has expired"
 
+      assert Phoenix.Flash.get(conn.assigns.flash, :error) =~
+               "Email change link is invalid or it has expired"
     end
 
     test "does not update email with invalid token", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
       conn = get(conn, ~p"<%= schema.route_prefix %>/settings/confirm_email/oops")
       assert redirected_to(conn) == ~p"<%= schema.route_prefix %>/settings"
+
       assert Phoenix.Flash.get(conn.assigns.flash, :error) =~
-        "Email change link is invalid or it has expired"
+               "Email change link is invalid or it has expired"
 
       assert <%= inspect context.alias %>.get_<%= schema.singular %>_by_email(<%= schema.singular %>.email)
     end
diff --git a/priv/templates/phx.gen.auth/settings_live_test.exs b/priv/templates/phx.gen.auth/settings_live_test.exs
index 875cae3f5..45503e3fd 100644
--- a/priv/templates/phx.gen.auth/settings_live_test.exs
+++ b/priv/templates/phx.gen.auth/settings_live_test.exs
@@ -109,9 +109,11 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
       new_password_conn = follow_trigger_action(form, conn)
 
       assert redirected_to(new_password_conn) == ~p"<%= schema.route_prefix %>/settings"
+
       assert get_session(new_password_conn, :<%= schema.singular %>_token) != get_session(conn, :<%= schema.singular %>_token)
+
       assert Phoenix.Flash.get(new_password_conn.assigns.flash, :info) =~
-        "Password updated successfully"
+               "Password updated successfully"
 
       assert <%= inspect context.alias %>.get_<%= schema.singular %>_by_email_and_password(<%= schema.singular %>.email, new_password)
     end
diff --git a/test/mix/tasks/phx.digest_test.exs b/test/mix/tasks/phx.digest_test.exs
index ddeba6ac0..ea0bb6b5c 100644
--- a/test/mix/tasks/phx.digest_test.exs
+++ b/test/mix/tasks/phx.digest_test.exs
@@ -5,8 +5,9 @@ defmodule Mix.Tasks.Phx.DigestTest do
   import MixHelper
 
   test "fails when the given paths are invalid" do
-    Mix.Tasks.Phx.Digest.run(["invalid_path", "--no-deps-check"])
+    exit_code = catch_exit(Mix.Tasks.Phx.Digest.run(["invalid_path", "--no-deps-check"]))
     assert_received {:mix_shell, :error, ["The input path \"invalid_path\" does not exist"]}
+    assert exit_code == {:shutdown, 1}
   end
 
   @output_path "mix_phoenix_digest"
diff --git a/test/mix/tasks/phx.gen.auth/injector_test.exs b/test/mix/tasks/phx.gen.auth/injector_test.exs
index 63c2ccc89..679b0e91b 100644
--- a/test/mix/tasks/phx.gen.auth/injector_test.exs
+++ b/test/mix/tasks/phx.gen.auth/injector_test.exs
@@ -667,12 +667,22 @@ defmodule Mix.Tasks.Phx.Gen.Auth.InjectorTest do
                          </ul>
                          <ul>
                            <%= if @current_user do %>
-                             <li><%= @current_user.email %></li>
-                             <li><.link href={~p"/users/settings"}>Settings</.link></li>
-                             <li><.link href={~p"/users/log_out"} method="delete">Log out</.link></li>
+                             <li>
+                               <%= @current_user.email %>
+                             </li>
+                             <li>
+                               <.link href={~p"/users/settings"}>Settings</.link>
+                             </li>
+                             <li>
+                               <.link href={~p"/users/log_out"} method="delete">Log out</.link>
+                             </li>
                            <% else %>
-                             <li><.link href={~p"/users/register"}>Register</.link></li>
-                             <li><.link href={~p"/users/log_in"}>Log in</.link></li>
+                             <li>
+                               <.link href={~p"/users/register"}>Register</.link>
+                             </li>
+                             <li>
+                               <.link href={~p"/users/log_in"}>Log in</.link>
+                             </li>
                            <% end %>
                          </ul>
                        </nav>
@@ -730,12 +740,22 @@ defmodule Mix.Tasks.Phx.Gen.Auth.InjectorTest do
                          </ul>\r
                          <ul>\r
                            <%= if @current_user do %>\r
-                             <li><%= @current_user.email %></li>\r
-                             <li><.link href={~p"/users/settings"}>Settings</.link></li>\r
-                             <li><.link href={~p"/users/log_out"} method="delete">Log out</.link></li>\r
+                             <li>\r
+                               <%= @current_user.email %>\r
+                             </li>\r
+                             <li>\r
+                               <.link href={~p"/users/settings"}>Settings</.link>\r
+                             </li>\r
+                             <li>\r
+                               <.link href={~p"/users/log_out"} method="delete">Log out</.link>\r
+                             </li>\r
                            <% else %>\r
-                             <li><.link href={~p"/users/register"}>Register</.link></li>\r
-                             <li><.link href={~p"/users/log_in"}>Log in</.link></li>\r
+                             <li>\r
+                               <.link href={~p"/users/register"}>Register</.link>\r
+                             </li>\r
+                             <li>\r
+                               <.link href={~p"/users/log_in"}>Log in</.link>\r
+                             </li>\r
                            <% end %>\r
                          </ul>\r
                        </nav>\r
@@ -777,12 +797,22 @@ defmodule Mix.Tasks.Phx.Gen.Auth.InjectorTest do
                  <body>
                    <ul>
                      <%= if @current_user do %>
-                       <li><%= @current_user.email %></li>
-                       <li><.link href={~p"/users/settings"}>Settings</.link></li>
-                       <li><.link href={~p"/users/log_out"} method="delete">Log out</.link></li>
+                       <li>
+                         <%= @current_user.email %>
+                       </li>
+                       <li>
+                         <.link href={~p"/users/settings"}>Settings</.link>
+                       </li>
+                       <li>
+                         <.link href={~p"/users/log_out"} method="delete">Log out</.link>
+                       </li>
                      <% else %>
-                       <li><.link href={~p"/users/register"}>Register</.link></li>
-                       <li><.link href={~p"/users/log_in"}>Log in</.link></li>
+                       <li>
+                         <.link href={~p"/users/register"}>Register</.link>
+                       </li>
+                       <li>
+                         <.link href={~p"/users/log_in"}>Log in</.link>
+                       </li>
                      <% end %>
                    </ul>
                    <main class="container">
@@ -826,12 +856,22 @@ defmodule Mix.Tasks.Phx.Gen.Auth.InjectorTest do
                  <body>\r
                    <ul>\r
                      <%= if @current_user do %>\r
-                       <li><%= @current_user.email %></li>\r
-                       <li><.link href={~p"/users/settings"}>Settings</.link></li>\r
-                       <li><.link href={~p"/users/log_out"} method="delete">Log out</.link></li>\r
+                       <li>\r
+                         <%= @current_user.email %>\r
+                       </li>\r
+                       <li>\r
+                         <.link href={~p"/users/settings"}>Settings</.link>\r
+                       </li>\r
+                       <li>\r
+                         <.link href={~p"/users/log_out"} method="delete">Log out</.link>\r
+                       </li>\r
                      <% else %>\r
-                       <li><.link href={~p"/users/register"}>Register</.link></li>\r
-                       <li><.link href={~p"/users/log_in"}>Log in</.link></li>\r
+                       <li>\r
+                         <.link href={~p"/users/register"}>Register</.link>\r
+                       </li>\r
+                       <li>\r
+                         <.link href={~p"/users/log_in"}>Log in</.link>\r
+                       </li>\r
                      <% end %>\r
                    </ul>\r
                    <main class="container">\r
diff --git a/test/mix/tasks/phx.gen.auth_test.exs b/test/mix/tasks/phx.gen.auth_test.exs
index 763be1755..8d7b3f520 100644
--- a/test/mix/tasks/phx.gen.auth_test.exs
+++ b/test/mix/tasks/phx.gen.auth_test.exs
@@ -315,6 +315,7 @@ defmodule Mix.Tasks.Phx.Gen.AuthTest do
                    pipe_through [:browser]
 
                    delete "/users/log_out", UserSessionController, :delete
+
                    live_session :current_user,
                      on_mount: [{MyAppWeb.UserAuth, :mount_current_user}] do
                      live "/users/confirm/:token", UserConfirmationLive, :edit
@@ -412,6 +413,7 @@ defmodule Mix.Tasks.Phx.Gen.AuthTest do
                    pipe_through [:browser]
 
                    delete "/users/log_out", UserSessionController, :delete
+
                    live_session :current_user,
                      on_mount: [{MyAppWeb.UserAuth, :mount_current_user}] do
                      live "/users/confirm/:token", UserConfirmationLive, :edit
@@ -647,7 +649,7 @@ defmodule Mix.Tasks.Phx.Gen.AuthTest do
                  ~S|<.simple_form :let={f} for={@email_changeset} action={~p"/warehouse/users/settings"} id="update_email">|
 
         assert file =~
-                 ~S|<.simple_form :let={f} for={@password_changeset} action={~p"/warehouse/users/settings"} id="update_password">|
+                 ~s|<.simple_form\n      :let={f}\n      for={@password_changeset}\n      action={~p"/warehouse/users/settings"}\n      id="update_password"\n    >|
       end)
 
       assert_file("lib/my_app_web/views/warehouse/user_settings_view.ex", fn file ->
@@ -1356,12 +1358,22 @@ defmodule Mix.Tasks.Phx.Gen.AuthTest do
 
             <ul>
               <%= if @current_user do %>
-                <li><%= @current_user.email %></li>
-                <li><.link href={~p"/users/settings"}>Settings</.link></li>
-                <li><.link href={~p"/users/log_out"} method="delete">Log out</.link></li>
+                <li>
+                  <%= @current_user.email %>
+                </li>
+                <li>
+                  <.link href={~p"/users/settings"}>Settings</.link>
+                </li>
+                <li>
+                  <.link href={~p"/users/log_out"} method="delete">Log out</.link>
+                </li>
               <% else %>
-                <li><.link href={~p"/users/register"}>Register</.link></li>
-                <li><.link href={~p"/users/log_in"}>Log in</.link></li>
+                <li>
+                  <.link href={~p"/users/register"}>Register</.link>
+                </li>
+                <li>
+                  <.link href={~p"/users/log_in"}>Log in</.link>
+                </li>
               <% end %>
             </ul>
         """
@@ -1390,16 +1402,27 @@ defmodule Mix.Tasks.Phx.Gen.AuthTest do
 
             <ul>
               <%= if @current_user do %>
-                <li><%= @current_user.email %></li>
-                <li><.link href={~p"/users/settings"}>Settings</.link></li>
-                <li><.link href={~p"/users/log_out"} method="delete">Log out</.link></li>
+                <li>
+                  <%= @current_user.email %>
+                </li>
+                <li>
+                  <.link href={~p"/users/settings"}>Settings</.link>
+                </li>
+                <li>
+                  <.link href={~p"/users/log_out"} method="delete">Log out</.link>
+                </li>
               <% else %>
-                <li><.link href={~p"/users/register"}>Register</.link></li>
-                <li><.link href={~p"/users/log_in"}>Log in</.link></li>
+                <li>
+                  <.link href={~p"/users/register"}>Register</.link>
+                </li>
+                <li>
+                  <.link href={~p"/users/log_in"}>Log in</.link>
+                </li>
               <% end %>
             </ul>
 
         """
+
         assert_received {:mix_shell, :info, [^help_text]}
       end)
     end
diff --git a/test/mix/tasks/phx.gen.presence_test.exs b/test/mix/tasks/phx.gen.presence_test.exs
index b3d86d845..be983ad51 100644
--- a/test/mix/tasks/phx.gen.presence_test.exs
+++ b/test/mix/tasks/phx.gen.presence_test.exs
@@ -15,7 +15,8 @@ defmodule Mix.Tasks.Phx.Gen.PresenceTest do
 
       assert_file "lib/phoenix_web/channels/my_presence.ex", fn file ->
         assert file =~ ~S|defmodule PhoenixWeb.MyPresence do|
-        assert file =~ ~S|use Phoenix.Presence, otp_app: :phoenix|
+        assert file =~ ~S|use Phoenix.Presence|
+        assert file =~ ~S|otp_app: :phoenix|
         assert file =~ ~S|pubsub_server: Phoenix.PubSub|
       end
     end
@@ -27,7 +28,8 @@ defmodule Mix.Tasks.Phx.Gen.PresenceTest do
 
       assert_file "lib/phoenix_web/channels/presence.ex", fn file ->
         assert file =~ ~S|defmodule PhoenixWeb.Presence do|
-        assert file =~ ~S|use Phoenix.Presence, otp_app: :phoenix|
+        assert file =~ ~S|use Phoenix.Presence|
+        assert file =~ ~S|otp_app: :phoenix|
         assert file =~ ~S|pubsub_server: Phoenix.PubSub|
       end
     end