Umbrella for an SPA app?

Hi, I’m trying to figure out if I should start building an umbrella app or not.
The app is going to be 90% a SPA, meaning that I don’t exclude having something (visually functionally) outside that single page but most of it will be some kind of image annotation program and a bunch of forms all built with Elm.
The app will need to authenticate against a RoR Oauth provider, the frontend will communicate with the backend through an API, everything will be backed by a PostgreSQL database.
Without writing a single line of code I see a backend to fetch and write data, an api endpoint, and a rich frontend app serving Elm + HTML.
Seems to me that it could be a Phoenix app or an umbrella app and that both approaches kinda fit, I’m looking for a recommendation.

TIA,
ngw

1 Like

I’ve used both umbrellas and regular one app settings. I’m developing a game (quite developed by now) in a phoenix only setup, serving a vue app and it has been great. I’ve done an umbrella controlling chrome headless browser bots with success and I’m now working on an application where I decided again to use an umbrella. In fact stretching it a bit more and using only phoenix as api’s apps, while the nuxt front-end is outside of the phoenix app (which allows to deploy the front-end to something like now) and then the backends to their cloud servers. I’m not sure yet if I’ll use docker to containerise the apps (building with distillery) or just use plain releases to deploy them.
Either way, this is the structure I’ve been using so far, and I’m really enjoying how it’s coming together:

It’s a single repo, ~_nuxt_frontend is the nuxt app, npm-packages-offline-cache are the tar balls for yarn dependencies and in the apps, db_main & db_msl are ecto apps, admin_api and main_api are phoenix apps (with --no-brunch --no-ecto, and only have html because I needed a way to render email templates, and didn’t find a good way of extracting that without creating another phoenix app - probably there’s a way (simple) though), csv_parser and `records_builder are --sup applications and the remaining plain apps without supervision trees. The admin_api has dependencies on both ecto apps, while the main_api only has on db_main.

I think in the end it boils down to what you need. A phoenix only app is certainly more than enough for a lot of use cases. An umbrella app is also quite a good choice for more complex situations and handles simpler situations just as fine. What I think is a plus of umbrellas is that you can sort of “package” your different parts of the “system”, even if its all to be deployed as a “single system”. If you intend to deploy multiple apps as independent systems though then an umbrella makes it much easier. And in this particular case, it makes everything (even disparate systems such as node/vues-nuxt fit in the same repo)

(and when I say umbrella I just mean independent apps, as far as I know there’s other approaches that don’t require to be declared as an umbrella and instead mimic what the umbrella does by linking the apps & dependencies in a regular way - it has been pointed here on the forum’s a lot of times pragdave’s approach, which I think that at a conceptual level matches the idea of an umbrella but is done manually without the auto-gluing of the --umbrella).

6 Likes

A Phoenix app can be a great way to start. The generators and pre-made configuration setup for ecto, schemas, contexts, controllers, etc. is great for productivity. That being said if you’re really want to separate concerns you might break the application up into smaller pieces; particularly the Ecto/Context and OAuth concerns in the typical Phoenix CRUD application. It will take more initial setup to break things up nicely in an Umbrella, and if you’re new to the Elixir ecosystem, you’re probably best served remaining within Phoenix’s gentle embrace.

What I’d do with the Umbrella is build a separate application for the OAuth concerns and integrate it with the Phoenix app using a plug. Then if you’re using Ecto for PostgreSQL, build another mix application for the the query and persistence logic. Ecto can sometimes be confusing to setup to the degree of convenience you have with Phoenix, so I like to use something like mix generator to help with getting the various environments setup for testing and what-not. Using the mix generator to setup an Ecto application will give you maybe 60% of the convenience Phoenix gives you as you’ll still need to hand-write schemas and migrations (no handy mix phx.gen.context/JSON commands).

Breaking things up into small applications naturally lends itself to isolated testing and decoupled components.

Depending on how separate you want your concerns you can build another application that supports the primary business logic that contains some sort of command-layer API. This is just personal preference. I like to have command and query separation; this allows having a stateful core application that doesn’t know about Ecto (it uses only the public API in the persistence application). This gives you a very natural way to build out. When you find another piece that doesn’t quite fit, just mix new my_app --sup and do your thing.

But again. It’s not that hard to rebuild into an umbrella, but there is more surface area to know up front - it will slow you down if you’re just starting. I recently refactored a Phoenix application into an Umbrella just a few days ago and it went fine. If you design your Contexts well - it’ll be a breeze. Prioritize productivity and get moving fast - Phoenix’s conventions will serve you well. Momentum shouldn’t be understated.

4 Likes