Thoughts on File Based Routing?

Hey guys, I was wondering what everyone’s take on file-based routing? I know Phoenix has very much the style of Rails Routes setup but the flow with file-based routing feels really smooth for me. I was wondering if y’all feel the same way?

Prime examples of this can be seen in many of the front-end frameworks :
Next
Remix
SvelteKit

I was contemplating making a library that leverages what Phoenix offers but through file-based routing. Would others be interested in this? Is this even possible?

I’ve got a lot to learn to implement this, but I really enjoy Phoenix & Elixir and I think the philosophy of being a wrapper around your app vs the backbone of your app can be leveraged further in this way.

Would love y’alls thoughts on this, and sorry if this is really dumb.

I’d imagine you could build a router at compile time based on files quite well. Though I’d be curious if people actually have a single file per route, because for my projects that’s hardly the case.

2 Likes

I was thinking things can be very much like how SvelteKit shadow points are, and how we have a live structure now actually. Just spit balling here:

├── post
│   ├── new.ex
│   ├── new.html.heex #Optional if you have a render call in index.ex (seen below)
│   ├── [id].ex

Within this, we can have predefined functions of [get, post, put, del] very much how we have it in the live controller with [mount, handle_event, handle_info, update, etc.]

ie: new.ex would have

  def get(conn, _params) do
    # Logic
    render(conn, "index.html")
  end

  def post(conn, _params) do
    # Logic
    render(conn, "index.html")
  end

# This can be separated into separate heex page if wanted, as we currently have in phx
  def render(assigns) do 
    ~H"""
     <form></form>
     """
  end

And then when we run mix phx.routes we can see naming of

post_new_path GET /posts ??? :new
post_path GET /posts/id ??? :id

Now I’m not sure how this would work live_view wise but REST wise it would work right?

Not quite, typically REST doesn’t POST to /resources/new. It would look something like:

  • resource
    • new.ex - has a get function (new in standard Phoenix)
    • index.ex - has a get (Phoenix index) and a post (Phoenix create) function
    • [id].ex - has a get (Phoenix show), a put (Phoenix update) and a delete (Phoenix delete)
    • [id]/edit.ex has a get (Phoenix edit)

One big challenge I see with this approach is that it’s not possible to tell which HTTP verbs a particular file supports without compiling it. That would make compiling route helpers a circular dependency: the files that talk HTTP define the routes but also USE them.

Some things that are split apart in this approach (new vs create for instance) are IMO better off together, because they depend on common templates and therefore need to set the same assigns.

1 Like