xndrjs is a TypeScript toolkit for teams that want Clean Architecture without over-engineering their codebase from day one, while leaving room to evolve as complexity grows.
It helps you keep the core of your system as independent as possible from React, Next.js, Angular, SvelteKit, backend frameworks, databases, queues, and other infrastructure details.
Frameworks stay useful entry points. Your domain stays the place where meaning, rules, and correctness live.
Architecture over frameworks
Clean Architecture starts from a simple idea: the core of your application should not depend on delivery mechanisms.
UI frameworks, runtimes, databases, and external services are adapters. They should plug into your system, not shape it.
xndrjs gives TypeScript projects small primitives for making this separation explicit instead of relying on custom solutions and discipline alone.
Domain modeling first
The domain model is where xndrjs is most opinionated, because it is often the most under-modeled part of a TypeScript application.
When values, invariants, transitions, and guarantees are explicit, the rest of the architecture becomes easier to organize.
xndrjs focuses on APIs that are both correct by architectural standards and ergonomic enough to use every day.
Meaningful boundaries
The toolkit defines orthogonal responsibilities that compose instead of getting tangled.
For example, domain modeling is split into:
validation -> what data is allowed (Validator)
representation -> what data can be trusted (shape, primitive)
behavior -> how data evolves (capabilities)
guarantees -> what additional conditions hold (proof)
This gives each concept a natural home and keeps business meaning out of controllers, components, handlers, and persistence code.
Correct by construction
Instead of scattering validation across the codebase, xndrjs makes it part of how data is created and transformed.
Once a value enters the system through a domain boundary, it is:
validated
immutable
safe to use
This removes entire classes of bugs and eliminates uncertainty about data correctness.
If you can create/transform it, it’s valid.
Adapters, not lock-in
xndrjs integrates with Zod, Valibot, AJV, OpenAPI, and other validation sources through adapters.
Your code depends on a small validation contract, not on a specific schema engine.
That lets each boundary use the tool that fits it best while the domain continues to speak in Email, User, Order, VerifiedUser, and named capabilities.
Beyond the domain
xndrjs also includes a small package for retryable async tasks. And there will be more.
But these areas are harder to capture with a large universal API, so the toolkit stays intentionally light there.
The goal is to provide useful primitives and clear guidance for integrating them into your own architecture, while keeping framework and infrastructure choices outside the core.