docs/ROUTEX_AND_PHOENIX_ROUTER.md

# How Routex and Phoenix Router Work Together: A Blueprint for Understanding

<small>
 All code on this page is for illustration purpose only. It is incorrect and
 should not be used.
</small>

How Routex, its extensions, and the Phoenix Router work together can be better
understood through an analogy. As the saying goes, "a picture is worth a
thousand words," this document also includes an illustrative blueprint.


## Analogy: the housing project

Imagine you're a *real estate developer* planning to build several houses. You
have a general vision for the houses (your route definitions in `route.ex`) and
some specific ideas about their style and features (your Routex configuration).

```
# routes
/products
/products/:id

# config
alternatives: %{
    "/fr" => %{name: "French"},
    "/es" => %{name: "Spanish"}
}
```

Routex is the *architect*. It takes your vision (route definitions) and
preferences (Routex config) and creates detailed blueprints.

Routex extensions are the *architect's specialized tools*. These tools allow the
architect to refine and customize the blueprints. Without them, the architect
could only create basic, unmodified plans.

```
# input
[
%Route{path: "/products"}
%Route{path: "/products/:id"}
]

# output after transformation by Alternatives extension
[
%Route{path: "/fr/products",      metadata: %{name: "French"}},
%Route{path: "/fr/products/:id",  metadata: %{name: "French"}},
%Route{path: "/es/products",      metadata: %{name: "Spanish"}},
%Route{path: "/es/products/:id",  metadata: %{name: "Spanish"}}
]
```

Once the blueprints are finalized, they're handed off to the *construction
company*: Phoenix Router. Phoenix Router builds the actual houses (your routes)
according to the architect's precise specifications. The blueprints are
perfectly formatted for Phoenix Router, ensuring a smooth construction process.

```
# note: incorrect pseudo code

if match?("/fr/products"      ), do: ProductLive, :index, metadata: ["French"]
if match?("/fr/products/" <> id), do: ProductLive, :show,  metadata: ["French"]
if match?("/es/products"      ), do: ProductLive, :index, metadata: ["Spanish"]
if match?("/es/products/" <> id), do: ProductLive, :show,  metadata: ["Spanish"]
```

This explains the first key concept:

> **Routex generates blueprints from your route definitions and configuration,
> ready for Phoenix Router to build the actual routes.**

Because Routex is the architect, it has intimate knowledge of the house designs.
This allows it to create perfectly matching accessories, like custom-designed
sunshades or smart garage doors. These are *additional* features that enhance
the houses built by Phoenix Router, adding convenience and functionality.

```
# generated convenient functions
defmodule Helpers do
  def alternatives("/products") do
    [
      %Route{path: "/fr/products", name: "French"},
      %Route{path: "/es/products", name: "Spanish"}
    ]
  end
end

# your usage
This page is available in:
for alt <- Helpers.alternatives("/products") do
 <.link navigate={alt.path}>{alt.name}<./link>
end

# output
This page is available in:
<a href="/fr/products">French</a>
<a href="/es/products">Spanish</a>
```

This leads to the second key concept:

> **Routex also creates helpful accessory functions that you can use with the
> houses (routes) built by Phoenix Router.** These functions streamline common
> tasks and improve the overall experience.


## Example blueprint

A picture paints a thousand words, or so they say. The blueprint clearly shows
how Routex is middleware, plugged between two stages of Phoenix route generation.

Also shown is the use two co-operating extensions: `Translations` uses the
`:language` attribute set by `Alternatives`.

<pre class="mermaid">
flowchart TD
 subgraph subGraph1["Routex"]
        F["ExampleWeb.RoutexBackend.ex"]
        G["configure/2 callbacks"]
        H["Alternatives.transform/3 callback"]
        I["Translations.transform/3 callback"]
        J["create_helpers/3 callbacks"]
     K["ExampleWeb.Router.RoutexHelpers"]
  end
  subgraph subGraph0["Phoenix"]
        A["ExampleWeb.Router.ex"]
        B["Convert to Phoenix.Routes.Route structs"]
        C["Generate route functions"]
        D["ExampleWeb.Router"]
  end
  A -- "/products/:id" --> B
  B -- "%{path: /products/:id}" --> H
  F -- "extensions: [Alternatives, Translations]" --> G
  G --> H
  H -- "%{path: ..., attrs: %{lang: fr}}
       %{path: ..., attrs: %{lang: es}}" --> I
  I -- "%{path: /produit/:id, attrs: ...}
       %{path: /producto/:id, attrs: ...}" --> C & J
  C -- "def match?(/produit/:id), do: ProductController
      def match?(/producto/:id), do: ProductController" --> D
  J -- "def alternatives(/products/:id) do
        %{path: /produit/:id, attrs: %{lang: fr}}
        %{path: /producto/:id, attrs: %{lang: es}}
      end" --> K

  F:::routex
  G:::routex
  H:::routex
  I:::routex
  J:::routex
  K:::routex
  A:::phoenix
  B:::phoenix
  C:::phoenix
  D:::phoenix
 classDef routex  fill:#4d4d4d, stroke:#888, stroke-width:2px, color:#ffffff
 classDef phoenix  stroke-width:1px, stroke-dasharray: 0, stroke:#616161, fill:#FF6D00, color:#424242
 style subGraph0 fill:#FFFFFF, stroke:#757575
 style subGraph1 fill:#FFFFFF, stroke:#757575
</pre>


## Conclusion
Phoenix Router and Routex, along with its extensions, form a powerful
partnership that empowers you to build any route in your web application. Routex
expertly designs the intricate pathways of your application's URLs, while
Phoenix Router flawlessly constructs them, ensuring a smooth and efficient user
experience.