Hey everyone!
I’m still working hard on Gland, and after a lot of refactoring and R&D, I’m excited to share some of the new developments. Gl...
For further actions, you may consider blocking this person and/or reporting abuse
Do we really need another new web framework?
It really depends on what you’re looking for. Express still "works," and NestJS still "works," so if those fit your needs, there's no reason to switch.
But whether we need a new framework or not comes down to what problems you're trying to solve. Gland isn't trying to replace NestJS it’s taking a different, fully event-driven approach that makes code more modular and flexible. If that resonates with your project’s needs, then it’s worth considering. If not, sticking with what already works is totally fine.
This is the proper response. Even if it is the millionth JavaScript framework it is worth the attempt. At best it becomes something popular at worst you learned a lot about the problems that frameworks are trying to solve.
I agree. every new project is an opportunity to learn and grow, even if it's as simple as a basic calculator. For me, even if Gland doesn't become a huge success, the process of building it, the challenges I’ve faced, and the research I've conducted are incredibly valuable. Every experience, including failures, contributes to future successes as long as we learn from them.
This one is unique due to its event driven nature
Short answer? Yes. Even thousands more, as long people are creating them in the name of innovation.
Not sure I understand this. You're raising an event users.read.server assuming that some channel is implementing it, but the raiser has no type info to know what the channel will return. Am I supposed to do just project wide searches for strings to figure things out?
Good question! Right now, Gland’s event system is highly dynamic, allowing you to emit events without strict type constraints. While this provides flexibility, as you pointed out, it can make tracking responses harder.
One of the planned improvements is to introduce better type safety for emitted events, ensuring that the caller knows exactly what to expect. This could involve a type mapping system that links events to expected return types, making event-driven logic more predictable.
I’ll definitely take a closer look at this and explore ways to improve type inference in Gland’s event-driven flow. Thanks for the feedback!
In technology I see a recycling of ideas. One technology claims an improvement then comes another with its own baggages. I like the dynamics but the big question is why has not humanity succeeded in bringing a better technology we can all agree on? Is it even possible? What is wrong with us?
The problem is not with us, but with our idea of progress. Perhaps progress does not mean reaching a final and perfect technology at all, but rather the same constant movement between ideas, tests and failures.
I like @m_mdy_m response but here's another perspective. Maybe the problem is just that humans can't remain fixed on one thing. They say change is nature and we die the moment we stop changing and improving.
If all humanity agrees to use one perfect framework then that eliminates variety and subsequently, change. There has to be options.
Nice work, liked the idea, I would suggest to go beyond controllers and give more concrete implementation to leverage ore advanced patterns and architectures like domain driven design and clean architecture, I think as framework if u give some guideline and specific patterns to leverage those architectures with the use of events it will be very awesome
Also we need to think how can we build a package that uses events for db interactions and managing transactions
One last thing, we can use this pattern to add extra functionality for saving all interactions happen on the server through events, for example controller emits to service and service emits to db then emits back controller then to channel, we can add one extra functionality that records those events so it can be very useful for logs and traces
Thanks for the great insights! I really like the idea of going beyond just controllers and providing structured guidelines for architectures like DDD and Clean Architecture. That’s definitely something worth exploring—especially how event-driven patterns can naturally fit into these architectures and enhance modularity and maintainability.
I've already been working extensively on this idea and actively exploring ways to integrate these principles into Gland. Additionally, I plan to release third-party modules for database interactions that seamlessly integrate with Gland’s event-driven approach. These modules will provide a clean, decoupled way to manage data without tightly coupling the database logic to the application’s core.
In the future, I will also publish detailed documentation and guidelines on how to build third-party extensions for Gland, ensuring that developers can easily create plugins and integrations that align with its architecture. Of course, this will come after Gland reaches a stable release.
I also love the suggestion about event-based logging and tracing. Implementing a system that tracks and records all emitted events could be incredibly useful for debugging, monitoring, and even replaying events for auditing purposes. This is definitely something I’ll be looking into as Gland evolves.
Really appreciate the feedback! If you have any concrete ideas, specific use cases, or even suggestions on how you'd like to see these features implemented, feel free to share—I’d love to refine Gland’s event-driven approach even further.
Hey!
This is very interesting approach 👍 with event driven framework, I feel like writing state-machines in the backend would fit nicely.
I have a thought about the ctx.emit. I feel like it should not return result of the channel's event handler (10). Emitter usually should not know or care who handled the event and listeners should act on their own behalf.
Typically, if original emitter needs data, some listener would emit a response event, which the original emitter would be listening to.
Thank you for your thoughtful comment! You’ve raised a really important point about how event-driven systems should work, and I completely agree with the idea that emitters shouldn’t necessarily care about who handles the event or how it’s handled. This is actually one of the core principles behind Gland’s design, and I’d love to explain how we’ve approached this.
In Gland, ctx.emit is designed to give developers flexibility. While it can return the result of the handler, it doesn’t have to. This is intentional because we want to support both scenarios:
When you need a response: Sometimes, you might want to ensure that an event has been handled before moving forward. For example, if you’re processing a payment, you might want to confirm that the payment was logged before proceeding. In this case, waiting for a response from the handler makes sense.
When you don’t need a response: In other cases, like sending a notification, you might not care about the result at all. Here, you can simply emit the event and let the listeners handle it independently.
This flexibility allows developers to choose the right approach for their specific use case. If you prefer a more decoupled workflow where the emitter doesn’t wait for a response, you can design your system so that listeners emit follow-up events, and the emitter listens for those if needed. This keeps the emitter completely unaware of who’s handling the event or how it’s being handled, which aligns with your suggestion.
For example, imagine a scenario where a user signs up:
user:signup
event.user:created
event.user:created
event and sends a welcome email.In this case, the emitter doesn’t need to know about the database or the email service. It just broadcasts the event, and the listeners handle the rest.
That said, I completely understand your concern about the emitter potentially becoming too involved in the handling process. This is something I’ll keep in mind for future updates. For example, we could introduce stronger type constraints or event-response contracts to make it clearer when and how responses should be used. This would help developers avoid unintended coupling while still maintaining the flexibility that Gland offers.
Thanks again for sharing your thoughts! Your feedback is incredibly valuable, and it’s exactly this kind of discussion that helps make Gland better. If you have more ideas or suggestions, I’d love to hear them!
There are many cases where you may care that the event was handled before you moved on to something else, you may not care who has handled the event, but you many care that it has been handled.
Thank you for highlighting that nuance! I completely agree—there are indeed many cases where you might need confirmation that an event was handled before moving on, even if you don't care who handled it. In Gland, we've intentionally designed ctx.emit to be flexible. You can simply emit an event without waiting for a response when that's all you need, or you can structure your workflow so that follow-up events or asynchronous callbacks provide the confirmation you require.
For instance, in scenarios where processing order is critical (like logging a payment or updating a user record), you can have a listener emit a follow-up event to signal that the handling is complete. This allows you to wait for confirmation without coupling your emitter to a specific handler. It’s all about letting you choose the approach that best fits your use case.
Time to reset the clock
Gland is a new event-driven JavaScript web framework inspired by NestJS and Angular. It features dependency injection, controllers, and modular channels instead of providers, making apps more scalable and flexible. Using an Event-Driven System (EDS), actions are triggered by events rather than direct responses, enhancing modularity. The framework is lightweight, with minimal dependencies. Gland is still evolving, and feedback or contributions are welcome to refine its approach! 🚀
What we really need is a new web language.
Good, Keep going. I'm also making my own Framework for web still not have done that much. 😅
Great idea! I see a lot of potential for microservices here. Breaking the code into asynchronous, event-driven modules can make it non-blocking and much more efficient, which really helps with the performance across services.
Ive been commercially using Blazor for web development for over 3 years now, the freedom of no javascript and all the tooling is amazing, also really fast and responsive. Its 2025 no need for such an old language as Javascript any more and crazy tooling and dependancies.
Did you try moostjs? moost.org
No! I did not try it. But now I looked at its documentation. I only saw controllers with packages named "event", but I didn't see any traces of eds in them. What is your eds implementation?
But I was attracted by your package @wooksjs/http-body. It's a good idea, maybe I'll try it.
I'm not quite sure what you mean behind "EDS" and what kind of "eds traces" you are looking for. But I can explain a few base concepts behind wooks/moost projects.
At the very core there is wooks project, which implements events lifecycle with support of "event context" and "router". So each hypothetical event can be defined via some route + handler. Within the handler an event context is available at any place via
useAsyncEventContext
composable (yes, wooks brings "composables" term from frontend like vue, which is pretty similar to react hooks, that's why it's called wooks (W-web, (h)ooks)).Wooks supports adapters that bridges generic wooks events handling pipeline with the specific events sources/targets. For instance
@wooksjs/event-http
is an adapter for http events, so basically an alternative for express and fastify etc.The next level of abstraction is covered by moost. That one brings nestjs-like decorators and wraps wooks and wooks adapters into moost+decorators. Basically you get pretty much nestjs experience but IMHO much less boilerplate and much easier event context handling and much easier custom decorators.
The package
@wooksjs/http-body
that you found interesting is just a set of composables for@wooksjs/event-http
. Those composables are wrapped into decorators within@moostjs/event-http
package.If you want to take a glance of how it is supposed to work all together, just run
npm create moost@latest
, selecthttp
project and answer "no" to all the additional questions (or whatever you like, actually).P.S. I think the workflow adapter for wooks/moost could be very close to what you're doing. And if you have a strong reason why events should be defined your way, I can create another adapter that would support Gland-like events. (you're welcome to contribute as well :) )
Thanks for breaking down how Moost and Wooks work – really cool to see how you’re handling events with composables and adapters. Let me try to explain how Gland’s event-driven system (EDS) works differently, because I think it’s a fun twist on traditional frameworks.
In Gland, controllers don’t directly return responses. Instead, they just fire off events, and separate "channels" pick up those events to do the actual work. It’s like splitting the "what happened" from the "what to do about it." like this:
The beauty here is that the controller doesn’t know (or care) how the user is fetched – it just announces that someone asked for a user. The channel handles the nitty-gritty details. Want to add caching later? Just add another channel listener – no need to touch the controller.
Why this approach?
read:server:error
example).And this isn’t limited to HTTP. The same pattern works for WebSockets, database changes, message queues, or anything else that emits events.
Your Moost/Wooks approach with composables looks super clean for HTTP workflows! Where I think Gland differs is treating all actions as events – even non-HTTP ones. For example, you could have channels that respond to database changes or external API calls using the same pattern.
users:event
,orders:created
, etc.), so they stay organized.Your adapter offer
That’s super generous! I’d love to explore how Gland’s event-first approach could work with Moost’s composable system. Maybe:
I’ll definitely play with
npm create moost@latest
this week – the HTTP body parsing decorators already gave me ideas for simplifying Gland’s validation pipes.Ok, I think I am getting your idea. Although it raises many questions in my mind, like
1. Multiple listeners
What if multiple classes defined as
@Channel('users')
and subscribed for@On('read:server')
?2. What about
providers
?In other words why not just using a
provider
concept likewhere
UsersProvider
is a provider for users that gets instantiated by DI and can be whatever you want.3. Context
What is
Context
type? Is it the same for all kind of events? If no, how is user supposed to ensure proper types?Speaking about wooks/moost
Well, not only for HTTP workflows as http adapter is just one of the adapters for event handling pipeline. You can write websocket or kafka adapter to handle websocket/kafka events in similar matter. Currently there are
cli
andworkflow
adapters that streamline event processing with no relation to http.In moost app I would solve the decoupling you're talking about via
provider
as described above.When you want to add caching and/or logging, you just apply interceptors to event handler:
An interceptor has an initialization phase and 3 optional hooks:
before
hook is triggered after the handler arguments are resolved but before handler is triggered.after
hook is triggered after the handler is processed (with no error)onError
hook is triggered if a handler raised an error. On each step interceptor can overtake or overwrite the response.Gland-like event processing
If you still want to just emit some event from the controller, it is also doable within moost framework.
gland
events@Channel
and@On
that would provide metadata for your adapterHere's how moost code could look like if you had
gland
adapter:As I mentioned earlier the
@moostjs/event-wf
adapter is very close to what you are doing, it is a custom event type that can be raised out of controller. Although it is not about channels, it is about the exact wf implementation.In any case, is it going to simplify seo related limitations with current frameworks? Nice project tho
SEO is a separate concern when it comes to backend frameworks like Gland, NestJS, Express, Koa, Fastify, and others. These frameworks primarily focus on server-side logic, and SEO optimization typically relates more to frontend rendering and how search engines crawl and index the content.
The main goal of Gland is to provide an event-driven and modular system, offering innovative ways to implement logic in backend applications. While SEO is important, it falls outside the scope of what Gland is designed to address.
For anyone who's used/using Kafka, would this make it easier to work with Kafka in some way?
"What? Again? This stupid country." -- M. Quimby.
Haha, I get it. "What? Again?" -- M. Quimby. But hey, sometimes a new approach can bring fresh perspectives! Gland’s fully event-driven design isn't just another NestJS clone, it’s a different way of thinking about how data flows. Check it out: Gland GitHub.
This has to be a joke.
why?
Is another framework really necessary?
dev.to/m__mdy__m/comment/2m57f
Do events have to be magic strings? Can they be typed somehow?
Cool ideas though!
yes you can