I've been able to achieve this by relying on TypeScript, a 4-layer architecture (UseCase => App => Product => Target) and dependency injection.
This mechanism allows me to use whatever tech stack I want, provided the good adapters are developed. For instance, I have pre-built ones : node express (server), next.js (server), node hono (server in alpha), node parseArgs (CLI), node stricli (CLI), react-web-pure (web with no CSS), react-native (mobile), node mcp server (anthropic MCP in alpha), etc.
The same goes with data storage : Postgres, SQLite, a txt file, whatever.
It also comes with auto testing and auto documentation.
Did I reinvent the wheel ? Probably on some aspects. Is it too much abstraction ? Probably as well. But I like the idea of modularity and portability.
That's why it's not made for everyone, nor all types of projects.
If you like testing new stuff, give it a try and feel free to ping me if needed, I'd love to help.
I'm aware the documentation is not state of the art yet. I wanted to focus on the "Getting Started" Guide to give a quick overview instead of going to deeply into the details.
Best,
I feel like you could describe the abstractions you built in more detail. When I read the explanation for what the 'UseCase', 'App', 'Product' and 'Target' were, it wasn't clear how each of those translates to TypeScript. My guess is that 'UseCase' and 'App' would be like Classes, if you're modeling your program in an OOP way? The 'Product' seems like it would be the TypeScript project itself, with the package.json, source code and all of that.
I would rethink how you named the 'App' layer. The examples given ('auth', 'accounting', etc.) are not necessarily what I would call an 'app'.
As you introduce names and concepts for things in your library, I recommend trying to keep the cognitive load as low as possible. It seems like there are a very high amount of high-level concepts and implementation details like types, functions, etc. that 1. are specific/unique to libmodulor and 2. you need to learn before you can start actually building your application, from looking at the examples. The barrier to give it a try in a side project seems really high.
Building things is cool regardless :) I'm happy that you built something it's useful to you and that you got to share here.
That's a fair point. I will add more details on how each of these notions translates to TypeScript. Quickly :
> I would rethink how you named the 'App' layerI'm not a huge fan of this name either, but couldn't come up with something better at this time. `Module` seemed to broad to me. Although the notion is not totally clear to you, do you have any ideas in mind ?
I agree that it's not as straightforward as other solutions at this moment. I'll keep working and improving this to reduce the time needed to get started.
It includes a simple react-native target to show how to do it. To make things easier to understand, I've also revamped the documentation, added a Guide to create your own target and enhanced the Tutorial with a RN target.
Finally, I've added the Tutorial code in the repo for whoever wants to browse it without necessarily performing all the steps.
Thanks a lot again for your feedback. My email is open :)
But I’m still a bit confused on what the project actually “is”. I see you have an architecture and I’m using ts to define the interface between those 4 types of components. But let’s say I have a react-native target: what am I expressing in that interface? A cli which can build/deploy that interface? Each ui screen in that rn app (rn login, rn add contact)? Or all of the api endpoints in the web target which gets called by the rn target?
In the readme, I would focus a bit less on the UML part, and a bit more on the “if I have a webapp and a mobile app, with auth and crud for contacts, here’s what you’d need”
Let's say you want to create a product with auth and crud for contacts. You'll have a SignInUCD, a CreateContactUCD, a AddPhoneNumberToContactUCD, etc.
As you said, your react-native target will define the UI screens. You are free to design them the way you want as the library does not make any assumptions about the UI/UX. In every screen where you want to "inject" a use case, you'll use the `useUC` hook and `<UCPanel uc={uc} />` (see https://github.com/c100k/libmodulor/tree/master/dist/esm/tar...). See also https://github.com/c100k/libmodulor/blob/master/docs/getting.... It explains for web, but the mechanics are the same.
Since react-native expects `<View>`, `<Text>` and not `<div>`, etc. you'll also need to define your "design system", like it's been done here for example : https://github.com/c100k/libmodulor/tree/master/dist/esm/tar.... Basically, you need to define how you want a use case form to be displayed, etc. When in web we rely on `<input>`, in react-native we'll rely on `<TextInput>`. And of course, according to the data type, you can display a specific form control.
I realize it's super hard to explain and I'm not clear enough but hopefully I'll find the best way to express it.
There is obviously some cost to expressing the interface between the product/target/usecase. What exact benefit is that cost getting me? do i know that if i expose a certain use case in one target then i have to explicitly decide if i'm going to expose (or not expose) it in a different target, which helps me get consistency/governance between my app as it grows? does it help me "integration test" by application in isolation, in a "similar" way that pact [2] helps with integration testing microservices? (ex: the mobile app relies on X input, but from the ts interfaces, the tool can detect that the web-api is no longer defining an output for that api. if so, is this on the /api/v1/resource level? the openapi schema for a json body response level?). do i get a mono-build-system, where everything flows together and i just say "libmodulor build" and "libmodulor deploy" and I'm good to go?
said in another way: many of the people on HN have a backend api, a react SPA, and a mobile app. what types of problems do i have now which libmodulor solves?
[1] https://ui.shadcn.com/docs/components/dialog [2] https://pact.io/
It might help you implement some of these ideas
I build something similar (vramework.dev), actually on my way now to give a talk on it
Got a presentation for it at presentation.vramework.dev if anyone is interested
Also abstracts away the idea of an eventbus which is pretty critical in any Websocket deployment.
It doesn’t use Websocket directly via Vercel, but would work if you use nextjs by providing it a http server and also providing that server to ws
Can get this to work, but I’m pretty curious why you think this is a game changer? Thanks!
It’s used in three companies so far, but the new productised (via the cli) version is still in development / qa stages
There is one company that has been using it for over four years tho! Just checked in and seems to be working solid
Deleted Comment
I apologise for being off topic, but I really want “an opinionated X” to stop having some kind of positive connotation to junior devs.
In my case, I'm using the word because the library defines a set of rules and conventions to follow. They are indeed based on my experience.
Are they perfect ? Probably not. And I'm totally open to review them if I missed things. That's how we all learn. Like any model (in a mathematical way), it is an approximation of the actual problem.
I think it’s misunderstanding the angst of knowledgeable people’s frustration with the world, by trying to emulate the frustration without having the actual knowledge or experience.
Extremely immature and "I'm an asshole and I'm making it your problem" behavior
Deleted Comment