GenericJam

GenericJam

Proposed Plugin System for Mob - BEAM Mobile Framework

Plugin System for Mob

Mob is growing by leaps and bounds! I realize now we will not be able to accommodate all the functionality people would want in the main framework itself. It is designed to be extensible. The build system should be able to handle plugins now.

The idea for the plugins is similar to React Native plugins. This is more than coincidence because React Native and Mob have similar architectures, with Mob being a bit simpler. The native code in Kotlin/Java, Swift/ObjC, C is likely very close to what Mob would need. The main difference is the logic is in Elixir, not JS and the distribution is hex.

One of the upsides of the similarity is we could migrate many of these to Mob which would be a big boost to the ecosystem. There are ~150-200 that land in this ‘native heavy’ category that would be very attractive to use such as date pickers, etc. that translate to native elements.

So you’d have the Android native code in /android and the iOS native code in /ios. You could have one sided plugins that only land on one platform.

I’ve brainstormed a pretty extensive document on this with Claude. Here’s the shorter summary:

Mob Plugins: Manifest Schema Proposal

Three design choices anchor this proposal. First, the manifest is data, not code — mob_dev reads priv/mob_plugin.exs at compile time rather than having plugins call register_plugin at runtime. Static, inspectable, validatable; closer to mix.exs than to Phoenix’s runtime route registration. Second, activation is explicit and separate from installation, borrowed from how iOS entitlements work: a framework supporting capability X doesn’t mean your app uses X without explicit declaration. This mitigates supply-chain risk by ensuring mix deps.get can never silently modify your app’s permission set. Third, the schema scales with plugin tier rather than being exhaustive everywhere — small plugins write three fields, large plugins write a dozen sections, and the shape of the manifest doesn’t make trivial plugins look heavy. Underlying all of this: Hex is the substrate, so versioning, dep resolution, security posture, and hexdocs publication come free, and static linking is required (no dlopen) to stay App-Store-compatible.

The schema spans five tiers. Tier-0 is a pure Elixir Hex package needing no manifest at all. Tier-1 adds NIFs and per-platform native sources — Kotlin bridge files, Swift files, Gradle deps, frameworks, permissions, plist keys. Tier-2 introduces :ui_components for new render-tree node types with paired SwiftUI views and Composables. Tier-3 layers on :screens, :migrations, and :assets for plugins that ship entire mini-applications. Tier-4 adds :lifecycle, :settings, and :notifications for embedded sub-apps with supervised children, persisted user settings, and push notification handlers. Required top-level fields are just :name, :mob_version, and :plugin_spec_version; everything else is independently optional.

Installation is deliberately two-step. Adding a plugin to deps and running mix deps.get makes it resolvable but does not merge native code, permissions, or plist keys. Activation requires an explicit entry in config :mob, :plugins in mob.exs. mob_dev prints the diff at compile time so users see exactly what’s being added — permission set changes are never silent. mix mob.add_plugin wraps both steps plus optional interactive setup prompts where plugin authors guide tier-3/4 integration (e.g., “Register MobChatKit.MessageListScreen in your App.navigation/1?”). The standard flow always works; the convenience command is not a required entry point.

Validation runs at two stages and fails loud. mix mob.validate_plugin checks the plugin in isolation: paths exist, files parse, version requirements are valid, and single-platform UI components are flagged as warnings (the #1 React Native plugin pain point). mob_dev then re-validates at compile time across all activated plugins — no duplicate component atoms, no colliding screen routes, no migration namespace collisions, all activated plugins present in deps. Hot-pushability is computed automatically from which sections are populated: tier-0 hot-pushes fully, tiers 1-2 require a native rebuild, tiers 3-4 are partial (Elixir hot-pushes; native does not). Forward compatibility is handled via :plugin_spec_version, letting the schema evolve without breaking existing plugins — bump the integer, support both versions in mob_dev for a migration window, deprecate.

Any comments or questions are appreciated.

Where Next?

Popular in RFCs Top

dergraf
Hey everyone! :waving_hand: I’ve been working on a side project for the last 4 months that I’m excited to share—it’s called ProxyConf! P...
New
bartblast
:test_tube: Could use a hand testing something. Just landed a protocol pruning enhancement - the compiler now drops protocol implementati...
New
UlrikHD
I’ve been wanting to write a library for the lemmy API so that I can port some of my scripts over to elixir. For those unfamiliar with le...
New
ca1989
Hi all, this week I played a bit with Phoenix and Elm. I ended up with this POC: https://github.com/carlotm/elmex The repository cont...
New
puemos
Hey everyone :waving_hand: Code: GitHub - puemos/overbooked: Overbooked is a self-hosted flexible workplace platform for indie co-wor...
New
wingyplus
Hi, I start working on the fork version of Elixir GRPC. What I’ve done is the past few days: Support Elixir 1.11+ Support OTP 23+ OTP...
New
wingyplus
I just publish a library called redoc_ui_plug | Hex. The library renders Redoc UI from the openapi specification url. I used this library...
New
Billzabob
Hello! I have an idea for an Elixir library I’d like to work on, but wanted to get some thoughts from the community first. It would allo...
New
weakwire
Hello people, Big fan of elixir & phoenix LiveView. While designing LiveView applications I use LiveComponent extensively. Issue-I...
New
benlime
In the last couple of days I was playing around with LiveView, function components and animations. I ended up with a little prototype whi...
New

Other popular topics Top

danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29377 241
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43622 214
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 36128 110
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

We're in Beta

About us Mission Statement