Why Xeno.JS?
Introduction
Section titled “Introduction”A TypeScript application rarely becomes difficult because of its first few features.
The complexity usually appears later.
As the application grows, business rules, databases, external services, authentication, validation, caching, background jobs, and transport concerns begin to interact.
At that point, the main challenge is no longer simply writing code.
It is keeping the architecture understandable as the codebase grows.
Xeno.JS exists to address that problem.
The problem is architectural complexity
Section titled “The problem is architectural complexity”A small application can often work well with a straightforward structure:
Request ↓Controller ↓Service ↓DatabaseAs the application grows, that structure can become harder to maintain.
A service may start handling business rules, database access, authorization, external APIs, logging, and validation at the same time.
Controllers can become responsible for more than transport.
Infrastructure concerns can leak into domain logic.
Dependencies can become difficult to see.
The architecture still exists, but much of it is implicit.
Xeno.JS takes a different approach:
Make the application architecture explicit.
Instead of relying on conventions scattered across the codebase, Xeno.JS provides explicit application-level primitives and boundaries.
Keep the application independent from the transport
Section titled “Keep the application independent from the transport”One of the main reasons for separating application architecture from transport is that the same application logic may be reached through different entry points.
For example:
┌── HTTP │ ├── CLI │ ├── Worker │ └── Other transport │ ▼ Xeno.JS Application │ ▼ DomainThe transport determines how the application is reached.
The application determines what the system does.
Keeping those concerns separate means application use cases do not need to be designed around a particular HTTP framework.
This allows an application to use frameworks such as Fastify, Express, or Hono without making them the architectural center of the application.
Make dependencies explicit
Section titled “Make dependencies explicit”As applications grow, dependency relationships become increasingly important.
A use case may depend on a repository.
A repository may depend on a database.
Another service may depend on an external API.
Authentication may depend on a token provider.
When these relationships are hidden inside framework mechanisms or constructed throughout the application, understanding the dependency graph becomes harder.
Xeno.JS makes dependency injection part of application composition.
The goal is simple:
Application │ ├── Use Case │ ├── Repository │ └── External Service │ └── InfrastructureThe dependencies are part of the architecture rather than an implementation detail scattered across the codebase.
Keep business logic separate from infrastructure
Section titled “Keep business logic separate from infrastructure”Business rules should not need to know whether data comes from PostgreSQL, an external API, a cache, or another implementation.
A growing application benefits from a clear distinction between:
Domain ↓Application ↓InfrastructureThe domain expresses business concepts and rules.
The application coordinates use cases.
Infrastructure provides concrete implementations.
Xeno.JS provides contracts and application primitives that help maintain these boundaries.
Treat application execution as an architectural concern
Section titled “Treat application execution as an architectural concern”A real application does more than execute a function.
A use case may need validation, authorization, logging, error handling, performance monitoring, idempotency, or other cross-cutting behavior.
Without a consistent execution model, these concerns can end up duplicated across controllers and services.
Xeno.JS provides commands, queries, and pipelines as part of its application model.
Conceptually:
Command / Query ↓ Pipeline ↓ Handler ↓ Application ResultThis makes cross-cutting execution part of the application architecture instead of something every feature needs to assemble independently.
Reduce framework coupling
Section titled “Reduce framework coupling”Frameworks are useful because they provide conventions and infrastructure.
The problem appears when application logic becomes dependent on those conventions.
When business logic, use cases, and domain concepts depend directly on a transport framework, changing that framework can become an architectural change rather than a transport change.
Xeno.JS is designed to keep the application layer independent from that choice.
That means the application can use:
FastifyExpressHonoCLIWorkeras entry points while keeping the application model underneath them.
One application model instead of many unrelated patterns
Section titled “One application model instead of many unrelated patterns”Large TypeScript applications often accumulate multiple architectural patterns over time.
One module may use services.
Another may use controllers.
Another may introduce a custom command bus.
Another may use a separate dependency injection solution.
Another may implement its own middleware pipeline.
Each individual choice can be reasonable.
The problem is the resulting system: developers have to understand many different ways of expressing application behavior.
Xeno.JS brings dependency injection, commands, queries, pipelines, context, modules, and application composition into one architectural model.
The goal is not to eliminate every architectural choice.
It is to provide a consistent foundation for those choices.
The Xeno.JS approach
Section titled “The Xeno.JS approach”The central idea can be summarized in one sentence:
Make application architecture explicit in code.
Xeno.JS provides a common foundation for defining:
- where application logic lives
- how dependencies are composed
- how use cases are executed
- how cross-cutting concerns are applied
- how domain and infrastructure remain separated
- how the application stays independent from its transport
The next page explains how these pieces fit together.
Next steps
Section titled “Next steps”Support Us
Section titled “Support Us”Xeno.JS is an MIT-licensed open source project. It can grow thanks to the support of these awesome people. If you’d like to join them, please read more at support section
