[data-reveal]{opacity:1!important;transform:none!important}
Antelope FrameworkOne model, across the ecosystem

Hexagonal architecture. Beyond your own code.

Keep your business logic behind explicit contracts. Bring ecosystem modules into the same model, and choose their implementations at the application boundary.

  • Explicit contracts
  • Replaceable implementations
  • Less integration plumbing

Follow the dependencies

Your dependencies should respect your boundaries.

You already separate ports from adapters in your own code. Antelope extends that model to the modules you install. Consumers depend on contracts, providers implement them, and the application selects which implementation to load.

Hexagonal architecture, in action

Payment providers · click to swap

  • Stripe adapter@example/payment-stripe
    Loaded
  • Mollie adapter@example/payment-mollie
    Compatible
  • Checkout adapter@example/payment-checkout
    Compatible

Your business logic

await charge(order)await sendEmail(message)no provider SDK
Contractinterface-payment
Contractinterface-email
AntelopeJS corereads antelope.config.tsloads @example/email-brevobinds it to interface-email

Change the adapter, not the consumer

Swap compatible implementations. Keep your consuming code.

  1. 01Implement
    Keep the same contract

    Build a second adapter that exports the same capability, with the behavior consumers expect.

    construct() · in each adapter
    // @example/payment-stripe
    ImplementInterface(
      await import("@example/interface-payment"),
      await import("./stripe"),
    );
     
    // @example/email-brevo
    ImplementInterface(
      await import("@example/interface-email"),
      await import("./brevo"),
    );
    
  2. 02Select
    Change application assembly

    Select the new provider package and supply its required configuration before running the application.

    antelope.config.ts · excerpt
    payment: {
      source: { type: "package",
        // Was: @example/payment-checkout
        package: "@example/payment-stripe" },
    },
    email: {
      source: { type: "package",
        // Was: @example/email-smtp
        package: "@example/email-brevo" },
    },
    
  3. 03VerifyUnchanged
    Leave the consumer alone

    Verify the new provider against the contract and your integration tests. The consumer keeps its original import and call.

    modules/checkout/place-order.ts · unchanged
    import { charge } from
      "@example/interface-payment";
    import { sendEmail } from
      "@example/interface-email";
     
    export async function place(order: Order) {
      await charge({
        amount: order.total,
        reference: order.id,
      });
      await sendEmail({
        to: order.email,
        subject: "Order confirmed",
      });
    }
    

A replacement must respect the same contract and its behavior, not just its types. Provider configuration, credentials and any data migrations remain your responsibility. Antelope supplies the binding mechanisms; your code must still respect the boundaries.

The framework, in code

From table to API. Typed end to end.

Follow one CRM module from its database table to its HTTP routes, its auth and the providers it plugs into. Every snippet uses the real AntelopeJS interfaces and decorators.

modules/crm/db/contact.tsts
import {
  CreationTime,
  Encrypted,
  EncryptionModifier,
  Field,
  Index,
  RegisterTable,
  Relation,
  Table,
  UpdateTime,
} from "@antelopejs/interface-database-decorators";
import { Company } from "./company";

@RegisterTable("crm_contacts", "crm")
export class Contact extends Table.with(EncryptionModifier) {
  @Field("string") declare _id: string;
  @Field("string") declare name: string;
  @Index() @Field("string") declare email: string;
  @Index() @Field("string") declare status: "lead" | "customer";

  @Field("string")
  @Relation({ to: () => Company })
  declare companyId?: string;

  @Encrypted({ secretKey: process.env.CRM_SECRET! })
  @Field("string")
  declare phone?: string;

  @CreationTime() @Index() @Field("date") declare createdAt: Date;
  @UpdateTime() @Index() @Field("date") declare updatedAt: Date;
}
Your schema is TypeScript. Decorators describe columns, indexes, relations, encryption and timestamps; every table gets an implicit _id key.

Beyond the example

The same model in the ecosystem you assemble.

This is not only a folder structure for your application. Antelope publishes interface packages and provider modules that participate in the same contract model. Check the interfaces and versions each module supports before choosing an implementation.

Authentication

Use the auth-jwt module for authentication capabilities behind the ecosystem’s interfaces.

auth-jwt

Database providers

Explore MongoDB and RethinkDB modules. Compare their supported contracts and migration requirements, not just their package names.

mongodbrethinkdb

API contracts

Share typed API contracts and HTTP controller primitives through the API interface package.

interface-api

Your own modules

Keep a critical adapter in-house. Compose local modules alongside packages and Git sources in the same application.

localpackagegit

Less plumbing, more implementation

Keep the architecture. Stop rebuilding its machinery.

Antelope provides interface binding, module lifecycle and application assembly. The CLI brings module creation, composition and testing into one workflow, so you can focus on the contracts and business behavior that matter to your product.

acme-shop · ajs
And moreajs project modules updateajs project modules removeajs project logging setajs config setajs pluginsajs updateEvery command in the cheat sheet

Run it anywhere

Your app. Your infrastructure.

An AntelopeJS app is a Node.js project. Run it on your own servers, or push it to AntelopeJS Cloud, which reads your antelope.config.ts to provision what it needs.

Deploy option A

Self-host

Your infra, your rules

Deploy option B

AntelopeJS Cloud

Managed hosting

Your AntelopeJS app

Modules, interfaces, providers

Framework · open source

Your next module

Start with a contract. Keep your options open.

Build your first Antelope module, then bring ecosystem implementations into the same architecture. Your business code depends on the capability, not the provider you choose today.