Repository: phoenixframework/phoenix
Pull request #6002 (2024-12-06 17:38:05)

Refer to `MIX_TARGET` not `MIX_BUILD` in docs around separate build directories
I couldn't find reference to `MIX_BUILD` in the Mix docs, but I think `MIX_TARGET` is what's meant to be referred to here.

See https://hexdocs.pm/mix/Mix.html#module-environment-variables and https://hexdocs.pm/mix/Mix.html#module-targets for more info.


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c11117b32..6685cb92c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -22,8 +22,11 @@ jobs:
           - elixir: 1.14.5
             otp: 25.3.2.9
 
+          - elixir: 1.15.x
+            otp: 25.x
+
           - elixir: 1.17.3
-            otp: 27.1
+            otp: 27.2
             lint: true
             installer: true
 
diff --git a/.gitignore b/.gitignore
index 44fba2603..e46730c56 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@
 /installer/deps/
 /installer/doc/
 /installer/phx_new-*.ez
+/installer/tmp/
 
 /integration_test/_build/
 /integration_test/deps/
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d3849ce1c..2cc0b330c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,241 +1,5 @@
-# Changelog for v1.7
+# Changelog for v1.8
 
-See the [upgrade guide](https://gist.github.com/chrismccord/00a6ea2a96bc57df0cce526bd20af8a7) to upgrade from Phoenix 1.6.x.
+## v1.7
 
-Phoenix v1.7 requires Elixir v1.11+ & Erlang v22.1+.
-
-## Introduction of Verified Routes
-
-Phoenix 1.7 includes a new `Phoenix.VerifiedRoutes` feature which provides `~p`
-for route generation with compile-time verification.
-
-Use of the `sigil_p` macro allows paths and URLs throughout your
-application to be compile-time verified against your Phoenix router(s).
-For example the following path and URL usages:
-
-    <.link href={~p"/sessions/new"} method="post">Log in</.link>
-
-    redirect(to: url(~p"/posts/#{post}"))
-
-Will be verified against your standard `Phoenix.Router` definitions:
-
-    get "/posts/:post_id", PostController, :show
-    post "/sessions/new", SessionController, :create
-
-Unmatched routes will issue compiler warnings:
-
-    warning: no route path for AppWeb.Router matches "/postz/#{post}"
-      lib/app_web/controllers/post_controller.ex:100: AppWeb.PostController.show/2
-
-*Note: Elixir v1.14+ is required for comprehensive warnings. Older versions
-will work properly and warn on new compilations, but changes to the router file
-will not issue new warnings.*
-
-This feature replaces the `Helpers` module generated in your Phoenix router, but helpers
-will continue to work and be generated. You can disable router helpers by passing the
-`helpers: false` option to `use Phoenix.Router`.
-
-## phx.new revamp
-
-The `phx.new` application generator has been improved to rely on function components for
-both Controller and LiveView rendering, ultimately simplifying the rendering stack of
-Phoenix applications and providing better reuse.
-
-New applications come with a collection of well-documented and accessible core components,
-styled with Tailwind CSS by default. You can opt-out of Tailwind CSS with the `--no-tailwind`
-flag (the Tailwind CSS classes are kept in the generated components as reference for
-future styling).
-
-## 1.7.14 (2024-06-18)
-
-### Bug fixes
-  * Revert "Add `follow_redirect/2` to Phoenix.ConnTest" (#5797) as this conflicts with `follow_redirect/2` in LiveView, which is imported with ConnTest by default
-
-## 1.7.13 (2024-06-18)
-
-### Bug fixes
-  * Fix Elixir 1.17 warning in Cowboy2Adapter
-  * Fix verified routes emitting diagnostics without file and position
-
-### JavaScript Client Bug Fixes
-  * Fix error when `sessionStorage` is not available on global namespace
-
-### Enhancements
-  * Add `follow_redirect/2` to Phoenix.ConnTest
-  * Use LiveView 1.0.0-rc for newly generated applications
-  * Use new `Phoenix.Component.used_input?` for form errors in generated `core_components.ex`
-  * Allow `mix ecto.setup` from the umbrella root
-  * Bump Endpoint static cache manifest on `config_change` callback
-
-## 1.7.12 (2024-04-11)
-
-### JavaScript Client Bug Fixes
-  * Fix all unjoined channels from being removed from the socket when channel leave is called on any single unjoined channel instance
-
-### Enhancements
-  * [phx.gen.auth] Add enhanced session fixation protection.
-    For applications whichs previously used `phx.gen.auth`, the following line can be added to the `renew_session` function in the auth module:
-
-    ```diff
-      defp renew_session(conn) do
-    +   delete_csrf_token()
-
-        conn
-        |> configure_session(renew: true)
-        |> clear_session()
-    ```
-
-    *Note*: because the session id is in a http-only cookie by default, the only way to perform this attack prior to this change is if your application was already vulnerable to an XSS attack, which itself grants more escalated "privileges” than the CSRF fixation.
-
-### JavaScript Client Enhancements
-  * Only memorize longpoll fallback for browser session if WebSocket never had a successful connection
-
-## 1.7.11 (2024-02-01)
-
-### Enhancements
-  * [phx.new] Default to the [Bandit webserver](https://github.com/mtrudel/bandit) for newly generated applications
-  * [phx.new] Enable longpoll transport by default and auto fallback when websocket fails for newly generated applications
-
-### JavaScript Client Enhancements
-  * Support new `longPollFallbackMs` option to auto fallback when websocket fails to connect
-  * Support new `debug` option to enable verbose logging
-
-### Deprecations
-  * Deprecate the `c:init/2` callback in endpoints in favor of `config/runtime.exs` or in favor of `{Phoenix.Endpoint, options}`
-
-## 1.7.10 (2023-11-03)
-
-### Bug fixes
-  * [phx.new] Fix `CoreComponents.flash` generating incorrect id's causing flash messages to fail to be closed when clicked
-
-### Enhancements
-  * [Phoenix.Endpoint] Support dynamic port for `Endpoint.url/0`
-
-## 1.7.9 (2023-10-11)
-
-### Bug fixes
-  * [Phoenix.CodeReloader] - Fix error in code reloader causing compilation errors
-  * [phx.new] – fix LiveView debug heex configuration being generated when `--no-html` pas passed
-
-## 1.7.8 (2023-10-09)
-
-### Bug fixes
-  * [Phoenix.ChannelTest] Stringify lists when pushing data
-  * [Phoenix.Controller] Fix filename when sending downloads with non-ascii names
-  * [Phoenix.CodeReloader] Remove duplicate warnings on recent Elixir versions
-  * [Phoenix.CodeReloader] Do not crash code reloader if file information is missing from diagnostic
-  * [Phoenix.Logger] Do not crash when status is atom
-  * [phx.gen.release] Fix `mix phx.gen.release --docker` failing with `:http_util` error on Elixir v1.15
-  * [phx.gen.*] Skip map inputs in generated forms as there is no trivial matching input
-  * [phx.new] Fix tailwind/esbuild config and paths in umbrella projects
-  * [phx.new] Do not render `th` for actions if actions are empty
-
-### Enhancements
-  * [Phoenix] Allow latest `plug_crypto`
-  * [Phoenix.Endpoint] Support dynamic socket drainer configuration
-  * [Phoenix.Logger] Change socket serializer/version logs to warning
-  * [Phoenix.VerifiedRoutes] Add support for static resources with fragments in `~p`
-  * [phx.gen.schema] Support `--repo` and `--migration-dir` flags
-  * [phx.new] Allow `<.input type="checkbox">` without `value` attr in core components
-  * [phx.new] Allow UTC datetimes in the generators
-  * [phx.new] Automatically migrate when release starts when using sqlite 3
-  * [phx.new] Allow ID to be assigned in flash component
-  * [phx.new] Add `--adapter` flag for generating application with bandit
-  * [phx.new] Include DNSCluster for simple clustering
-  * [phx.routes] Support `--method` option
-
-## 1.7.7 (2023-07-10)
-
-### Enhancements
-  * Support incoming binary payloads to channels over longpoll transport
-
-## 1.7.6 (2023-06-16)
-
-### Bug Fixes
-  * Support websock_adapter 0.5.3
-
-### Enhancements
-  *  Allow using Phoenix.ChannelTest socket/connect in another process
-
-## 1.7.5 (2023-06-15)
-
-### Bug Fixes
-  * Fix LongPoll error when draining connections
-
-## 1.7.4 (2023-06-15)
-
-### Bug Fixes
-  * Fix the WebSocket draining sending incorrect close code when draining causing LiveViews to reload the page instead of reconnecting
-
-## 1.7.3 (2023-05-30)
-
-### Enhancements
-  * Use LiveView 0.19 for new apps
-
-### Bug Fixes
-  * Fix compilation error page on plug debugger showing obscure error when app fails to compile
-  * Fix warnings being printed twice in route verification
-
-## 1.7.2 (2023-03-20)
-
-### Enhancements
-  * [Endpoint] Add socket draining for batched and orchestrated Channel/LiveView socket shutdown
-  * [code reloader] Improve the compilation error page to remove horizontal scrolling and include all warnings and errors from compilation
-  * [phx.new] Support the `--no-tailwind` and `--no-esbuild` flags
-  * [phx.new] Move heroicons to assets/vendor
-  * [phx.new] Simplify core modal to use the new JS.exec instruction to reduce footprint
-  * [sockets] Allow custom csrf_token_keys in WebSockets
-
-## 1.7.1 (2023-03-02)
-
-### Enhancements
-  * [phx.new] Embed heroicons in app.css bundle to optimize usage
-
-## 1.7.0 (2023-02-24)
-
-### Bug Fixes
-  * Fix race conditions in the longpoll transport by batching messages
-
-## 1.7.0-rc.3 (2023-02-15)
-
-### Enhancements
-  * Use stream based collections for `phx.gen.live` generators
-  * Update `phx.gen.live` generators to use `Phoenix.Component.to_form`
-
-## 1.7.0-rc.2 (2023-01-13)
-
-### Bug Fixes
-  * [Router] Fix routing bug causing incorrect matching order on similar routes
-  * [phx.new] Fix installation hanging in some cases
-
-## 1.7.0-rc.1 (2023-01-06)
-
-### Enhancements
-  * Raise if using verified routes outside of functions
-  * Add tailwind.install/esbuild.install to mix setup
-
-### Bug Fixes
-  * [Presence] fix task shutdown match causing occasional presence errors
-  * [VerifiedRoutes] Fix expansion causing more compile-time deps than necessary
-  * [phx.gen.auth] Add password inputs to password reset edit form
-  * [phx.gen.embedded] Fixes missing :references generation to phx.gen.embedded
-  * Fix textarea rendering in core components
-  * Halt all sockets on intercept to fix longpoll response already sent error
-
-## 1.7.0-rc.0 (2022-11-07)
-
-### Deprecations
-  * `Phoenix.Controller.get_flash` has been deprecated in favor of the new `Phoenix.Flash` module, which provides unified flash access
-
-### Enhancements
-  * [Router] Add `Phoenix.VerifiedRoutes` for `~p`-based route generation with compile-time verification.
-  * [Router] Support `helpers: false` to `use Phoenix.Router` to disable helper generation
-  * [Router] Add `--info [url]` switch to `phx.routes` to get route information about a url/path
-  * [Flash] Add `Phoenix.Flash` for unfied flash access
-
-### JavaScript Client Bug Fixes
-  * Fix heartbeat being sent after disconnect and causing abnormal disconnects
-
-## v1.6
-
-The CHANGELOG for v1.6 releases can be found in the [v1.6 branch](https://github.com/phoenixframework/phoenix/blob/v1.6/CHANGELOG.md).
+The CHANGELOG for v1.7 releases can be found in the [v1.7 branch](https://github.com/phoenixframework/phoenix/blob/v1.7/CHANGELOG.md).
diff --git a/guides/components.md b/guides/components.md
index 83e6710e8..5e98f9213 100644
--- a/guides/components.md
+++ b/guides/components.md
@@ -16,7 +16,7 @@ At the end of the Request life-cycle chapter, we created a template at `lib/hell
 
 ```heex
 <section>
-  <h2>Hello World, from <%= @messenger %>!</h2>
+  <h2>Hello World, from {@messenger}!</h2>
 </section>
 ```
 
@@ -34,7 +34,7 @@ That's simple enough. There's only two lines, `use HelloWeb, :html`. This line c
 
 All of the imports and aliases we make in our module will also be available in our templates. That's because templates are effectively compiled into functions inside their respective module. For example, if you define a function in your module, you will be able to invoke it directly from the template. Let's see this in practice.
 
-Imagine we want to refactor our `show.html.heex` to move the rendering of `<h2>Hello World, from <%= @messenger %>!</h2>` to its own function. We can move it to a function component inside `HelloHTML`, let's do so:
+Imagine we want to refactor our `show.html.heex` to move the rendering of `<h2>Hello World, from {@messenger}!</h2>` to its own function. We can move it to a function component inside `HelloHTML`, let's do so:
 
 ```elixir
 defmodule HelloWeb.HelloHTML do
@@ -46,7 +46,7 @@ defmodule HelloWeb.HelloHTML do
 
   def greet(assigns) do
     ~H"""
-    <h2>Hello World, from <%= @messenger %>!</h2>
+    <h2>Hello World, from {@messenger}!</h2>
     """
   end
 end
@@ -89,19 +89,21 @@ Next, let's fully understand the expressive power behind the HEEx template langu
 
 ## HEEx
 
-Function components and templates files are powered by [the HEEx template language](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#sigil_H/2), which stands for  "HTML+EEx". EEx is an Elixir library that uses `<%= expression %>` to execute Elixir expressions and interpolate their results into the template. This is frequently used to display assigns we have set by way of the `@` shortcut. In your controller, if you invoke:
+Function components and templates files are powered by [the HEEx template language](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#sigil_H/2), which stands for  "HTML+EEx". EEx is an Elixir library that uses `<%= expression %>` to execute Elixir expressions and interpolate their results into arbitrary text templates. HEEx extends EEx for writing HTML templates mixed with Elixir interpolation. We can write Elixir code inside `{...}` for HTML-aware interpolation inside tag attributes and the body. We can also interpolate arbitrary HEEx blocks using EEx interpolation (`<%= ... %>`). We use `@name` to access the key `name` defined inside `assigns`.
+
+This is frequently used to display assigns we have set by way of the `@` shortcut. In your controller, if you invoke:
 
 ```elixir
 render(conn, :show, username: "joe")
 ```
 
-Then you can access said username in the templates as `<%= @username %>`. In addition to displaying assigns and functions, we can use pretty much any Elixir expression. For example, in order to have conditionals:
+Then you can access said username in the templates as `{@username}`. In addition to displaying assigns and functions, we can use pretty much any Elixir expression. For example, in order to have conditionals:
 
 ```heex
 <%= if some_condition? do %>
-  <p>Some condition is true for user: <%= @username %></p>
+  <p>Some condition is true for user: {@username}</p>
 <% else %>
-  <p>Some condition is false for user: <%= @username %></p>
+  <p>Some condition is false for user: {@username}</p>
 <% end %>
 ```
 
@@ -115,8 +117,8 @@ or even loops:
   </tr>
   <%= for number <- 1..10 do %>
     <tr>
-      <td><%= number %></td>
-      <td><%= number * number %></td>
+      <td>{number}</td>
+      <td>{number * number}</td>
     </tr>
   <% end %>
 </table>
@@ -131,20 +133,20 @@ HEEx also comes with handy HTML extensions we will learn next.
 Besides allowing interpolation of Elixir expressions via `<%= %>`, `.heex` templates come with HTML-aware extensions. For example, let's see what happens if you try to interpolate a value with "<" or ">" in it, which would lead to HTML injection:
 
 ```heex
-<%= "<b>Bold?</b>" %>
+{"<b>Bold?</b>"}
 ```
 
 Once you render the template, you will see the literal `<b>` on the page. This means users cannot inject HTML content on the page. If you want to allow them to do so, you can call `raw`, but do so with extreme care:
 
 ```heex
-<%= raw "<b>Bold?</b>" %>
+{raw("<b>Bold?</b>")}
 ```
 
-Another super power of HEEx templates is validation of HTML and lean interpolation syntax of attributes. You can write:
+Another super power of HEEx templates is validation of HTML and interpolation syntax of attributes. You can write:
 
 ```heex
 <div title="My div" class={@class}>
-  <p>Hello <%= @username %></p>
+  <p>Hello {@username}</p>
 </div>
 ```
 
@@ -154,7 +156,7 @@ To interpolate a dynamic number of attributes in a keyword list or map, do:
 
 ```heex
 <div title="My div" {@many_attributes}>
-  <p>Hello <%= @username %></p>
+  <p>Hello {@username}</p>
 </div>
 ```
 
@@ -178,7 +180,7 @@ Likewise, for comprehensions may be written as:
 
 ```heex
 <ul>
-  <li :for={item <- @items}><%= item.name %></li>
+  <li :for={item <- @items}>{item.name}</li>
 </ul>
 ```
 
@@ -189,7 +191,7 @@ Layouts are just function components. They are defined in a module, just like al
 You may be wondering how the string resulting from a rendered view ends up inside a layout. That's a great question! If we look at `lib/hello_web/components/layouts/root.html.heex`, just about at the end of the `<body>`, we will see this.
 
 ```heex
-<%= @inner_content %>
+{@inner_content}
 ```
 
 In other words, after rendering your page, the result is placed in the `@inner_content` assign.
diff --git a/guides/contexts.md b/guides/contexts.md
index b266842f7..22fc256eb 100644
--- a/guides/contexts.md
+++ b/guides/contexts.md
@@ -525,10 +525,9 @@ We added a `category_select` above our save button. Now let's try it out. Next,
 <.list>
   ...
 + <:item title="Categories">
-+   <%= for cat <- @product.categories do %>
-+     <%= cat.title %>
-+     <br/>
-+   <% end %>
++   <ul>
++     <li :for={cat <- @product.categories}>{cat.title}</li>
++   </ul>
 + </:item>
 </.list>
 ```
@@ -937,34 +936,28 @@ We created a view to render our `show.html` template and aliased our `ShoppingCa
 Next we can create the template at `lib/hello_web/controllers/cart_html/show.html.heex`:
 
 ```heex
-<%= if @cart.items == [] do %>
-  <.header>
-    My Cart
-    <:subtitle>Your cart is empty</:subtitle>
-  </.header>
-<% else %>
-  <.header>
-    My Cart
-  </.header>
+<.header>
+  My Cart
+  <:subtitle :if={@cart.items == []}>Your cart is empty</:subtitle>
+</.header>
 
+<div :if={@cart.items !== []}>
   <.simple_form :let={f} for={@changeset} action={~p"/cart"}>
-    <.inputs_for :let={item_form} field={f[:items]}>
-	<% item = item_form.data %>
+    <.inputs_for :let={%{data: item} = item_form} field={f[:items]}>
       <.input field={item_form[:quantity]} type="number" label={item.product.title} />
-      <%= currency_to_str(ShoppingCart.total_item_price(item)) %>
+      {currency_to_str(ShoppingCart.total_item_price(item))}
     </.inputs_for>
     <:actions>
       <.button>Update cart</.button>
     </:actions>
   </.simple_form>
-
-  <b>Total</b>: <%= currency_to_str(ShoppingCart.total_cart_price(@cart)) %>
-<% end %>
+  <b>Total</b>: {currency_to_str(ShoppingCart.total_cart_price(@cart))}
+</div>
 
 <.back navigate={~p"/products"}>Back to products</.back>
 ```
 
-We started by showing the empty cart message if our preloaded `cart.items` is empty. If we have items, we use the `simple_form` component provided by our `HelloWeb.CoreComponents` to take our cart changeset that we assigned in the `CartController.show/2` action and create a form which maps to our cart controller `update/2` action. Within the form, we use the [`inputs_for`](`Phoenix.Component.inputs_for/1`) component to render inputs for the nested cart items. This will allow us to map item inputs back together when the form is submitted. Next, we display a number input for the item quantity and label it with the product title. We finish the item form by converting the item price to string. We haven't written the `ShoppingCart.total_item_price/1` function yet, but again we employed the idea of clear, descriptive public interfaces for our contexts. After rendering inputs for all the cart items, we show an "update cart" submit button, along with the total price of the entire cart. This is accomplished with another new `ShoppingCart.total_cart_price/1` function which we'll implement in a moment. Finally, we added a `back` component to go back to our products page.
+We started by showing the empty cart message if our preloaded `cart.items` is empty. If we have items, we use the `simple_form` component provided by our `HelloWeb.CoreComponents` to take our cart changeset that we assigned in the `CartController.show/2` action and create a form which maps to our cart controller `update/2` action. Within the form, we use the [`inputs_for`](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#inputs_for/1) component to render inputs for the nested cart items. This will allow us to map item inputs back together when the form is submitted. Next, we display a number input for the item quantity and label it with the product title. We finish the item form by converting the item price to string. We haven't written the `ShoppingCart.total_item_price/1` function yet, but again we employed the idea of clear, descriptive public interfaces for our contexts. After rendering inputs for all the cart items, we show an "update cart" submit button, along with the total price of the entire cart. This is accomplished with another new `ShoppingCart.total_cart_price/1` function which we'll implement in a moment. Finally, we added a `back` component to go back to our products page.
 
 We're almost ready to try out our cart page, but first we need to implement our new currency calculation functions. Open up your shopping cart context at `lib/hello/shopping_cart.ex` and add these new functions:
 
@@ -1034,7 +1027,7 @@ Head back over to your shopping cart context in `lib/hello/shopping_cart.ex` and
   end
 ```
 
-We started much like how our out-of-the-box code started – we take the cart struct and cast the user input to a cart changeset, except this time we use `Ecto.Changeset.cast_assoc/3` to cast the nested item data into `CartItem` changesets. Remember the [`<.inputs_for />`](`Phoenix.Component.inputs_for/1`) call in our cart form template? That hidden ID data is what allows Ecto's `cast_assoc` to map item data back to existing item associations in the cart. Next we use `Ecto.Multi.new/0`, which you may not have seen before. Ecto's `Multi` is a feature that allows lazily defining a chain of named operations to eventually execute inside a database transaction. Each operation in the multi chain receives the values from the previous steps and executes until a failed step is encountered. When an operation fails, the transaction is rolled back and an error is returned, otherwise the transaction is committed.
+We started much like how our out-of-the-box code started – we take the cart struct and cast the user input to a cart changeset, except this time we use `Ecto.Changeset.cast_assoc/3` to cast the nested item data into `CartItem` changesets. Remember the [`<.inputs_for />`](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#inputs_for/1) call in our cart form template? That hidden ID data is what allows Ecto's `cast_assoc` to map item data back to existing item associations in the cart. Next we use `Ecto.Multi.new/0`, which you may not have seen before. Ecto's `Multi` is a feature that allows lazily defining a chain of named operations to eventually execute inside a database transaction. Each operation in the multi chain receives the values from the previous steps and executes until a failed step is encountered. When an operation fails, the transaction is rolled back and an error is returned, otherwise the transaction is committed.
 
 For our multi operations, we start by issuing an update of our cart, which we named `:cart`. After the cart update is issued, we perform a multi `delete_all` operation, which takes the updated cart and applies our zero-quantity logic. We prune any items in the cart with zero quantity by returning an ecto query that finds all cart items for this cart with an empty quantity. Calling `Repo.transaction/1` with our multi will execute the operations in a new transaction and we return the success or failure result to the caller just like the original function.
 
@@ -1299,20 +1292,20 @@ Next we can create the template at `lib/hello_web/controllers/order_html/show.ht
 <.header>
   Thank you for your order!
   <:subtitle>
-     <strong>User uuid: </strong><%= @order.user_uuid %>
+     <strong>User uuid: </strong>{@order.user_uuid}
   </:subtitle>
 </.header>
 
 <.table id="items" rows={@order.line_items}>
-  <:col :let={item} label="Title"><%= item.product.title %></:col>
-  <:col :let={item} label="Quantity"><%= item.quantity %></:col>
+  <:col :let={item} label="Title">{item.product.title}</:col>
+  <:col :let={item} label="Quantity">{item.quantity}</:col>
   <:col :let={item} label="Price">
-    <%= HelloWeb.CartHTML.currency_to_str(item.price) %>
+    {HelloWeb.CartHTML.currency_to_str(item.price)}
   </:col>
 </.table>
 
 <strong>Total price:</strong>
-<%= HelloWeb.CartHTML.currency_to_str(@order.total_price) %>
+{HelloWeb.CartHTML.currency_to_str(@order.total_price)}
 
 <.back navigate={~p"/products"}>Back to products</.back>
 ```
@@ -1324,11 +1317,11 @@ Our last addition will be to add the "complete order" button to our cart page to
 ```diff
   <.header>
     My Cart
-+    <:actions>
-+      <.link href={~p"/orders"} method="post">
-+        <.button>Complete order</.button>
-+      </.link>
-+    </:actions>
++   <:actions>
++     <.link href={~p"/orders"} method="post">
++       <.button>Complete order</.button>
++     </.link>
++   </:actions>
   </.header>
 ```
 
diff --git a/guides/plug.md b/guides/plug.md
index 0c1d6a517..04e502a48 100644
--- a/guides/plug.md
+++ b/guides/plug.md
@@ -120,7 +120,7 @@ In the [`init/1`] callback, we pass a default locale to use if none is present i
 To see the assign in action, go to the template in `lib/hello_web/controllers/page_html/home.html.heex` and add the following code after the closing of the `</h1>` tag:
 
 ```heex
-<p>Locale: <%= @locale %></p>
+<p>Locale: {@locale}</p>
 ```
 
 Go to [http://localhost:4000/](http://localhost:4000/) and you should see the locale exhibited. Visit [http://localhost:4000/?locale=fr](http://localhost:4000/?locale=fr) and you should see the assign changed to `"fr"`. Someone can use this information alongside [Gettext](https://hexdocs.pm/gettext/Gettext.html) to provide a fully internationalized web application.
diff --git a/guides/real_time/presence.md b/guides/real_time/presence.md
index 106ea4177..32271b855 100644
--- a/guides/real_time/presence.md
+++ b/guides/real_time/presence.md
@@ -217,7 +217,7 @@ defmodule HelloWeb.OnlineLive do
   def render(assigns) do
     ~H"""
     <ul id="online_users" phx-update="stream">
-      <li :for={{dom_id, %{id: id, metas: metas}} <- @streams.presences} id={dom_id}><%= id %> (<%= length(metas) %>)</li>
+      <li :for={{dom_id, %{id: id, metas: metas}} <- @streams.presences} id={dom_id}>{id} ({length(metas)})</li>
     </ul>
     """
   end
diff --git a/guides/request_lifecycle.md b/guides/request_lifecycle.md
index 177b9376a..79ac1e964 100644
--- a/guides/request_lifecycle.md
+++ b/guides/request_lifecycle.md
@@ -181,7 +181,7 @@ Now that we've got the route, controller, view, and template, we should be able
 There are a couple of interesting things to notice about what we just did. We didn't need to stop and restart the server while we made these changes. Yes, Phoenix has hot code reloading! Also, even though our `index.html.heex` file consists of only a single `section` tag, the page we get is a full HTML document. Our index template is actually rendered into layouts: first it renders `lib/hello_web/components/layouts/root.html.heex` which renders `lib/hello_web/components/layouts/app.html.heex` which finally includes our content. If you open those files, you'll see a line that looks like this at the bottom:
 
 ```heex
-<%= @inner_content %>
+{@inner_content}
 ```
 
 This line injects our template into the layout before the HTML is sent off to the browser. We will talk more about layouts in the Controllers guide.
@@ -273,15 +273,17 @@ It's good to remember that the keys of the `params` map will always be strings,
 
 For the last piece of this puzzle, we'll need a new template. Since it is for the `show` action of `HelloController`, it will go into the `lib/hello_web/controllers/hello_html` directory and be called `show.html.heex`. It will look surprisingly like our `index.html.heex` template, except that we will need to display the name of our messenger.
 
-To do that, we'll use the special HEEx tags for executing Elixir expressions: `<%=  %>`. Notice that the initial tag has an equals sign like this: `<%=` . That means that any Elixir code that goes between those tags will be executed, and the resulting value will replace the tag in the HTML output. If the equals sign were missing, the code would still be executed, but the value would not appear on the page.
+To do that, we'll use the special HEEx tags for executing Elixir expressions: `{...}` and `<%= %>`. Notice that EEx tag has an equals sign like this: `<%=` . That means that any Elixir code that goes between those tags will be executed, and the resulting value will replace the tag in the HTML output. If the equals sign were missing, the code would still be executed, but the value would not appear on the page.
 
-Remember our templates are written in HEEx (HTML+EEx). HEEx is a superset of EEx which is why it shares the `<%= %>` syntax.
+Remember our templates are written in HEEx (HTML+EEx). HEEx is a superset of EEx, and thereby supports the EEx `<%= %>` interpolation syntax for interpolating arbitrary blocks of code. In general, the HEEx `{...}` interpolation syntax is preferred anytime there is HTML-aware intepolation to be done – such as within attributes or inline values with a body.
 
-And this is what the template should look like:
+The only times `EEx` `<%= %>` interpolation is necessary is for interpolationg arbitrary blocks of markup, such as branching logic that inects separate markup trees, or for interpolating values within `<script>` or `<style>` tags.
+
+This is what the `hello_html/show.html.heex` template should look like:
 
 ```heex
 <section>
-  <h2>Hello World, from <%= @messenger %>!</h2>
+  <h2>Hello World, from {@messenger}!</h2>
 </section>
 ```
 
diff --git a/installer/lib/phx_new/generator.ex b/installer/lib/phx_new/generator.ex
index b0c0a9f0d..18a8cd94e 100644
--- a/installer/lib/phx_new/generator.ex
+++ b/installer/lib/phx_new/generator.ex
@@ -188,7 +188,8 @@ defmodule Phx.New.Generator do
     {adapter_app, adapter_module, adapter_config} =
       get_ecto_adapter(db, String.downcase(project.app), project.app_mod)
 
-    {web_adapter_app, web_adapter_vsn, web_adapter_module, web_adapter_docs} = get_web_adapter(web_adapter)
+    {web_adapter_app, web_adapter_vsn, web_adapter_module, web_adapter_docs} =
+      get_web_adapter(web_adapter)
 
     pubsub_server = get_pubsub_server(project.app_mod)
 
@@ -304,8 +305,16 @@ defmodule Phx.New.Generator do
     Mix.raise("Unknown database #{inspect(db)}")
   end
 
-  defp get_web_adapter("cowboy"), do: {:plug_cowboy, "~> 2.7", Phoenix.Endpoint.Cowboy2Adapter, "https://hexdocs.pm/plug_cowboy/Plug.Cowboy.html"}
-  defp get_web_adapter("bandit"), do: {:bandit, "~> 1.5", Bandit.PhoenixAdapter, "https://hexdocs.pm/bandit/Bandit.html#t:options/0"}
+  defp get_web_adapter("cowboy"),
+    do:
+      {:plug_cowboy, "~> 2.7", Phoenix.Endpoint.Cowboy2Adapter,
+       "https://hexdocs.pm/plug_cowboy/Plug.Cowboy.html"}
+
+  defp get_web_adapter("bandit"),
+    do:
+      {:bandit, "~> 1.5", Bandit.PhoenixAdapter,
+       "https://hexdocs.pm/bandit/Bandit.html#t:options/0"}
+
   defp get_web_adapter(other), do: Mix.raise("Unknown web adapter #{inspect(other)}")
 
   defp fs_db_config(app, module) do
@@ -380,6 +389,8 @@ defmodule Phx.New.Generator do
       # ssl: true,
       url: database_url,
       pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
+      # For machines with several cores, consider starting multiple pools of `pool_size`
+      # pool_count: 4,
       socket_options: maybe_ipv6
       """
     ]
@@ -465,13 +476,13 @@ defmodule Phx.New.Generator do
   # ## Examples
   #
   #     iex> ~s|<tag>#{maybe_eex_gettext("Hello", true)}</tag>|
-  #     ~S|<tag><%= gettext("Hello") %></tag>|
+  #     ~S|<tag>{gettext("Hello")}</tag>|
   #
   #     iex> ~s|<tag>#{maybe_eex_gettext("Hello", false)}</tag>|
   #     ~S|<tag>Hello</tag>|
   def maybe_eex_gettext(message, gettext?) do
     if gettext? do
-      ~s|<%= gettext(#{inspect(message)}) %>|
+      ~s|{gettext(#{inspect(message)})}|
     else
       message
     end
diff --git a/installer/mix.exs b/installer/mix.exs
index 518f3a243..7ea60b14c 100644
--- a/installer/mix.exs
+++ b/installer/mix.exs
@@ -6,7 +6,7 @@ end
 defmodule Phx.New.MixProject do
   use Mix.Project
 
-  @version "1.7.14"
+  @version "1.8.0-dev"
   @scm_url "https://github.com/phoenixframework/phoenix"
 
   # If the elixir requirement is updated, we need to update:
diff --git a/installer/templates/phx_single/mix.exs b/installer/templates/phx_single/mix.exs
index ed631a252..0e990e8d0 100644
--- a/installer/templates/phx_single/mix.exs
+++ b/installer/templates/phx_single/mix.exs
@@ -43,8 +43,7 @@ defmodule <%= @app_module %>.MixProject do
       {<%= inspect @adapter_app %>, ">= 0.0.0"},<% end %><%= if @html do %>
       {:phoenix_html, "~> 4.1"},
       {:phoenix_live_reload, "~> 1.2", only: :dev},
-      # TODO bump on release to {:phoenix_live_view, "~> 1.0.0"},
-      {:phoenix_live_view, "~> 1.0.0-rc.1", override: true},
+      {:phoenix_live_view, "~> 1.0.0"},
       {:floki, ">= 0.30.0", only: :test},<% end %><%= if @dashboard do %>
       {:phoenix_live_dashboard, "~> 0.8.3"},<% end %><%= if @javascript do %>
       {:esbuild, "~> 0.8", runtime: Mix.env() == :dev},<% end %><%= if @css do %>
diff --git a/installer/templates/phx_umbrella/apps/app_name_web/mix.exs b/installer/templates/phx_umbrella/apps/app_name_web/mix.exs
index f0bd3d0cd..d2ce376fc 100644
--- a/installer/templates/phx_umbrella/apps/app_name_web/mix.exs
+++ b/installer/templates/phx_umbrella/apps/app_name_web/mix.exs
@@ -41,8 +41,7 @@ defmodule <%= @web_namespace %>.MixProject do
       {:phoenix_ecto, "~> 4.5"},<% end %><%= if @html do %>
       {:phoenix_html, "~> 4.1"},
       {:phoenix_live_reload, "~> 1.2", only: :dev},
-      # TODO bump on release to {:phoenix_live_view, "~> 1.0.0"},
-      {:phoenix_live_view, "~> 1.0.0-rc.1", override: true},
+      {:phoenix_live_view, "~> 1.0.0"},
       {:floki, ">= 0.30.0", only: :test},<% end %><%= if @dashboard do %>
       {:phoenix_live_dashboard, "~> 0.8.3"},<% end %><%= if @javascript do %>
       {:esbuild, "~> 0.8", runtime: Mix.env() == :dev},<% end %><%= if @css do %>
diff --git a/installer/templates/phx_umbrella/mix.exs b/installer/templates/phx_umbrella/mix.exs
index 7d48e0836..e02ac6262 100644
--- a/installer/templates/phx_umbrella/mix.exs
+++ b/installer/templates/phx_umbrella/mix.exs
@@ -27,8 +27,7 @@ defmodule <%= @root_app_module %>.MixProject do
     [
       <%= if @dev or @phoenix_version.pre != [] do %><%= @phoenix_dep_umbrella_root %>,
       <% end %># Required to run "mix format" on ~H/.heex files from the umbrella root
-      # TODO bump on release to {:phoenix_live_view, ">= 0.0.0"},
-      {:phoenix_live_view, "~> 1.0.0-rc.1", override: true}
+      {:phoenix_live_view, ">= 0.0.0"}
     ]<% else %>
     []<% end %>
   end
diff --git a/installer/templates/phx_web/components/core_components.ex b/installer/templates/phx_web/components/core_components.ex
index c604ef553..aaf89f484 100644
--- a/installer/templates/phx_web/components/core_components.ex
+++ b/installer/templates/phx_web/components/core_components.ex
@@ -54,9 +54,9 @@ defmodule <%= @web_namespace %>.CoreComponents do
       <p :if={@title} class="flex items-center gap-1.5 text-sm font-semibold leading-6">
         <.icon :if={@kind == :info} name="hero-information-circle-mini" class="h-4 w-4" />
         <.icon :if={@kind == :error} name="hero-exclamation-circle-mini" class="h-4 w-4" />
-        <%%= @title %>
+        {@title}
       </p>
-      <p class="mt-2 text-sm leading-5"><%%= msg %></p>
+      <p class="mt-2 text-sm leading-5">{msg}</p>
       <button type="button" class="group absolute top-1 right-1 p-2" aria-label=<%= maybe_heex_attr_gettext.("close", @gettext) %>>
         <.icon name="hero-x-mark-solid" class="h-5 w-5 opacity-40 group-hover:opacity-70" />
       </button>
@@ -135,9 +135,9 @@ defmodule <%= @web_namespace %>.CoreComponents do
     ~H"""
     <.form :let={f} for={@for} {@as} {@rest}>
       <div class="mt-10 space-y-8 bg-white">
-        <%%= render_slot(@inner_block, f) %>
+        {render_slot(@inner_block, f)}
         <div :for={action <- @actions} class="mt-2 flex items-center justify-between gap-6">
-          <%%= render_slot(action, f) %>
+          {render_slot(action, f)}
         </div>
       </div>
     </.form>
@@ -169,7 +169,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
       ]}
       {@rest}
     >
-      <%%= render_slot(@inner_block) %>
+      {render_slot(@inner_block)}
     </button>
     """
   end
@@ -253,9 +253,9 @@ defmodule <%= @web_namespace %>.CoreComponents do
           class="rounded border-zinc-300 text-zinc-900 focus:ring-0"
           {@rest}
         />
-        <%%= @label %>
+        {@label}
       </label>
-      <.error :for={msg <- @errors}><%%= msg %></.error>
+      <.error :for={msg <- @errors}>{msg}</.error>
     </div>
     """
   end
@@ -263,7 +263,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
   def input(%{type: "select"} = assigns) do
     ~H"""
     <div>
-      <.label for={@id}><%%= @label %></.label>
+      <.label for={@id}>{@label}</.label>
       <select
         id={@id}
         name={@name}
@@ -271,10 +271,10 @@ defmodule <%= @web_namespace %>.CoreComponents do
         multiple={@multiple}
         {@rest}
       >
-        <option :if={@prompt} value=""><%%= @prompt %></option>
-        <%%= Phoenix.HTML.Form.options_for_select(@options, @value) %>
+        <option :if={@prompt} value="">{@prompt}</option>
+        {Phoenix.HTML.Form.options_for_select(@options, @value)}
       </select>
-      <.error :for={msg <- @errors}><%%= msg %></.error>
+      <.error :for={msg <- @errors}>{msg}</.error>
     </div>
     """
   end
@@ -282,7 +282,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
   def input(%{type: "textarea"} = assigns) do
     ~H"""
     <div>
-      <.label for={@id}><%%= @label %></.label>
+      <.label for={@id}>{@label}</.label>
       <textarea
         id={@id}
         name={@name}
@@ -292,8 +292,8 @@ defmodule <%= @web_namespace %>.CoreComponents do
           @errors != [] && "border-rose-400 focus:border-rose-400"
         ]}
         {@rest}
-      ><%%= Phoenix.HTML.Form.normalize_value("textarea", @value) %></textarea>
-      <.error :for={msg <- @errors}><%%= msg %></.error>
+      >{Phoenix.HTML.Form.normalize_value("textarea", @value)}</textarea>
+      <.error :for={msg <- @errors}>{msg}</.error>
     </div>
     """
   end
@@ -302,7 +302,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
   def input(assigns) do
     ~H"""
     <div>
-      <.label for={@id}><%%= @label %></.label>
+      <.label for={@id}>{@label}</.label>
       <input
         type={@type}
         name={@name}
@@ -315,7 +315,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
         ]}
         {@rest}
       />
-      <.error :for={msg <- @errors}><%%= msg %></.error>
+      <.error :for={msg <- @errors}>{msg}</.error>
     </div>
     """
   end
@@ -329,7 +329,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
   def label(assigns) do
     ~H"""
     <label for={@for} class="block text-sm font-semibold leading-6 text-zinc-800">
-      <%%= render_slot(@inner_block) %>
+      {render_slot(@inner_block)}
     </label>
     """
   end
@@ -343,7 +343,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
     ~H"""
     <p class="mt-1.5 flex gap-1.5 text-sm leading-6 text-rose-600">
       <.icon name="hero-exclamation-circle-mini" class="mt-0.5 h-5 w-5 flex-none" />
-      <%%= render_slot(@inner_block) %>
+      {render_slot(@inner_block)}
     </p>
     """
   end
@@ -362,13 +362,13 @@ defmodule <%= @web_namespace %>.CoreComponents do
     <header class={[@actions != [] && "flex items-center justify-between gap-6", @class]}>
       <div>
         <h1 class="text-lg font-semibold leading-8 text-zinc-800">
-          <%%= render_slot(@inner_block) %>
+          {render_slot(@inner_block)}
         </h1>
         <p :if={@subtitle != []} class="mt-2 text-sm leading-6 text-zinc-600">
-          <%%= render_slot(@subtitle) %>
+          {render_slot(@subtitle)}
         </p>
       </div>
-      <div class="flex-none"><%%= render_slot(@actions) %></div>
+      <div class="flex-none">{render_slot(@actions)}</div>
     </header>
     """
   end
@@ -379,8 +379,8 @@ defmodule <%= @web_namespace %>.CoreComponents do
   ## Examples
 
       <.table id="users" rows={@users}>
-        <:col :let={user} label="id"><%%= user.id %></:col>
-        <:col :let={user} label="username"><%%= user.username %></:col>
+        <:col :let={user} label="id">{user.id}</:col>
+        <:col :let={user} label="username">{user.username}</:col>
       </.table>
   """
   attr :id, :string, required: true
@@ -409,7 +409,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
       <table class="w-[40rem] mt-11 sm:w-full">
         <thead class="text-sm text-left leading-6 text-zinc-500">
           <tr>
-            <th :for={col <- @col} class="p-0 pb-4 pr-6 font-normal"><%%= col[:label] %></th>
+            <th :for={col <- @col} class="p-0 pb-4 pr-6 font-normal">{col[:label]}</th>
             <th :if={@action != []} class="relative p-0 pb-4">
               <span class="sr-only"><%= maybe_eex_gettext.("Actions", @gettext) %></span>
             </th>
@@ -429,7 +429,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
               <div class="block py-4 pr-6">
                 <span class="absolute -inset-y-px right-0 -left-4 group-hover:bg-zinc-50 sm:rounded-l-xl" />
                 <span class={["relative", i == 0 && "font-semibold text-zinc-900"]}>
-                  <%%= render_slot(col, @row_item.(row)) %>
+                  {render_slot(col, @row_item.(row))}
                 </span>
               </div>
             </td>
@@ -440,7 +440,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
                   :for={action <- @action}
                   class="relative ml-4 font-semibold leading-6 text-zinc-900 hover:text-zinc-700"
                 >
-                  <%%= render_slot(action, @row_item.(row)) %>
+                  {render_slot(action, @row_item.(row))}
                 </span>
               </div>
             </td>
@@ -457,8 +457,8 @@ defmodule <%= @web_namespace %>.CoreComponents do
   ## Examples
 
       <.list>
-        <:item title="Title"><%%= @post.title %></:item>
-        <:item title="Views"><%%= @post.views %></:item>
+        <:item title="Title">{@post.title}</:item>
+        <:item title="Views">{@post.views}</:item>
       </.list>
   """
   slot :item, required: true do
@@ -470,8 +470,8 @@ defmodule <%= @web_namespace %>.CoreComponents do
     <div class="mt-14">
       <dl class="-my-4 divide-y divide-zinc-100">
         <div :for={item <- @item} class="flex gap-4 py-4 text-sm leading-6 sm:gap-8">
-          <dt class="w-1/4 flex-none text-zinc-500"><%%= item.title %></dt>
-          <dd class="text-zinc-700"><%%= render_slot(item) %></dd>
+          <dt class="w-1/4 flex-none text-zinc-500">{item.title}</dt>
+          <dd class="text-zinc-700">{render_slot(item)}</dd>
         </div>
       </dl>
     </div>
@@ -496,7 +496,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
         class="text-sm font-semibold leading-6 text-zinc-900 hover:text-zinc-700"
       >
         <.icon name="hero-arrow-left-solid" class="h-3 w-3" />
-        <%%= render_slot(@inner_block) %>
+        {render_slot(@inner_block)}
       </.link>
     </div>
     """
diff --git a/installer/templates/phx_web/components/layouts/app.html.heex b/installer/templates/phx_web/components/layouts/app.html.heex
index d16409073..d754c69b4 100644
--- a/installer/templates/phx_web/components/layouts/app.html.heex
+++ b/installer/templates/phx_web/components/layouts/app.html.heex
@@ -5,7 +5,7 @@
         <img src={~p"/images/logo.svg"} width="36" />
       </a>
       <p class="bg-brand/5 text-brand rounded-full px-2 font-medium leading-6">
-        v<%%= Application.spec(:phoenix, :vsn) %>
+        v{Application.spec(:phoenix, :vsn)}
       </p>
     </div>
     <div class="flex items-center gap-4 font-semibold leading-6 text-zinc-900">
@@ -26,7 +26,7 @@
 </header>
 <main class="px-4 py-20 sm:px-6 lg:px-8">
   <div class="mx-auto max-w-2xl">
-    <%%= @inner_content %>
+    {@inner_content}
   </div>
 </main>
 <.flash_group flash={@flash} />
diff --git a/installer/templates/phx_web/components/layouts/root.html.heex b/installer/templates/phx_web/components/layouts/root.html.heex
index fdbd4aa4e..8d6e5b985 100644
--- a/installer/templates/phx_web/components/layouts/root.html.heex
+++ b/installer/templates/phx_web/components/layouts/root.html.heex
@@ -5,13 +5,13 @@
     <meta name="viewport" content="width=device-width, initial-scale=1" />
     <meta name="csrf-token" content={get_csrf_token()} />
     <.live_title default="<%= @app_module %>" suffix=" · Phoenix Framework">
-      <%%= assigns[:page_title] %>
+      {assigns[:page_title]}
     </.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">
-    <%%= @inner_content %>
+    {@inner_content}
   </body>
 </html>
diff --git a/installer/templates/phx_web/controllers/page_html/home.html.heex b/installer/templates/phx_web/controllers/page_html/home.html.heex
index 071a7104d..cd96076f0 100644
--- a/installer/templates/phx_web/controllers/page_html/home.html.heex
+++ b/installer/templates/phx_web/controllers/page_html/home.html.heex
@@ -50,7 +50,7 @@
     <h1 class="text-brand mt-10 flex items-center text-sm font-semibold leading-6">
       Phoenix Framework
       <small class="bg-brand/5 text-[0.8125rem] ml-3 rounded-full px-2 font-medium leading-6">
-        v<%%= Application.spec(:phoenix, :vsn) %>
+        v{Application.spec(:phoenix, :vsn)}
       </small>
     </h1>
     <p class="text-[2rem] mt-4 font-semibold leading-10 tracking-tighter text-zinc-900 text-balance">
diff --git a/lib/mix/phoenix.ex b/lib/mix/phoenix.ex
index 7c6b8e6d5..78181df0b 100644
--- a/lib/mix/phoenix.ex
+++ b/lib/mix/phoenix.ex
@@ -43,8 +43,12 @@ defmodule Mix.Phoenix do
         end) || raise "could not find #{source_file_path} in any of the sources"
 
       case format do
-        :text -> Mix.Generator.create_file(target, File.read!(source))
-        :eex  -> Mix.Generator.create_file(target, EEx.eval_file(source, binding))
+        :text ->
+          Mix.Generator.create_file(target, File.read!(source))
+
+        :eex ->
+          Mix.Generator.create_file(target, EEx.eval_file(source, binding))
+
         :new_eex ->
           if File.exists?(target) do
             :ok
@@ -57,6 +61,7 @@ defmodule Mix.Phoenix do
 
   defp to_app_source(path, source_dir) when is_binary(path),
     do: Path.join(path, source_dir)
+
   defp to_app_source(app, source_dir) when is_atom(app),
     do: Application.app_dir(app, source_dir)
 
@@ -97,23 +102,25 @@ defmodule Mix.Phoenix do
 
   """
   def inflect(singular) do
-    base       = Mix.Phoenix.base()
+    base = Mix.Phoenix.base()
     web_module = base |> web_module() |> inspect()
-    scoped     = Phoenix.Naming.camelize(singular)
-    path       = Phoenix.Naming.underscore(scoped)
-    singular   = String.split(path, "/") |> List.last
-    module     = Module.concat(base, scoped) |> inspect
-    alias      = String.split(module, ".") |> List.last
-    human      = Phoenix.Naming.humanize(singular)
-
-    [alias: alias,
-     human: human,
-     base: base,
-     web_module: web_module,
-     module: module,
-     scoped: scoped,
-     singular: singular,
-     path: path]
+    scoped = Phoenix.Naming.camelize(singular)
+    path = Phoenix.Naming.underscore(scoped)
+    singular = String.split(path, "/") |> List.last()
+    module = Module.concat(base, scoped) |> inspect
+    alias = String.split(module, ".") |> List.last()
+    human = Phoenix.Naming.humanize(singular)
+
+    [
+      alias: alias,
+      human: human,
+      base: base,
+      web_module: web_module,
+      module: module,
+      scoped: scoped,
+      singular: singular,
+      path: path
+    ]
   end
 
   @doc """
@@ -121,8 +128,9 @@ defmodule Mix.Phoenix do
   """
   def check_module_name_availability!(name) do
     name = Module.concat(Elixir, name)
+
     if Code.ensure_loaded?(name) do
-      Mix.raise "Module name #{inspect name} is already taken, please choose another name"
+      Mix.raise("Module name #{inspect(name)} is already taken, please choose another name")
     end
   end
 
@@ -151,7 +159,7 @@ defmodule Mix.Phoenix do
   defp app_base(app) do
     case Application.get_env(app, :namespace, app) do
       ^app -> app |> to_string() |> Phoenix.Naming.camelize()
-      mod  -> mod |> inspect()
+      mod -> mod |> inspect()
     end
   end
 
@@ -190,7 +198,7 @@ defmodule Mix.Phoenix do
   Checks if the given `app_path` is inside an umbrella.
   """
   def in_umbrella?(app_path) do
-    umbrella = Path.expand(Path.join [app_path, "..", ".."])
+    umbrella = Path.expand(Path.join([app_path, "..", ".."]))
     mix_path = Path.join(umbrella, "mix.exs")
     apps_path = Path.join(umbrella, "apps")
     File.exists?(mix_path) && File.exists?(apps_path)
@@ -223,6 +231,7 @@ defmodule Mix.Phoenix do
           {^ctx_app, path} -> Path.relative_to_cwd(path)
           _ -> mix_app_path(ctx_app, this_app)
         end
+
       Path.join(app_path, rel_path)
     end
   end
@@ -270,8 +279,9 @@ defmodule Mix.Phoenix do
     case Application.get_env(this_otp_app, :generators)[:context_app] do
       nil ->
         :error
+
       false ->
-        Mix.raise """
+        Mix.raise("""
         no context_app configured for current application #{this_otp_app}.
 
         Add the context_app generators config in config.exs, or pass the
@@ -288,9 +298,11 @@ defmodule Mix.Phoenix do
 
         Note: cli option only works when `context_app` is not set to `false`
         in the config.
-        """
+        """)
+
       {app, _path} ->
         {:ok, app}
+
       app ->
         {:ok, app}
     end
@@ -300,11 +312,12 @@ defmodule Mix.Phoenix do
     case Mix.Project.deps_paths() do
       %{^app => path} ->
         Path.relative_to_cwd(path)
+
       deps ->
-        Mix.raise """
-        no directory for context_app #{inspect app} found in #{this_otp_app}'s deps.
+        Mix.raise("""
+        no directory for context_app #{inspect(app)} found in #{this_otp_app}'s deps.
 
-        Ensure you have listed #{inspect app} as an in_umbrella dependency in mix.exs:
+        Ensure you have listed #{inspect(app)} as an in_umbrella dependency in mix.exs:
 
             def deps do
               [
@@ -315,9 +328,9 @@ defmodule Mix.Phoenix do
 
         Existing deps:
 
-            #{inspect Map.keys(deps)}
+            #{inspect(Map.keys(deps))}
 
-        """
+        """)
     end
   end
 
@@ -332,15 +345,18 @@ defmodule Mix.Phoenix do
       end)
 
     case Enum.filter(file_paths, &File.exists?(&1)) do
-      [] -> :ok
+      [] ->
+        :ok
+
       conflicts ->
-        Mix.shell().info"""
+        Mix.shell().info("""
         The following files conflict with new files to be generated:
 
         #{Enum.map_join(conflicts, "\n", &"  * #{&1}")}
 
         See the --web option to namespace similarly named resources
-        """
+        """)
+
         unless Mix.shell().yes?("Proceed with interactive overwrite?") do
           System.halt()
         end
@@ -359,13 +375,25 @@ defmodule Mix.Phoenix do
   end
 
   def to_text(data) do
-    inspect data, limit: :infinity, printable_limit: :infinity
+    inspect(data, limit: :infinity, printable_limit: :infinity)
   end
 
   def prepend_newline(string) do
     "\n" <> string
   end
 
+  @doc """
+  Ensures user's LiveView is compatible with the current generators.
+  """
+  def ensure_live_view_compat!(generator_mod) do
+    vsn = Application.spec(:phoenix_live_view)[:vsn]
+
+    # if lv is not installed, such as in phoenix's own test env, do not raise
+    if vsn && Version.compare("#{vsn}", "1.0.0-rc.7") != :gt do
+      raise "#{inspect(generator_mod)} requires :phoenix_live_view >= 1.0.0, got: #{vsn}"
+    end
+  end
+
   # In the context of a HEEx attribute value, transforms a given message into a
   # dynamic `gettext` call or a fixed-value string attribute, depending on the
   # `gettext?` parameter.
diff --git a/lib/mix/phoenix/context.ex b/lib/mix/phoenix/context.ex
index 27fbc6562..b4134de33 100644
--- a/lib/mix/phoenix/context.ex
+++ b/lib/mix/phoenix/context.ex
@@ -27,15 +27,15 @@ defmodule Mix.Phoenix.Context do
   end
 
   def new(context_name, %Schema{} = schema, opts) do
-    ctx_app   = opts[:context_app] || Mix.Phoenix.context_app()
-    base      = Module.concat([Mix.Phoenix.context_base(ctx_app)])
-    module    = Module.concat(base, context_name)
-    alias     = Module.concat([module |> Module.split() |> List.last()])
-    basedir   = Phoenix.Naming.underscore(context_name)
-    basename  = Path.basename(basedir)
-    dir       = Mix.Phoenix.context_lib_path(ctx_app, basedir)
-    file      = dir <> ".ex"
-    test_dir  = Mix.Phoenix.context_test_path(ctx_app, basedir)
+    ctx_app = opts[:context_app] || Mix.Phoenix.context_app()
+    base = Module.concat([Mix.Phoenix.context_base(ctx_app)])
+    module = Module.concat(base, context_name)
+    alias = Module.concat([module |> Module.split() |> List.last()])
+    basedir = Phoenix.Naming.underscore(context_name)
+    basename = Path.basename(basedir)
+    dir = Mix.Phoenix.context_lib_path(ctx_app, basedir)
+    file = dir <> ".ex"
+    test_dir = Mix.Phoenix.context_test_path(ctx_app, basedir)
     test_file = test_dir <> "_test.exs"
     test_fixtures_dir = Mix.Phoenix.context_app_path(ctx_app, "test/support/fixtures")
     test_fixtures_file = Path.join([test_fixtures_dir, basedir <> "_fixtures.ex"])
diff --git a/lib/mix/tasks/phx.gen.auth.ex b/lib/mix/tasks/phx.gen.auth.ex
index 04cb5d234..5dcec16f6 100644
--- a/lib/mix/tasks/phx.gen.auth.ex
+++ b/lib/mix/tasks/phx.gen.auth.ex
@@ -126,6 +126,8 @@ defmodule Mix.Tasks.Phx.Gen.Auth do
       Mix.raise("mix phx.gen.auth can only be run inside an application directory")
     end
 
+    Mix.Phoenix.ensure_live_view_compat!(__MODULE__)
+
     {opts, parsed} = OptionParser.parse!(args, strict: @switches)
     validate_args!(parsed)
     hashing_library = build_hashing_library!(opts)
diff --git a/lib/mix/tasks/phx.gen.auth/injector.ex b/lib/mix/tasks/phx.gen.auth/injector.ex
index 48ae16782..cc891bc70 100644
--- a/lib/mix/tasks/phx.gen.auth/injector.ex
+++ b/lib/mix/tasks/phx.gen.auth/injector.ex
@@ -170,7 +170,7 @@ defmodule Mix.Tasks.Phx.Gen.Auth.Injector do
     <ul class="relative z-10 flex items-center gap-4 px-4 sm:px-6 lg:px-8 justify-end">
       <%= if @current_#{schema.singular} do %>
         <li class="#{base_tailwind_classes}">
-          <%= @current_#{schema.singular}.email %>
+          {@current_#{schema.singular}.email}
         </li>
         <li>
           <.link
diff --git a/lib/mix/tasks/phx.gen.html.ex b/lib/mix/tasks/phx.gen.html.ex
index e3f75b2c6..e9222dacc 100644
--- a/lib/mix/tasks/phx.gen.html.ex
+++ b/lib/mix/tasks/phx.gen.html.ex
@@ -102,6 +102,8 @@ defmodule Mix.Tasks.Phx.Gen.Html do
       )
     end
 
+    Mix.Phoenix.ensure_live_view_compat!(__MODULE__)
+
     {context, schema} = Gen.Context.build(args)
     Gen.Context.prompt_for_code_injection(context)
 
diff --git a/lib/mix/tasks/phx.gen.live.ex b/lib/mix/tasks/phx.gen.live.ex
index e0d10ba91..3aa01cdd0 100644
--- a/lib/mix/tasks/phx.gen.live.ex
+++ b/lib/mix/tasks/phx.gen.live.ex
@@ -113,6 +113,8 @@ defmodule Mix.Tasks.Phx.Gen.Live do
       )
     end
 
+    Mix.Phoenix.ensure_live_view_compat!(__MODULE__)
+
     {context, schema} = Gen.Context.build(args)
     Gen.Context.prompt_for_code_injection(context)
 
diff --git a/lib/phoenix/endpoint.ex b/lib/phoenix/endpoint.ex
index a923be9a8..5396a79ea 100644
--- a/lib/phoenix/endpoint.ex
+++ b/lib/phoenix/endpoint.ex
@@ -74,7 +74,7 @@ defmodule Phoenix.Endpoint do
       instances of the same app at the same time with code reloading in
       development, as they will race each other and only one will effectively
       recompile the files. In such cases, tweak your config files so code
-      reloading is enabled in only one of the apps or set the MIX_BUILD
+      reloading is enabled in only one of the apps or set the `MIX_BUILD_PATH`
       environment variable to give them distinct build directories
 
     * `:debug_errors` - when `true`, uses `Plug.Debugger` functionality for
diff --git a/mix.exs b/mix.exs
index 4f47ffa67..dc35d971a 100644
--- a/mix.exs
+++ b/mix.exs
@@ -8,7 +8,7 @@ defmodule Phoenix.MixProject do
     end
   end
 
-  @version "1.7.14"
+  @version "1.8.0-dev"
   @scm_url "https://github.com/phoenixframework/phoenix"
 
   # If the elixir requirement is updated, we need to make the installer
@@ -23,7 +23,6 @@ defmodule Phoenix.MixProject do
       elixir: @elixir_requirement,
       deps: deps(),
       package: package(),
-      preferred_cli_env: [docs: :docs],
       consolidate_protocols: Mix.env() != :test,
       xref: [
         exclude: [
@@ -47,6 +46,12 @@ defmodule Phoenix.MixProject do
     ]
   end
 
+  def cli do
+    [
+      preferred_envs: [docs: :docs]
+    ]
+  end
+
   defp elixirc_paths(:docs), do: ["lib", "installer/lib"]
   defp elixirc_paths(_), do: ["lib"]
 
@@ -124,12 +129,12 @@ defmodule Phoenix.MixProject do
       main: "overview",
       logo: "logo.png",
       extra_section: "GUIDES",
-      assets: "guides/assets",
+      assets: %{"guides/assets" => "assets"},
       formatters: ["html", "epub"],
       groups_for_modules: groups_for_modules(),
       extras: extras(),
       groups_for_extras: groups_for_extras(),
-      groups_for_functions: [
+      groups_for_docs: [
         Reflection: &(&1[:type] == :reflection)
       ],
       skip_undefined_reference_warnings_on: ["CHANGELOG.md"]
diff --git a/priv/templates/phx.gen.auth/schema.ex b/priv/templates/phx.gen.auth/schema.ex
index 13ff8f1db..b289b3e0b 100644
--- a/priv/templates/phx.gen.auth/schema.ex
+++ b/priv/templates/phx.gen.auth/schema.ex
@@ -46,7 +46,9 @@ defmodule <%= inspect schema.module %> do
   defp validate_email(changeset, opts) do
     changeset
     |> validate_required([:email])
-    |> validate_format(:email, ~r/^[^\s]+@[^\s]+$/, message: "must have the @ sign and no spaces")
+    |> validate_format(:email, ~r/^[^@,;\s]+@[^@,;\s]+$/,
+      message: "must have the @ sign and no spaces"
+    )
     |> validate_length(:email, max: 160)
     |> maybe_validate_unique_email(opts)
   end
diff --git a/priv/templates/phx.gen.auth/session_new.html.heex b/priv/templates/phx.gen.auth/session_new.html.heex
index 1e7abc4fc..8e19c7401 100644
--- a/priv/templates/phx.gen.auth/session_new.html.heex
+++ b/priv/templates/phx.gen.auth/session_new.html.heex
@@ -11,7 +11,7 @@
   </.header>
 
   <.simple_form :let={f} for={@conn.params["<%= schema.singular %>"]} as={:<%= schema.singular %>} action={~p"<%= schema.route_prefix %>/log-in"}>
-    <.error :if={@error_message}><%%= @error_message %></.error>
+    <.error :if={@error_message}>{@error_message}</.error>
 
     <.input field={f[:email]} type="email" label="Email" autocomplete="username" required />
     <.input
diff --git a/priv/templates/phx.gen.html/edit.html.heex b/priv/templates/phx.gen.html/edit.html.heex
index c9eaf288b..a896b5d79 100644
--- a/priv/templates/phx.gen.html/edit.html.heex
+++ b/priv/templates/phx.gen.html/edit.html.heex
@@ -1,5 +1,5 @@
 <.header>
-  Edit <%= schema.human_singular %> <%%= @<%= schema.singular %>.id %>
+  Edit <%= schema.human_singular %> {@<%= schema.singular %>.id}
   <:subtitle>Use this form to manage <%= schema.singular %> records in your database.</:subtitle>
 </.header>
 
diff --git a/priv/templates/phx.gen.html/index.html.heex b/priv/templates/phx.gen.html/index.html.heex
index c1f89108a..feec52ee5 100644
--- a/priv/templates/phx.gen.html/index.html.heex
+++ b/priv/templates/phx.gen.html/index.html.heex
@@ -10,7 +10,7 @@
 </.header>
 
 <.table id="<%= schema.plural %>" rows={@<%= schema.collection %>} row_click={&JS.navigate(~p"<%= schema.route_prefix %>/#{&1}")}><%= for {k, _} <- schema.attrs do %>
-  <:col :let={<%= schema.singular %>} label="<%= Phoenix.Naming.humanize(Atom.to_string(k)) %>"><%%= <%= schema.singular %>.<%= k %> %></:col><% end %>
+  <:col :let={<%= schema.singular %>} label="<%= Phoenix.Naming.humanize(Atom.to_string(k)) %>">{<%= schema.singular %>.<%= k %>}</:col><% end %>
   <:action :let={<%= schema.singular %>}>
     <div class="sr-only">
       <.link navigate={~p"<%= schema.route_prefix %>/#{<%= schema.singular %>}"}>Show</.link>
diff --git a/priv/templates/phx.gen.html/show.html.heex b/priv/templates/phx.gen.html/show.html.heex
index 9b46db567..ec3f7774a 100644
--- a/priv/templates/phx.gen.html/show.html.heex
+++ b/priv/templates/phx.gen.html/show.html.heex
@@ -1,5 +1,5 @@
 <.header>
-  <%= schema.human_singular %> <%%= @<%= schema.singular %>.id %>
+  <%= schema.human_singular %> {@<%= schema.singular %>.id}
   <:subtitle>This is a <%= schema.singular %> record from your database.</:subtitle>
   <:actions>
     <.button phx-click={JS.dispatch("click", to: {:inner, "a"})}>
@@ -11,7 +11,7 @@
 </.header>
 
 <.list><%= for {k, _} <- schema.attrs do %>
-  <:item title="<%= Phoenix.Naming.humanize(Atom.to_string(k)) %>"><%%= @<%= schema.singular %>.<%= k %> %></:item><% end %>
+  <: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>
diff --git a/priv/templates/phx.gen.live/core_components.ex b/priv/templates/phx.gen.live/core_components.ex
index c604ef553..aaf89f484 100644
--- a/priv/templates/phx.gen.live/core_components.ex
+++ b/priv/templates/phx.gen.live/core_components.ex
@@ -54,9 +54,9 @@ defmodule <%= @web_namespace %>.CoreComponents do
       <p :if={@title} class="flex items-center gap-1.5 text-sm font-semibold leading-6">
         <.icon :if={@kind == :info} name="hero-information-circle-mini" class="h-4 w-4" />
         <.icon :if={@kind == :error} name="hero-exclamation-circle-mini" class="h-4 w-4" />
-        <%%= @title %>
+        {@title}
       </p>
-      <p class="mt-2 text-sm leading-5"><%%= msg %></p>
+      <p class="mt-2 text-sm leading-5">{msg}</p>
       <button type="button" class="group absolute top-1 right-1 p-2" aria-label=<%= maybe_heex_attr_gettext.("close", @gettext) %>>
         <.icon name="hero-x-mark-solid" class="h-5 w-5 opacity-40 group-hover:opacity-70" />
       </button>
@@ -135,9 +135,9 @@ defmodule <%= @web_namespace %>.CoreComponents do
     ~H"""
     <.form :let={f} for={@for} {@as} {@rest}>
       <div class="mt-10 space-y-8 bg-white">
-        <%%= render_slot(@inner_block, f) %>
+        {render_slot(@inner_block, f)}
         <div :for={action <- @actions} class="mt-2 flex items-center justify-between gap-6">
-          <%%= render_slot(action, f) %>
+          {render_slot(action, f)}
         </div>
       </div>
     </.form>
@@ -169,7 +169,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
       ]}
       {@rest}
     >
-      <%%= render_slot(@inner_block) %>
+      {render_slot(@inner_block)}
     </button>
     """
   end
@@ -253,9 +253,9 @@ defmodule <%= @web_namespace %>.CoreComponents do
           class="rounded border-zinc-300 text-zinc-900 focus:ring-0"
           {@rest}
         />
-        <%%= @label %>
+        {@label}
       </label>
-      <.error :for={msg <- @errors}><%%= msg %></.error>
+      <.error :for={msg <- @errors}>{msg}</.error>
     </div>
     """
   end
@@ -263,7 +263,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
   def input(%{type: "select"} = assigns) do
     ~H"""
     <div>
-      <.label for={@id}><%%= @label %></.label>
+      <.label for={@id}>{@label}</.label>
       <select
         id={@id}
         name={@name}
@@ -271,10 +271,10 @@ defmodule <%= @web_namespace %>.CoreComponents do
         multiple={@multiple}
         {@rest}
       >
-        <option :if={@prompt} value=""><%%= @prompt %></option>
-        <%%= Phoenix.HTML.Form.options_for_select(@options, @value) %>
+        <option :if={@prompt} value="">{@prompt}</option>
+        {Phoenix.HTML.Form.options_for_select(@options, @value)}
       </select>
-      <.error :for={msg <- @errors}><%%= msg %></.error>
+      <.error :for={msg <- @errors}>{msg}</.error>
     </div>
     """
   end
@@ -282,7 +282,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
   def input(%{type: "textarea"} = assigns) do
     ~H"""
     <div>
-      <.label for={@id}><%%= @label %></.label>
+      <.label for={@id}>{@label}</.label>
       <textarea
         id={@id}
         name={@name}
@@ -292,8 +292,8 @@ defmodule <%= @web_namespace %>.CoreComponents do
           @errors != [] && "border-rose-400 focus:border-rose-400"
         ]}
         {@rest}
-      ><%%= Phoenix.HTML.Form.normalize_value("textarea", @value) %></textarea>
-      <.error :for={msg <- @errors}><%%= msg %></.error>
+      >{Phoenix.HTML.Form.normalize_value("textarea", @value)}</textarea>
+      <.error :for={msg <- @errors}>{msg}</.error>
     </div>
     """
   end
@@ -302,7 +302,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
   def input(assigns) do
     ~H"""
     <div>
-      <.label for={@id}><%%= @label %></.label>
+      <.label for={@id}>{@label}</.label>
       <input
         type={@type}
         name={@name}
@@ -315,7 +315,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
         ]}
         {@rest}
       />
-      <.error :for={msg <- @errors}><%%= msg %></.error>
+      <.error :for={msg <- @errors}>{msg}</.error>
     </div>
     """
   end
@@ -329,7 +329,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
   def label(assigns) do
     ~H"""
     <label for={@for} class="block text-sm font-semibold leading-6 text-zinc-800">
-      <%%= render_slot(@inner_block) %>
+      {render_slot(@inner_block)}
     </label>
     """
   end
@@ -343,7 +343,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
     ~H"""
     <p class="mt-1.5 flex gap-1.5 text-sm leading-6 text-rose-600">
       <.icon name="hero-exclamation-circle-mini" class="mt-0.5 h-5 w-5 flex-none" />
-      <%%= render_slot(@inner_block) %>
+      {render_slot(@inner_block)}
     </p>
     """
   end
@@ -362,13 +362,13 @@ defmodule <%= @web_namespace %>.CoreComponents do
     <header class={[@actions != [] && "flex items-center justify-between gap-6", @class]}>
       <div>
         <h1 class="text-lg font-semibold leading-8 text-zinc-800">
-          <%%= render_slot(@inner_block) %>
+          {render_slot(@inner_block)}
         </h1>
         <p :if={@subtitle != []} class="mt-2 text-sm leading-6 text-zinc-600">
-          <%%= render_slot(@subtitle) %>
+          {render_slot(@subtitle)}
         </p>
       </div>
-      <div class="flex-none"><%%= render_slot(@actions) %></div>
+      <div class="flex-none">{render_slot(@actions)}</div>
     </header>
     """
   end
@@ -379,8 +379,8 @@ defmodule <%= @web_namespace %>.CoreComponents do
   ## Examples
 
       <.table id="users" rows={@users}>
-        <:col :let={user} label="id"><%%= user.id %></:col>
-        <:col :let={user} label="username"><%%= user.username %></:col>
+        <:col :let={user} label="id">{user.id}</:col>
+        <:col :let={user} label="username">{user.username}</:col>
       </.table>
   """
   attr :id, :string, required: true
@@ -409,7 +409,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
       <table class="w-[40rem] mt-11 sm:w-full">
         <thead class="text-sm text-left leading-6 text-zinc-500">
           <tr>
-            <th :for={col <- @col} class="p-0 pb-4 pr-6 font-normal"><%%= col[:label] %></th>
+            <th :for={col <- @col} class="p-0 pb-4 pr-6 font-normal">{col[:label]}</th>
             <th :if={@action != []} class="relative p-0 pb-4">
               <span class="sr-only"><%= maybe_eex_gettext.("Actions", @gettext) %></span>
             </th>
@@ -429,7 +429,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
               <div class="block py-4 pr-6">
                 <span class="absolute -inset-y-px right-0 -left-4 group-hover:bg-zinc-50 sm:rounded-l-xl" />
                 <span class={["relative", i == 0 && "font-semibold text-zinc-900"]}>
-                  <%%= render_slot(col, @row_item.(row)) %>
+                  {render_slot(col, @row_item.(row))}
                 </span>
               </div>
             </td>
@@ -440,7 +440,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
                   :for={action <- @action}
                   class="relative ml-4 font-semibold leading-6 text-zinc-900 hover:text-zinc-700"
                 >
-                  <%%= render_slot(action, @row_item.(row)) %>
+                  {render_slot(action, @row_item.(row))}
                 </span>
               </div>
             </td>
@@ -457,8 +457,8 @@ defmodule <%= @web_namespace %>.CoreComponents do
   ## Examples
 
       <.list>
-        <:item title="Title"><%%= @post.title %></:item>
-        <:item title="Views"><%%= @post.views %></:item>
+        <:item title="Title">{@post.title}</:item>
+        <:item title="Views">{@post.views}</:item>
       </.list>
   """
   slot :item, required: true do
@@ -470,8 +470,8 @@ defmodule <%= @web_namespace %>.CoreComponents do
     <div class="mt-14">
       <dl class="-my-4 divide-y divide-zinc-100">
         <div :for={item <- @item} class="flex gap-4 py-4 text-sm leading-6 sm:gap-8">
-          <dt class="w-1/4 flex-none text-zinc-500"><%%= item.title %></dt>
-          <dd class="text-zinc-700"><%%= render_slot(item) %></dd>
+          <dt class="w-1/4 flex-none text-zinc-500">{item.title}</dt>
+          <dd class="text-zinc-700">{render_slot(item)}</dd>
         </div>
       </dl>
     </div>
@@ -496,7 +496,7 @@ defmodule <%= @web_namespace %>.CoreComponents do
         class="text-sm font-semibold leading-6 text-zinc-900 hover:text-zinc-700"
       >
         <.icon name="hero-arrow-left-solid" class="h-3 w-3" />
-        <%%= render_slot(@inner_block) %>
+        {render_slot(@inner_block)}
       </.link>
     </div>
     """
diff --git a/priv/templates/phx.gen.live/form.ex b/priv/templates/phx.gen.live/form.ex
index 25627a4e3..c9ea3be8b 100644
--- a/priv/templates/phx.gen.live/form.ex
+++ b/priv/templates/phx.gen.live/form.ex
@@ -8,7 +8,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
   def render(assigns) do
     ~H"""
     <.header>
-      <%%= @page_title %>
+      {@page_title}
       <:subtitle>Use this form to manage <%= schema.singular %> records in your database.</:subtitle>
     </.header>
 
diff --git a/priv/templates/phx.gen.live/index.ex b/priv/templates/phx.gen.live/index.ex
index 36f2e11cc..fd8a7d97d 100644
--- a/priv/templates/phx.gen.live/index.ex
+++ b/priv/templates/phx.gen.live/index.ex
@@ -22,7 +22,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
       rows={@streams.<%= schema.collection %>}
       row_click={fn {_id, <%= schema.singular %>} -> JS.navigate(~p"<%= schema.route_prefix %>/#{<%= schema.singular %>}") end}
     ><%= for {k, _} <- schema.attrs do %>
-      <:col :let={{_id, <%= schema.singular %>}} label="<%= Phoenix.Naming.humanize(Atom.to_string(k)) %>"><%%= <%= schema.singular %>.<%= k %> %></:col><% end %>
+      <:col :let={{_id, <%= schema.singular %>}} label="<%= Phoenix.Naming.humanize(Atom.to_string(k)) %>">{<%= schema.singular %>.<%= k %>}</:col><% end %>
       <:action :let={{_id, <%= schema.singular %>}}>
         <div class="sr-only">
           <.link navigate={~p"<%= schema.route_prefix %>/#{<%= schema.singular %>}"}>Show</.link>
diff --git a/priv/templates/phx.gen.live/show.ex b/priv/templates/phx.gen.live/show.ex
index 6973b730b..445a66fc0 100644
--- a/priv/templates/phx.gen.live/show.ex
+++ b/priv/templates/phx.gen.live/show.ex
@@ -7,7 +7,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
   def render(assigns) do
     ~H"""
     <.header>
-      <%= schema.human_singular %> <%%= @<%= schema.singular %>.<%= schema.opts[:primary_key] || :id %> %>
+      <%= schema.human_singular %> {@<%= schema.singular %>.<%= schema.opts[:primary_key] || :id %>}
       <:subtitle>This is a <%= schema.singular %> record from your database.</:subtitle>
       <:actions>
         <.button phx-click={JS.dispatch("click", to: {:inner, "a"})}>
@@ -19,7 +19,7 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
     </.header>
 
     <.list><%= for {k, _} <- schema.attrs do %>
-      <:item title="<%= Phoenix.Naming.humanize(Atom.to_string(k)) %>"><%%= @<%= schema.singular %>.<%= k %> %></:item><% end %>
+      <: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>


Test patch:
diff --git a/integration_test/mix.exs b/integration_test/mix.exs
index 63cedf531..a63f329ba 100644
--- a/integration_test/mix.exs
+++ b/integration_test/mix.exs
@@ -41,8 +41,7 @@ defmodule Phoenix.Integration.MixProject do
       {:tds, ">= 0.0.0"},
       {:ecto_sqlite3, ">= 0.0.0"},
       {:phoenix_html, "~> 4.1"},
-      # TODO bump on release to {:phoenix_live_view, "~> 1.0.0"},
-      {:phoenix_live_view, "~> 1.0.0-rc.0", override: true},
+      {:phoenix_live_view, "~> 1.0.0"},
       {:dns_cluster, "~> 0.1.1"},
       {:floki, ">= 0.30.0"},
       {:phoenix_live_reload, "~> 1.2"},
diff --git a/integration_test/mix.lock b/integration_test/mix.lock
index 6ce1c9a9c..199ec925d 100644
--- a/integration_test/mix.lock
+++ b/integration_test/mix.lock
@@ -1,51 +1,51 @@
 %{
   "argon2_elixir": {:hex, :argon2_elixir, "4.1.0", "2f242afe47c373663cb404eb75e792f749507075ed737b49685a9f2edcb401df", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "2ecb6f2ca2cca34b28e546224661bf2a85714516d2713c7313c5ffe8bdade7cf"},
-  "bandit": {:hex, :bandit, "1.5.4", "8e56e7cfc06f3c57995be0d9bf4e45b972d8732f5c7e96ef8ec0735f52079527", [:mix], [{:hpax, "~> 0.2.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "04c2b38874769af67fe7f10034f606ad6dda1d8f80c4d7a0c616b347584d5aff"},
-  "bcrypt_elixir": {:hex, :bcrypt_elixir, "3.1.0", "0b110a9a6c619b19a7f73fa3004aa11d6e719a67e672d1633dc36b6b2290a0f7", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "2ad2acb5a8bc049e8d5aa267802631912bb80d5f4110a178ae7999e69dca1bf7"},
-  "castore": {:hex, :castore, "1.0.9", "5cc77474afadf02c7c017823f460a17daa7908e991b0cc917febc90e466a375c", [:mix], [], "hexpm", "5ea956504f1ba6f2b4eb707061d8e17870de2bee95fb59d512872c2ef06925e7"},
+  "bandit": {:hex, :bandit, "1.6.1", "9e01b93d72ddc21d8c576a704949e86ee6cde7d11270a1d3073787876527a48f", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "5a904bf010ea24b67979835e0507688e31ac873d4ffc8ed0e5413e8d77455031"},
+  "bcrypt_elixir": {:hex, :bcrypt_elixir, "3.2.0", "feab711974beba4cb348147170346fe097eea2e840db4e012a145e180ed4ab75", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "563e92a6c77d667b19c5f4ba17ab6d440a085696bdf4c68b9b0f5b30bc5422b8"},
+  "castore": {:hex, :castore, "1.0.10", "43bbeeac820f16c89f79721af1b3e092399b3a1ecc8df1a472738fd853574911", [:mix], [], "hexpm", "1b0b7ea14d889d9ea21202c43a4fa015eb913021cb535e8ed91946f4b77a8848"},
   "cc_precompiler": {:hex, :cc_precompiler, "0.1.10", "47c9c08d8869cf09b41da36538f62bc1abd3e19e41701c2cea2675b53c704258", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "f6e046254e53cd6b41c6bacd70ae728011aa82b2742a80d6e2214855c6e06b22"},
   "comeonin": {:hex, :comeonin, "5.5.0", "364d00df52545c44a139bad919d7eacb55abf39e86565878e17cebb787977368", [:mix], [], "hexpm", "6287fc3ba0aad34883cbe3f7949fc1d1e738e5ccdce77165bc99490aa69f47fb"},
-  "db_connection": {:hex, :db_connection, "2.6.0", "77d835c472b5b67fc4f29556dee74bf511bbafecdcaf98c27d27fa5918152086", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c2f992d15725e721ec7fbc1189d4ecdb8afef76648c746a8e1cad35e3b8a35f3"},
+  "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"},
   "decimal": {:hex, :decimal, "2.2.0", "df3d06bb9517e302b1bd265c1e7f16cda51547ad9d99892049340841f3e15836", [:mix], [], "hexpm", "af8daf87384b51b7e611fb1a1f2c4d4876b65ef968fa8bd3adf44cff401c7f21"},
   "dns_cluster": {:hex, :dns_cluster, "0.1.3", "0bc20a2c88ed6cc494f2964075c359f8c2d00e1bf25518a6a6c7fd277c9b0c66", [:mix], [], "hexpm", "46cb7c4a1b3e52c7ad4cbe33ca5079fbde4840dedeafca2baf77996c2da1bc33"},
-  "ecto": {:hex, :ecto, "3.11.2", "e1d26be989db350a633667c5cda9c3d115ae779b66da567c68c80cfb26a8c9ee", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c38bca2c6f8d8023f2145326cc8a80100c3ffe4dcbd9842ff867f7fc6156c65"},
-  "ecto_sql": {:hex, :ecto_sql, "3.11.3", "4eb7348ff8101fbc4e6bbc5a4404a24fecbe73a3372d16569526b0cf34ebc195", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.11.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e5f36e3d736b99c7fee3e631333b8394ade4bafe9d96d35669fca2d81c2be928"},
-  "ecto_sqlite3": {:hex, :ecto_sqlite3, "0.16.0", "1cdc8ea6319e7cb1bc273a36db0ecde69ad56b4dea3037689ad8c0afc6a91e16", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.11", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.11", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:exqlite, "~> 0.22", [hex: :exqlite, repo: "hexpm", optional: false]}], "hexpm", "73c9dd56830d67c951bc254c082cb0a7f9fa139d44866bc3186c8859d1b4d787"},
-  "elixir_make": {:hex, :elixir_make, "0.8.4", "4960a03ce79081dee8fe119d80ad372c4e7badb84c493cc75983f9d3bc8bde0f", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "6e7f1d619b5f61dfabd0a20aa268e575572b542ac31723293a4c1a567d5ef040"},
-  "esbuild": {:hex, :esbuild, "0.8.1", "0cbf919f0eccb136d2eeef0df49c4acf55336de864e63594adcea3814f3edf41", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "25fc876a67c13cb0a776e7b5d7974851556baeda2085296c14ab48555ea7560f"},
+  "ecto": {:hex, :ecto, "3.12.5", "4a312960ce612e17337e7cefcf9be45b95a3be6b36b6f94dfb3d8c361d631866", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6eb18e80bef8bb57e17f5a7f068a1719fbda384d40fc37acb8eb8aeca493b6ea"},
+  "ecto_sql": {:hex, :ecto_sql, "3.12.1", "c0d0d60e85d9ff4631f12bafa454bc392ce8b9ec83531a412c12a0d415a3a4d0", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "aff5b958a899762c5f09028c847569f7dfb9cc9d63bdb8133bff8a5546de6bf5"},
+  "ecto_sqlite3": {:hex, :ecto_sqlite3, "0.17.5", "fbee5c17ff6afd8e9ded519b0abb363926c65d30b27577232bb066b2a79957b8", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.12", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:exqlite, "~> 0.22", [hex: :exqlite, repo: "hexpm", optional: false]}], "hexpm", "3b54734d998cbd032ac59403c36acf4e019670e8b6ceef9c6c33d8986c4e9704"},
+  "elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"},
+  "esbuild": {:hex, :esbuild, "0.8.2", "5f379dfa383ef482b738e7771daf238b2d1cfb0222bef9d3b20d4c8f06c7a7ac", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "558a8a08ed78eb820efbfda1de196569d8bfa9b51e8371a1934fbb31345feda7"},
   "expo": {:hex, :expo, "1.1.0", "f7b9ed7fb5745ebe1eeedf3d6f29226c5dd52897ac67c0f8af62a07e661e5c75", [:mix], [], "hexpm", "fbadf93f4700fb44c331362177bdca9eeb8097e8b0ef525c9cc501cb9917c960"},
-  "exqlite": {:hex, :exqlite, "0.23.0", "6e851c937a033299d0784994c66da24845415072adbc455a337e20087bce9033", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "404341cceec5e6466aaed160cf0b58be2019b60af82588c215e1224ebd3ec831"},
-  "file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"},
-  "finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"},
-  "floki": {:hex, :floki, "0.36.3", "1102f93b16a55bc5383b85ae3ec470f82dee056eaeff9195e8afdf0ef2a43c30", [:mix], [], "hexpm", "fe0158bff509e407735f6d40b3ee0d7deb47f3f3ee7c6c182ad28599f9f6b27a"},
-  "gettext": {:hex, :gettext, "0.26.1", "38e14ea5dcf962d1fc9f361b63ea07c0ce715a8ef1f9e82d3dfb8e67e0416715", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "01ce56f188b9dc28780a52783d6529ad2bc7124f9744e571e1ee4ea88bf08734"},
+  "exqlite": {:hex, :exqlite, "0.27.1", "73fc0b3dc3b058a77a2b3771f82a6af2ddcf370b069906968a34083d2ffd2884", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "79ef5756451cfb022e8013e1ed00d0f8f7d1333c19502c394dc16b15cfb4e9b4"},
+  "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"},
+  "finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"},
+  "floki": {:hex, :floki, "0.37.0", "b83e0280bbc6372f2a403b2848013650b16640cd2470aea6701f0632223d719e", [:mix], [], "hexpm", "516a0c15a69f78c47dc8e0b9b3724b29608aa6619379f91b1ffa47109b5d0dd3"},
+  "gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"},
   "heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "88ab3a0d790e6a47404cba02800a6b25d2afae50", [tag: "v2.1.1", sparse: "optimized", depth: 1]},
-  "hpax": {:hex, :hpax, "0.2.0", "5a58219adcb75977b2edce5eb22051de9362f08236220c9e859a47111c194ff5", [:mix], [], "hexpm", "bea06558cdae85bed075e6c036993d43cd54d447f76d8190a8db0dc5893fa2f1"},
+  "hpax": {:hex, :hpax, "1.0.1", "c857057f89e8bd71d97d9042e009df2a42705d6d690d54eca84c8b29af0787b0", [:mix], [], "hexpm", "4e2d5a4f76ae1e3048f35ae7adb1641c36265510a2d4638157fbcb53dda38445"},
   "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
   "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
   "mint": {:hex, :mint, "1.6.2", "af6d97a4051eee4f05b5500671d47c3a67dac7386045d87a904126fd4bbcea2e", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "5ee441dffc1892f1ae59127f74afe8fd82fda6587794278d924e4d90ea3d63f9"},
-  "myxql": {:hex, :myxql, "0.7.0", "3382f139b0b0da977a8fc33c8cded125e20df2e400f8d7b7e674fa62a7e077dd", [: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", "40e4b7ad4973c8b895e86a3de04ff7a79c2cf72b9f2bddef7717afb4ab36d8c0"},
+  "myxql": {:hex, :myxql, "0.7.1", "7c7b75aa82227cd2bc9b7fbd4de774fb19a1cdb309c219f411f82ca8860f8e01", [: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", "a491cdff53353a09b5850ac2d472816ebe19f76c30b0d36a43317a67c9004936"},
   "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
   "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"},
-  "pbkdf2_elixir": {:hex, :pbkdf2_elixir, "2.2.0", "2ec4f7daae2bf74cb9e52df3554bbdcec8a38104a7f0ccaa4d45d5919e4c3f19", [:mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}], "hexpm", "6c4af97f5cae925c56caded648520510ea583eebf1587e185b9f445762197aff"},
-  "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.1", "96798325fab2fed5a824ca204e877b81f9afd2e480f581e81f7b4b64a5a477f2", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.17", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "0ae544ff99f3c482b0807c5cec2c8289e810ecacabc04959d82c3337f4703391"},
+  "pbkdf2_elixir": {:hex, :pbkdf2_elixir, "2.3.0", "7b3967797963e15312cde8beeac29136238bb020b1da60c4a0ede610dd9115c1", [:mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}], "hexpm", "61a7bba2764ea03e68a1b8822fdf3e486149bf2caf8f7adf752e3e4aea4467bc"},
+  "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.3", "f686701b0499a07f2e3b122d84d52ff8a31f5def386e03706c916f6feddf69ef", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "909502956916a657a197f94cc1206d9a65247538de8a5e186f7537c895d95764"},
   "phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"},
-  "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.3", "7ff51c9b6609470f681fbea20578dede0e548302b0c8bdf338b5a753a4f045bf", [: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]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "f9470a0a8bae4f56430a23d42f977b5a6205fdba6559d76f932b876bfaec652d"},
+  "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.5", "d5f44d7dbd7cfacaa617b70c5a14b2b598d6f93b9caa8e350c51d56cd4350a9b", [: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]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "1d73920515554d7d6c548aee0bf10a4780568b029d042eccb336db29ea0dad70"},
   "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.5.3", "f2161c207fda0e4fb55165f650f7f8db23f02b29e3bff00ff7ef161d6ac1f09d", [:mix], [{:file_system, "~> 0.3 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "b4ec9cd73cb01ff1bd1cac92e045d13e7030330b74164297d1aee3907b54803c"},
-  "phoenix_live_view": {:hex, :phoenix_live_view, "1.0.0-rc.7", "d2abca526422adea88896769529addb6443390b1d4f1ff9cbe694312d8875fb2", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b82a4575f6f3eb5b97922ec6874b0c52b3ca0cc5dcb4b14ddc478cbfa135dd01"},
+  "phoenix_live_view": {:hex, :phoenix_live_view, "1.0.0", "3a10dfce8f87b2ad4dc65de0732fc2a11e670b2779a19e8d3281f4619a85bce4", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "254caef0028765965ca6bd104cc7d68dcc7d57cc42912bef92f6b03047251d99"},
   "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"},
   "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
   "plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
   "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
-  "postgrex": {:hex, :postgrex, "0.18.0", "f34664101eaca11ff24481ed4c378492fed2ff416cd9b06c399e90f321867d7e", [:mix], [{: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", "a042989ba1bc1cca7383ebb9e461398e3f89f868c92ce6671feb7ef132a252d1"},
-  "req": {:hex, :req, "0.5.4", "e375e4812adf83ffcf787871d7a124d873e983e3b77466e6608b973582f7f837", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "a17998ffe2ef54f79bfdd782ef9f4cbf987d93851e89444cbc466a6a25eee494"},
-  "swoosh": {:hex, :swoosh, "1.16.9", "20c6a32ea49136a4c19f538e27739bb5070558c0fa76b8a95f4d5d5ca7d319a1", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {: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]}, {:mua, "~> 0.2.0", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "878b1a7a6c10ebbf725a3349363f48f79c5e3d792eb621643b0d276a38acc0a6"},
-  "tailwind": {:hex, :tailwind, "0.2.3", "277f08145d407de49650d0a4685dc062174bdd1ae7731c5f1da86163a24dfcdb", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "8e45e7a34a676a7747d04f7913a96c770c85e6be810a1d7f91e713d3a3655b5d"},
+  "postgrex": {:hex, :postgrex, "0.19.3", "a0bda6e3bc75ec07fca5b0a89bffd242ca209a4822a9533e7d3e84ee80707e19", [:mix], [{: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", "d31c28053655b78f47f948c85bb1cf86a9c1f8ead346ba1aa0d0df017fa05b61"},
+  "req": {:hex, :req, "0.5.8", "50d8d65279d6e343a5e46980ac2a70e97136182950833a1968b371e753f6a662", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "d7fc5898a566477e174f26887821a3c5082b243885520ee4b45555f5d53f40ef"},
+  "swoosh": {:hex, :swoosh, "1.17.3", "5cda7bff6bc1121cc5b58db8ed90ef33261b373425ae3e32dd599688037a0482", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {: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]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "14ad57cfbb70af57323e17f569f5840a33c01f8ebc531dd3846beef3c9c95e55"},
+  "tailwind": {:hex, :tailwind, "0.2.4", "5706ec47182d4e7045901302bf3a333e80f3d1af65c442ba9a9eed152fb26c2e", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "c6e4a82b8727bab593700c998a4d98cf3d8025678bfde059aed71d0000c3e463"},
   "tds": {:hex, :tds, "2.3.5", "fedfb96d53206f01eac62ead859e47e1541a62e1553e9eb7a8801c7dca59eae8", [: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]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "52e350f5dd5584bbcff9859e331be144d290b41bd4c749b936014a17660662f2"},
   "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
   "telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"},
   "telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"},
-  "thousand_island": {:hex, :thousand_island, "1.3.5", "6022b6338f1635b3d32406ff98d68b843ba73b3aa95cfc27154223244f3a6ca5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2be6954916fdfe4756af3239fb6b6d75d0b8063b5df03ba76fd8a4c87849e180"},
+  "thousand_island": {:hex, :thousand_island, "1.3.7", "1da7598c0f4f5f50562c097a3f8af308ded48cd35139f0e6f17d9443e4d0c9c5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "0139335079953de41d381a6134d8b618d53d084f558c734f2662d1a72818dd12"},
   "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
-  "websock_adapter": {:hex, :websock_adapter, "0.5.6", "0437fe56e093fd4ac422de33bf8fc89f7bc1416a3f2d732d8b2c8fd54792fe60", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "e04378d26b0af627817ae84c92083b7e97aca3121196679b73c73b99d0d133ea"},
+  "websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"},
 }
diff --git a/test/mix/tasks/phx.gen.auth/injector_test.exs b/test/mix/tasks/phx.gen.auth/injector_test.exs
index 6f43d5d98..d526af98c 100644
--- a/test/mix/tasks/phx.gen.auth/injector_test.exs
+++ b/test/mix/tasks/phx.gen.auth/injector_test.exs
@@ -668,7 +668,7 @@ defmodule Mix.Tasks.Phx.Gen.Auth.InjectorTest do
                          <ul class="relative z-10 flex items-center gap-4 px-4 sm:px-6 lg:px-8 justify-end">
                            <%= if @current_user do %>
                              <li class="text-[0.8125rem] leading-6 text-zinc-900">
-                               <%= @current_user.email %>
+                               {@current_user.email}
                              </li>
                              <li>
                                <.link
@@ -762,7 +762,7 @@ defmodule Mix.Tasks.Phx.Gen.Auth.InjectorTest do
                          <ul class="relative z-10 flex items-center gap-4 px-4 sm:px-6 lg:px-8 justify-end">\r
                            <%= if @current_user do %>\r
                              <li class="text-[0.8125rem] leading-6 text-zinc-900">\r
-                               <%= @current_user.email %>\r
+                               {@current_user.email}\r
                              </li>\r
                              <li>\r
                                <.link\r
@@ -819,9 +819,9 @@ defmodule Mix.Tasks.Phx.Gen.Auth.InjectorTest do
         </head>
         <body>
           <main class="container">
-            <p class="alert alert-info" role="alert"><%= Phoenix.Flash.get(@conn, :info) %></p>
-            <p class="alert alert-danger" role="alert"><%= Phoenix.Flash.get(@conn, :error) %></p>
-            <%= @inner_content %>
+            <p class="alert alert-info" role="alert">{Phoenix.Flash.get(@conn, :info)}</p>
+            <p class="alert alert-danger" role="alert">{Phoenix.Flash.get(@conn, :error)}</p>
+            {@inner_content}
           </main>
         </body>
       </html>
@@ -840,7 +840,7 @@ defmodule Mix.Tasks.Phx.Gen.Auth.InjectorTest do
                    <ul class="relative z-10 flex items-center gap-4 px-4 sm:px-6 lg:px-8 justify-end">
                      <%= if @current_user do %>
                        <li class="text-[0.8125rem] leading-6 text-zinc-900">
-                         <%= @current_user.email %>
+                         {@current_user.email}
                        </li>
                        <li>
                          <.link
@@ -879,9 +879,9 @@ defmodule Mix.Tasks.Phx.Gen.Auth.InjectorTest do
                      <% end %>
                    </ul>
                    <main class="container">
-                     <p class="alert alert-info" role="alert"><%= Phoenix.Flash.get(@conn, :info) %></p>
-                     <p class="alert alert-danger" role="alert"><%= Phoenix.Flash.get(@conn, :error) %></p>
-                     <%= @inner_content %>
+                     <p class="alert alert-info" role="alert">{Phoenix.Flash.get(@conn, :info)}</p>
+                     <p class="alert alert-danger" role="alert">{Phoenix.Flash.get(@conn, :error)}</p>
+                     {@inner_content}
                    </main>
                  </body>
                </html>
@@ -899,9 +899,9 @@ defmodule Mix.Tasks.Phx.Gen.Auth.InjectorTest do
         </head>\r
         <body>\r
           <main class="container">\r
-            <p class="alert alert-info" role="alert"><%= Phoenix.Flash.get(@conn, :info) %></p>\r
-            <p class="alert alert-danger" role="alert"><%= Phoenix.Flash.get(@conn, :error) %></p>\r
-            <%= @inner_content %>\r
+            <p class="alert alert-info" role="alert">{Phoenix.Flash.get(@conn, :info)}</p>\r
+            <p class="alert alert-danger" role="alert">{Phoenix.Flash.get(@conn, :error)}</p>\r
+            {@inner_content}\r
           </main>\r
         </body>\r
       </html>\r
@@ -920,7 +920,7 @@ defmodule Mix.Tasks.Phx.Gen.Auth.InjectorTest do
                    <ul class="relative z-10 flex items-center gap-4 px-4 sm:px-6 lg:px-8 justify-end">\r
                      <%= if @current_user do %>\r
                        <li class="text-[0.8125rem] leading-6 text-zinc-900">\r
-                         <%= @current_user.email %>\r
+                         {@current_user.email}\r
                        </li>\r
                        <li>\r
                          <.link\r
@@ -959,9 +959,9 @@ defmodule Mix.Tasks.Phx.Gen.Auth.InjectorTest do
                      <% end %>\r
                    </ul>\r
                    <main class="container">\r
-                     <p class="alert alert-info" role="alert"><%= Phoenix.Flash.get(@conn, :info) %></p>\r
-                     <p class="alert alert-danger" role="alert"><%= Phoenix.Flash.get(@conn, :error) %></p>\r
-                     <%= @inner_content %>\r
+                     <p class="alert alert-info" role="alert">{Phoenix.Flash.get(@conn, :info)}</p>\r
+                     <p class="alert alert-danger" role="alert">{Phoenix.Flash.get(@conn, :error)}</p>\r
+                     {@inner_content}\r
                    </main>\r
                  </body>\r
                </html>\r
@@ -981,7 +981,7 @@ defmodule Mix.Tasks.Phx.Gen.Auth.InjectorTest do
           <div class="my-header">
             <ul>
               <%= if @current_user do %>
-                <li><%= @current_user.email %></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 %>
@@ -991,9 +991,9 @@ defmodule Mix.Tasks.Phx.Gen.Auth.InjectorTest do
             </ul>
           </div>
           <main class="container">
-            <p class="alert alert-info" role="alert"><%= Phoenix.Flash.get(@conn, :info) %></p>
-            <p class="alert alert-danger" role="alert"><%= Phoenix.Flash.get(@conn, :error) %></p>
-            <%= @inner_content %>
+            <p class="alert alert-info" role="alert">{Phoenix.Flash.get(@conn, :info)}</p>
+            <p class="alert alert-danger" role="alert">{Phoenix.Flash.get(@conn, :error)}</p>
+            {@inner_content}
           </main>
         </body>
       </html>
diff --git a/test/mix/tasks/phx.gen.auth_test.exs b/test/mix/tasks/phx.gen.auth_test.exs
index 773ec9a27..fb90b40fb 100644
--- a/test/mix/tasks/phx.gen.auth_test.exs
+++ b/test/mix/tasks/phx.gen.auth_test.exs
@@ -1368,7 +1368,7 @@ defmodule Mix.Tasks.Phx.Gen.AuthTest do
             <ul class="relative z-10 flex items-center gap-4 px-4 sm:px-6 lg:px-8 justify-end">
               <%= if @current_user do %>
                 <li class="text-[0.8125rem] leading-6 text-zinc-900">
-                  <%= @current_user.email %>
+                  {@current_user.email}
                 </li>
                 <li>
                   <.link
@@ -1432,7 +1432,7 @@ defmodule Mix.Tasks.Phx.Gen.AuthTest do
             <ul class="relative z-10 flex items-center gap-4 px-4 sm:px-6 lg:px-8 justify-end">
               <%= if @current_user do %>
                 <li class="text-[0.8125rem] leading-6 text-zinc-900">
-                  <%= @current_user.email %>
+                  {@current_user.email}
                 </li>
                 <li>
                   <.link