You can still use an umbrella to do this if the idea is to keep the apps and shared dependencies together during development. Each web app can have it’s own endpoint and router etc., they just need to bind to different ports… 4000, 4001, … if they’re going to be run together during development.
If you’re going to need to use them as independent apps in production, you can divide them using Mix.Release. Just define them in the releases section of the mix project and then you can generate a release that contains only a particular app and its common dependencies. The key is that that each web app cannot depend on each other.
I’m not quite sure what you mean by wanting to avoid multiple phoenix “instances”. Can you expand on that a little more?
You can have multiple Phoenix endpoints while running a single Phoenix server on a single port. One approach to assist with that is https://github.com/jesseshieh/master_proxy/
I’ve used that approach (or similar) to have two phoenix endpoints serving two different but related domains as well as serve multiple separate phoenix based projects from a single beam instance before.
My mistake, I misunderstood the term “endpoints”. I manually copied/pasted the project_web and create the new endpoint, configs, and modules as suggested by @kokolegorille. Would be great some phx command for this, but it is ok for me on do it manually. Now I have CMS running on port 4000 and REST running on port 4001 with its own Views, router, and Controllers.
The good thing is also that I can easily convert it to microservices just by cutting/copying the folder on a new brand phoenix project or using releases as @l00ker said.
I’m still not clear on why this shouldn’t be an umbrella project - copy-pasting like that would be easier if the compiler was helping you enforce the boundaries between the parts.
To be clear, this is a specific thing you can do with an umbrella not a general technique.
It’s either get a dependency or copy/paste the parts you need…
Anyhow, if you ever wanted another solution then check this out (it is configured like this). The reason for divergence was to support use of Phoenix LiveView, Phoenix Sockets, etc; at the same time I had to to ensure that functions internal to each Endpoint continue to work 100% correctly + all the tests would run correctly.
With this proxy pattern I could have an admin app that serves everything under /admin, a specialised app that serves everything under /external, and a general app that serves everything else, etc. At the end of the day listening on one port is easier than two or more.