Modules overview
Adonia modules are domain slices the CLI copies into an AdonisJS host from the registry. Each module ships a service, typed contracts, and optional host stubs.
This page is the catalog for the bundled registry. It explains the difference between core packages and feature modules, how add copies files, and which modules depend on which.
Core packages versus feature modules
The registry splits packages into core (always present after init) and feature modules (you add them one at a time).
npx adonia init copies the core set into your host modules/ directory. Feature modules list their dependencies in module.jsonregistryDependencies. adonia add walks that graph and copies missing packages first.
| Name | Kind | Role |
|---|---|---|
api | Core | Shared envelopes, ApiService, ctx.respond, exception handler |
types | Core | Envelope and model TypeScript types |
constants | Core | Exception codes and controller success codes |
contracts | Core | Shared User / UserStore port |
auth | Feature | Registration, login, verification, password reset |
account | Feature | Profile, email change, password change, deletion |
notification | Feature | Multi-channel dispatcher with a host-owned registry |
creem | Feature | Creem checkout, portal, invoices, webhooks |
subscription | Feature | Subscription state synced from Creem webhooks |
Core packages types, constants, and contracts don't have their own pages. They're documented with api, because add api pulls them in automatically.
NOTE
adonia list prints every name in the resolved registry and marks which ones are already in adonia.jsoninstalled.
How add copies a module
Plain adonia add <name> copies the domain slice only: the service, contracts, events, options, and module.json under modules/<name>/. Host files stay out of the way until you ask for them.
Opt-in flags copy stubs into the host tree. The flags stack:
--with-adapterscopies Lucid/SDK adapters toapp/adapters/.--with-controllerscopies controllers and implies adapters.--with-validatorscopies Vine validators andproviders/.--with-models/--with-migrationscopy Lucid models and migrations.--with-routescopiesstart/routes/<name>.tsand the limiter example understart/. Pass--wire-routesto import that file fromstart/routes.ts.--with-stubscopies models, migrations, controllers, validators, providers, start files, and adapters. It does not copy routes. Pass--with-routesas well when you want the example router file.
--with-tests copies the module's unit tests under modules/<name>/tests/. Host integration specs listed in hostTests stay in the registry as a reference; they are not copied by this flag.
IMPORTANT
Adonis packages used by stubs (@adonisjs/mail, @adonisjs/drive, @adonisjs/limiter) are not stubbed with no-ops. add and check warn when a copied stub needs a package that is missing from package.json and print node ace add @adonisjs/<pkg>.
See the add command for the full flag list.
Dependency graph
Feature modules never copy in isolation when a dependency is missing. add expands registryDependencies and prints a plan such as api → types → constants → contracts → auth.
api (+ types, constants, contracts)
├── auth
│ └── account
├── notification
└── creem
└── subscriptionInstall in that order, or pass the leaf name and let the CLI pull parents. For example, adonia add account also installs api (and core) and auth if they aren't already in adonia.json.
Domain services versus host HTTP
Domain services return DTOs or void and throw ApiException. They don't wrap HTTP envelopes. Controllers in the host, or the optional stubs, call ApiService.prepareResponse / preparePaginatedResponse and ctx.respond.
Services that extend ApiService emit events through emitSafe. An event fires only when its name is listed in config/modules.ts under that module's emits array. add merges those names when the module declares events in module.json.
NotificationService is infrastructure, not a domain service. It doesn't extend ApiService and it doesn't emit domain events.
Shared user port
auth and account talk to a shared UserStore in #modules/contracts. Persistence, password hashing, and schema details stay in the host adapter. The Lucid adapter stub lives with auth; account reuses #adapters/lucid_user_store.
You must implement UserStore yourself if you skip --with-adapters.
Next steps
Pick a module and add it to a wired host:
- Finish getting started and host wiring if you haven't run
npx adonia init --wire. - Read
apiso you know the envelope and exception shape every other module uses. - Add a feature module, starting with
authornotification.