Wanted: examples of well organized Phoenix LiveView apps

I feel lost in my Phoenix LiveView code base. Coming from Rails, I can’t find anything. But I also have no confidence that I’m got it organized according to best practices.

For example, where should the template for a certain page or route be? Should it be in a .heex file, or in .ex? When is one usually chosen over the other?

Are there any good examples out there of some full Phoenix LiveView apps that I can learn from?

I have your last post about this in mind and mostly balked at replying as it becomes a bit of an exhausting discussion where many people have Opions :tm: (and oh boy do I ever have Opinions :tm: myself!) For me, the best part of Rails and the worst part of Phoenix is that Rails is opinionated and Phoenix is not. Of course many people see Phoenix’s lack of opinion—atedness(?) as a good thing, but it does leave a lot of people lost.

All that is to say that the closest thing we have to best practices in Phoenix is the guides. I’d say that the most controversial part is contexts and what I’m assuming is giving you trouble in finding stuff. Oddly enough they are supposed to make that easier :sweat_smile: I love contexts and were a big part of the attraction for me. Contexts are loosely based on Bounded Contexts from Domain Driven Design. I say loosely because you are free to use them in a way that doesn’t conform to DDD’s idea, but you can absolutely use them as such! DDD is one of those things like Agile and TDD that you either buy into or you don’t. I’m personally a big fan (or parts of it at least, and I could go more into that) but of course you are not bound to it.

Even though it pains me personally to say this (:zany_face:) if you’re missing Rails then throwing all your schemas in a MyApp.Schemas namespace is perfectly acceptable. You could forgo contexts completely and add repo functions to your schemas like MyApp.User.save(user). Even Ash optionally supports this (though it would be MyApp.Accounts.User.save(user)) On the other hand, the last big Rails project I worked on used bounded contexts and it was great so, ya :slight_smile:

Asking for “well organized based on best practices” Phoenix project is a bit of a loaded question so I’d say refine it to “well organized” you’ll more likely get many different answers :smiley:

But as far what Chris was thinking in terms of context, I’d suggest at least reading about DDD’s bounded contexts if you’re curious. The neat thing about DDD is that it isn’t one of those prescriptive things where it claims you need to follow all of its advice exactly—it’s a HUGE book that openly says: “Here are a whole bunch of fleshed out ideas, maybe you want to use some of them.” It even puts a whole bunch of paragraphs throughout the book in bold text and suggests that only reading those paragraphs is perfectly acceptable to get a lot out of it.

PS I neglected your specific question to ramble:

Templates can go in either .heex or in render functions it’s totally up to you. The only metric I’ve ever heard anyone use is that they put it in a .heex file “when it gets too big.” Personally, I always put it in a render no matter how big it is.

3 Likes

Thanks! I appreciate the detailed reply. Are there any compiler or type safety differences between .heex and .ex? Or does it really just come to IDE support and preference for more vs. fewer files? Personally, it helps narrow down the search if say, I need to change the text on the “home” page, and I know I’m looking for a .heex file.

Naw, heex is heex whether it’s in a .heex file or ~H sigil!

I hear you on the making things easier to find. How you name LiveViews etc is another thing that you’ll see all sorts of different advice on. While it can vary per project, I’m generally looking for home/index_live.ex if I want something on the home page.

2 Likes

I’d try running some generators and only steering away from that if you have very good reason to do so. It’s a great starting point, everyone will know where things go.

mix phx.gen.live Accounts User users name:string age:integer and so forth. Contexts are a thing, once you start, it’s very foreign to not think about problems that way.

4 Likes