Add a module
Create a new package that plugs into Monark, with its own procedures, events and pages. Decide its tier first: extended for a business feature, core only for infrastructure every deployment needs. See Architecture for what each tier may depend on.
- Scaffold the package; never build the folders by hand:
This createspnpm gen:module <name> --tier extended pnpm install pnpm genpackages/<name>with/server,/clientand/contractsentry points and an empty router, and adds the module tomodules.manifest.ts. - Add procedures to the
<name>Routerinsrc/server/index.ts. Validate every input with zod, and paginate every list (seelistDataRecordsinpackages/data-models/src/server/data.ts). - Decide, for each platform system, whether the module uses it, and wire what applies:
- Register permissions for every write.
- Emit a domain event for every state change.
- Send a notification when a person should hear about something.
- Put a feature behind a flag if it ships in stages.
- Call each
register…()helper once inservices/api/src/server.ts, in the block for its kind, next to the existing calls. - If the module needs tables, change the database schema in its own fragment.
- If it has a page, add it under
services/web/src/app/(authed)/<name>/, add an entry toservices/web/src/config/primary-nav.ts, and addappBar.primaryNav.items.<name>to every message catalog. - Write
packages/<name>/README.md(copy the sections ofpackages/rbac/README.md), write tests including an integration suite, and add a changelog fragment underchangelog.d/. - Run the gate:
pnpm agent gatecheck:tiersfails if an extended module imports another extended module;check:modulesfails without the README,contracts/events.tsor the integration suite.
Good to know:
- Rerun
pnpm genwhenever you changecontracts/events.tsor the router. Never edit the generated files. - Other packages import only
@monark/<name>/server,/clientor/contracts; anything else is private.
Next: Register permissions