Best way to use Phoenix & Next.js?

Hello!

I have been searching the web for some resources on this topic but have fallen short. I am in the process of creating a web and mobile application that will utilize Phoenix Channels for realtime communication. After some prototyping, I have decided that rather than use LiveView, I will use Phoenix Channels to handle realtime connections and build out the application in React.

In the best case scenario, I’d like to use something like Next.js or Remix for my web application. The added benefit for me is that it can handle both static and dynamic web pages.

My thinking was that I could use Next.js as both a CRUD API for various actions on the site and use it as a reverse proxy to Phoenix for any realtime communication.

My concern is that doing this will take away some benefits of talking to Phoenix directly as I would have to do an additional network hop. Also, I’m not sure that Next.js supports proxying websocket requests, so that might not even be an option.

Does anyone know what the right approach here would be? I found this article that sort of summarizes my approach but I don’t know if there are other ways of going about this.

2 Likes

I’ll caveat that I’m very new to Elixir and Phoenix so take my answer with that in mind. However I’ve been coding in React/Node for many years.
Without knowing the exact requirements of your app, this sounds to me like unnecessary overhead just to get some pages statically generated. Why not start with just Phoenix across all your routes and look to optimise with static generation later if you have heavy traffic?
It sounds like you’d be trading all the ease of development that Phoenix offers to benefit some of your pages load times / server usage but you’d be adding layers of complexity and possibly latency everywhere else.

3 Likes

LveSvelte is better

I’m in the same boat! And I ultimately agree with your advice. It’s definitely unnecessary overhead, but I also think this is a pattern that could be quite common, especially for people that want to dabble in Phoenix, without being 100% sold on LiveView or are building applications outside of just a web app.

That said, I am doing this as a learning experience/experiment so I’m alright with the overhead for now. I found a few things that touched on what I was going for since posting this.

I’m not all in on Next.js /the JavaScript framework itself. I actually wanted to give Remix a fair shot, and reading through this doc gave me some ideas on how I might be able to approach the separation of server-client state: Backend For Frontend | Remix. Also, I found this repo on another thread that I might borrow some ideas from: GitHub - arcanemachine/phoenix-todo-list: Yet another todo list. Made using the Phoenix web framework. Features: Basic CRUD, LiveView CRUD, REST API, OpenAPI spec, Playwright E2E tests, GitHub Actions CI, and more!.

There are many downsides to doing what I’m suggesting if I plan on simply creating a website. This approach would mean that for any pages that hit the Node server first, I am mostly likely going to be doing unnecessary network hops. Client → Node server → Elixir → DB → Node → Client. However, for Phoenix channels, I am going to talk directly to my Elixir service and not overcomplicate that.

In addition, Auth and any communication to third party services will also happen in my Phoenix application. So really my Remix setup will be making redundant calls and ultimately provide no other value than an opinionated framework for writing JS/React.

The biggest hurdle so far for me has actually been finding an out-of-the-box auth solution. phx.gen.auth requires HTML (at least for the code generation) and while I have been trying to repurpose that for an API architecture, it is quite challenging for a newbie.

Either way, I’m going to continue with this approach, maybe it will make sense to use the SPA mode that Remix just introduced, but either way I’m not quite ready to give up on JS… Probably controversial, but the Phoenix development experience compared to the React toolkit isn’t there yet and I’m not ready to give it up.

1 Like

I also have written some projects in Svelte and really love it. I am just so much more productive with React believe it or not, so I don’t mind the JS bloat for now

It sounds like you’re not sold on LV, which is completely understandable, but why not use React for your FE with a Phoenix API+channels, which is not an uncommon setup (this is my stack at work for the last 3 years)? I don’t see the reason for introducing a third layer just for a CRUD API? Phoenix can serve static pages just fine as well…

2 Likes

Yeah this is definitely the easiest starting point. I was looking for a React framework that was a bit more opinionated to started, but after having done some poking around. This is the approach that makes the most sense. I might still experiment with Remix using their SPA mode, which still gives me the framework utils but without needing to host a Node server.

I recommend taking a look at the recently released Tanstack Router as well as Remix. It’s very similar to React Router/Remix, but with better type safety and I find the routing structure a bit easier to understand.

1 Like

I’m not sure if it’s what you’re looking for, but if you want static pages with React support, Astro is great. You don’t need a Node server but can add one later if you want any server-rendered routes. It also allows SPA routes (React, Vue, Svelte, or whatever you want).