Ship with less glue
Add capabilities through one application model instead of wiring every package by hand.
Add features, choose providers and evolve your architecture without turning every decision into custom integration work.
From the docs
The same typed primitives connect contracts, implementations, lifecycle and application configuration.
import { InterfaceFunction } from
"@antelopejs/interface-core";
export const sendEmail = InterfaceFunction<
(message: EmailMessage) => Promise<void>
>();
// Consumers call the capability.
await sendEmail({ to, subject, body });A small public boundary
Why Antelope
Get the flexibility of a modular architecture without spending your time building and maintaining the machinery around it.
Add capabilities through one application model instead of wiring every package by hand.
Select another compatible implementation while consumers keep the same interface.
Give each capability a clear boundary so changes stay close to what they affect.
Add modules as the product expands without reorganizing the whole application.
Use shared conventions so every team knows where a responsibility begins and ends.
Mix ecosystem packages with local modules for the parts that make your product unique.
Useful from the first feature
Clean boundaries should create options now—not only rescue the codebase before a rewrite. Antelope makes modularity practical throughout the product’s growth.
Choose only the capabilities the product needs today.
Introduce the next feature without spreading it across the codebase.
Use an ecosystem provider or keep a critical implementation in-house.
Evolve one implementation while its consumers keep a stable boundary.
Give teams clear capabilities they can understand and evolve.
Built for changing products
Start with the fastest path, add what the product proves it needs and change compatible providers without dragging that decision through the codebase.
Compose the capabilities needed for the first useful version.
modules: {
api: {
source: { type: "local",
path: "./modules/api" },
},
database: {
source: { type: "package",
package: "@antelopejs/mongodb",
version: "^1.2.0" },
},
}Extend the product through a module with a clear public boundary.
catalog/
├─ interface.ts
├─ module.ts
├─ config.ts
└─ tests/Select a compatible provider while consumers keep the same interface.
database: {
source: {
type: "package",
package: "@org/database-provider",
version: "^1.0.0",
},
}CLI workflow
Scaffold, compose, test and run the application from one predictable workflow.
ajs project initscaffold an applicationajs project devrun with module watchingajs project buildprepare a production buildajs project modules addadd a module sourceajs project modules listinspect application compositionajs project modules updateupdate configured modulesajs module initcreate a module boundaryajs module testrun local and published interface testsajs project dev --watchreload local modules in developmentEcosystem
Start with the capabilities your application needs and keep every implementation behind an explicit boundary.
Typed authentication and authorization capabilities.
auth-jwtDatabase interfaces with swappable provider modules.
mongodbrethinkdbTyped API contracts and HTTP controller primitives.
interface-apiLoad modules from packages, Git, local builds or local folders.
packagegitlocallocal-folderChoose room to evolve
Build the backend the product needs today, with boundaries that leave tomorrow’s decisions open.