(Phoenix.Router.NoRouteError) no route found for GET /images/logo.svg (MyWeb.Router)

Phoenix version from mix.exs:

defmodule MyWeb.MixProject do
  use Mix.Project

  def project do
      app: :my_web,
      version: "0.1.0",
      build_path: "../../_build",
      config_path: "../../config/config.exs",
      deps_path: "../../deps",
      lockfile: "../../mix.lock",
      elixir: "~> 1.14",
      elixirc_paths: elixirc_paths(Mix.env()),
      start_permanent: Mix.env() == :prod,
      aliases: aliases(),
      deps: deps()

  # Configuration for the OTP application.
  # Type `mix help compile.app` for more information.
  def application do
      mod: {MyWeb.Application, []},
      extra_applications: [:logger, :runtime_tools]

  # Specifies which paths to compile per environment.
  defp elixirc_paths(:test), do: ["lib", "test/support"]
  defp elixirc_paths(_), do: ["lib"]

  # Specifies your project dependencies.
  # Type `mix help deps` for examples and options.
  defp deps do
      {:phoenix, "~> 1.7.2"},
      {:phoenix_html, "~> 3.3"},
      {:phoenix_live_reload, "~> 1.2", only: :dev},
      {:phoenix_live_view, "~> 0.18.16"},
      {:floki, ">= 0.30.0", only: :test},
      {:phoenix_live_dashboard, "~> 0.7.2"},
      {:esbuild, "~> 0.7", runtime: Mix.env() == :dev},
      {:tailwind, "~> 0.2.0", runtime: Mix.env() == :dev},
      {:telemetry_metrics, "~> 0.6"},
      {:telemetry_poller, "~> 1.0"},
      {:gettext, "~> 0.20"},
      {:jason, "~> 1.2"},
      {:plug_cowboy, "~> 2.5"}

I added a /demo route to my app:

  scope "/", MyWeb do
    pipe_through :browser

    get "/", PageController, :home
    get "/demo", DemoController, :home

DemoController looks like this:

defmodule MyWeb.DemoController do
  use MyWeb, :controller

  def home(conn, _params) do
    # The home page is often custom made,
    # so skip the default app layout.
    render(conn, :home)

demo_html.ex looks like this:

defmodule MyWeb.DemoHTML do
  use MyWeb, :html

  embed_templates "demo_html/*"

And, demo_html/ has one file in it, home.html.heex , which looks like this:

  <div>Hello world, from Demo!</div>

mix phx.server starts up without any warnings or errors, but when I enter http://localhost:4000/demo in my browser, the server window displays the error:

(Phoenix.Router.NoRouteError) no route found for GET /images/logo.svg (MyWeb.Router)

I traced that error to the mix generated layout ../components/layouts/app.html.heex:

header class="px-4 sm:px-6 lg:px-8">
  <div class="flex items-center justify-between border-b border-zinc-100 py-3 text-sm">
    <div class="flex items-center gap-4">
      <a href="/">
        <img src={~p"/images/logo.svg"} width="36" />     <======ERROR

Why does the mix generated layout cause errors? There is no images directory anywhere in my app. I deleted the <img> tag to get rid of the warning. I don’t even understand how that layout gets rendered because router.ex looks like this:

defmodule MyWeb.Router do
  use MyWeb, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_live_flash
    plug :put_root_layout, {MyWeb.Layouts, :root}
    plug :protect_from_forgery
    plug :put_secure_browser_headers

  pipeline :api do
    plug :accepts, ["json"]

  scope "/", MyWeb do
    pipe_through :browser

    get "/", PageController, :home
    get "/demo", DemoController, :home

The :browser pipeline says to use the root layout, which presumably is layouts/root.html.heex–not layouts/app.html.heex.

I also get a warning:

warning: Plug.Swoosh.MailboxPreview.init/1 is undefined (module Plug.Swoosh.MailboxPreview is not available or is yet to be defined)

I haven’t solved that, yet.

And, the first time I started the server, I got this error:

11:38:51.923 [error] GenServer #PID<0.3462.0> terminating
** (ArgumentError) unknown registry: MyWeb.PubSub

which I solved using the advice in this thread Pubsub in a phoenix app under umbrella - #14 by josefrichter. To get rid of my PubSub error, I made the following changes to the file../apps/my_web/lib/my_web/application.ex:

  @impl true
  def start(_type, _args) do
    children = [
      # Start the Telemetry supervisor
      # Start the Endpoint (http/https)
      MyWeb.Endpoint,    ## <=======================ADD A COMMA HERE
      # Start a worker by calling: MyWeb.Worker.start_link(arg)
      # {MyWeb.Worker, arg}
      {Phoenix.PubSub, name: MyWeb.PubSub}   ##<======ADD THIS LINE

It seems like there is way too much complexity for mix to be able to set up a basic Phoenix umbrella app that works without warnings or errors.