paulstatezny

paulstatezny

Announcing Uniform.

Uniform tries to minimize the work required to maintain a large portfolio of Elixir apps. It does this via centralization and automation.

How it works

Uniform works best when you have a portfolio of apps whose core is very similar. (For example, a suite of Phoenix LiveView apps that all use TailwindCSS.)

Here’s how it works:

  1. You build your entire portfolio of apps in a single, “vanilla” Elixir app. (No “umbrella” or “poncho” setup.) You can generate this “Base Project” with mix new, mix phx.new, etc.
  2. You use Uniform’s “blueprint” DSL to set up “base files” and mix dependencies that are required for every app.
  3. You “eject” each app into its own completely separate codebase using mix uniform.eject. The ejected codebase contains the exact project structure you need, with only the code relevant to that app.
  4. You deploy each app using these ejected codebases.
  5. (Recommended) You automate updating ejected codebases via CI, (with mix uniform.eject) so that they basically “update themselves”.

The sales pitch

When you embrace the Uniform approach, it can feel a bit like magic.

  • Security defect in all 10 of the apps you maintain? Fix it in your Base Project and :magic_wand: poof – it’s fixed everywhere.
  • Need to quickly prototype a new app? mix uniform.gen.app my_app and you’re off to the races. No need to set up your suite of common tools for the umpteenth time. (Re-running generators, adding configuration, etc.)
  • Have a private library in one app that you want to use in another? Modify a couple lines of Uniform configuration and it’s instantly available.
  • Want to update some Hex deps across a dozen apps? Update them in your Base Project and they’re updated everywhere.

Uniform tries to lower the amount of effort required for developers to get stuff done. It automates away the manual work needed to keep your codebases “uniform” – in total sync. (But only in the ways you prefer them to be.)

Request for feedback

We know this approach is unconventional to say the least. But we’ve been quietly iterating on it, and it’s working pretty well for us!

We’re very curious what the community at large thinks about this approach.

Links

Click here for the docs and guides.

The code snippets in the Setting up a Phoenix project guide show what it looks like to configure Uniform for a “real” project.

https://github.com/ucbi/uniform

Showing Posts 1 to 10

halostatue

halostatue

This looks really useful, and might be interesting to adapt to make it easier to eject into umbrella apps (one of the systems that I’m working on has client-specific modules).

If I might suggest, an example ejectable repo would be useful to better understand how Uniform works, though.

paulstatezny

paulstatezny OP

@halostatue Thanks for your input! Great point about an example repo. That’s next on the list. :slight_smile:

Also, great to know there’s potential demand to make it work with umbrella apps. For your scenario, how much granularity would you need? Is an “all or none” approach sufficient? (Either an app is shipped with all the files in an OTP app, or it’s not.) Or would you need to conditionally exclude certain files for certain apps?

funk

funk

Looks great!

halostatue

halostatue

I’m not entirely sure what we’d want. The class of apps that we would “eject” are fairly template-able (at least in the beginning), so our primary needs could probably be met if we bothered with a standard template from a repo…but having something that lets us sync certain dependencies across would also be useful.

paulstatezny

paulstatezny OP

Hmm, so are we talking white labeling? Or totally separate apps that just share a bunch of boilerplate and some identical features?

We didn’t build this for white labeling, but it would probably work really well for that.

cmo

cmo

Do they all share the same assets folder?

paulstatezny

paulstatezny OP

@cmo That’s up to you. You can configure/tailor it to mostly whatever your setup needs.

If you always want to include everything from assets, use cp_r. (Which is named after File.cp_r and running cp -r on the command line.)

base_files do
  cp_r "assets"
end

If you want to only eject certain files in assets depending on the app, maybe read this part of the Setting up a Phoenix project guide. Here’s a code snippet from there.

base_files do
  file "assets/#{app.name.underscore}/**/*.{js,ts}"
end

Which would eject all files in assets/my_app_name or its subdirectories that end in .js or .ts

All the tools at your disposal are explained in the docs for Blueprint. Most importantly, the base_files macro.

halostatue

halostatue

The latter, not white labelling, although that would be an interesting use case for other purposes.

We have a concept of a “client adapter module”, which starts from the same definition, but quickly gets customized to adapt to external client systems and data structures. There’s a lot of shared code within that, though.

paulstatezny

paulstatezny OP

@halostatue That sounds like it fits perfectly into Uniform’s model.

Are you currently using private Hex packages for that shared code? Copy-pasting it across codebases? Something else?

Feel free to hit me up on Elixir Slack (@paulstatezny) if you want to talk about specifics that you’re not comfortable sharing here. I’d be happy to walk you through a potential setup that fits your needs.

halostatue

halostatue

The current code is…ad hoc and within the umbrella right now. What we’d be looking at retrofitting with Umbrella would be the management of those adapter submodules. I’m thinking we‘d have apps/adapter_template and then somehow do mix uniform.eject --umbrella to know it would be ejecting into the umbrella rather than to a new repo / package. There’s some other bits that would be good (and maybe Uniform could detect).

As I said, though, I’m not even quite sure what it is that we want, and we’ve got a few other overdue upgrade tasks that we’re working through now so we probably won’t be looking at this for a few weeks.

Where Next? Top

Trending in Announcing Top

bluzky
You may know https://ui.shadcn.com/, a UI component library for React. I really love it’s design style and components. I’ve built some co...
387 15136 120
New
woylie
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries. offset-based pagination with...
New
restlessronin
The repo is at GitHub - cyberchitta/openai_ex: Community maintained Elixir library for OpenAI API · GitHub. Docs are at OpenaiEx User Gu...
152 11030 135
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
shahryarjb
The Chelekom project is a library of Phoenix and LiveView components generated via Mix tasks to fit developer needs seamlessly. One of i...
New
woylie
Phoenix components for pagination, sortable tables and filter forms with Flop and (optionally) Ecto. pagination cursor pagination sorta...
New
kip
Please say hi to a new lib, Astro that aims to deliver easy-to-consume astronomy calculations of practical use. For now it only calculat...
New

Other Trending Topics Top

akoutmos
@hugobarauna and I (Alex Koutmos) have been hard at work on writing a book on Nerves that takes you from simply blinking LEDs to building...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
alexslade
Fly’s CEO posted this recently - Turn And Face The Strange · The Fly Blog It says that Fly is going all-in on sprites, which is a worry ...
New
bartblast
Hey folks, I just published a post about Hologram’s funding and where the project goes next - the short version: Curiosum as Main Spons...
New
Herve37
We’re evaluating API mocking tools for OpenAPI-based projects and would love to hear what other teams are using. We’re particularly inte...
New
mudasobwa
I am seeing a lot of aplications of Argumentum ad Vericundiam in software discussions. They do link some piece of writing and point us to...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews