Modules
Modules are reusable packages of Stack9 resources (entities, screens, queries, automations, etc.) that can be shared across multiple Stack9 applications. They enable code reuse, standardization, and rapid development by packaging common functionality into distributable NPM packages.
What are Modules?
Modules are NPM packages that bundle:
- Entities - Data models
- Screens - UI configurations
- Query Library - Data access queries
- Automations - Workflow definitions
- Action Types - Custom business logic
- Entity Hooks - Validation logic
- Connectors - External service integrations
- Apps - Navigation structures
When you install a module, Stack9 automatically:
- ✅ Registers all entities
- ✅ Makes screens available
- ✅ Loads queries into the library
- ✅ Activates automations
- ✅ Registers action types and hooks
- ✅ Configures connectors
Why Use Modules?
Without Modules (Copy-Paste Approach)
# Manually copy files between projects
cp -r project-a/src/entities/user.json project-b/src/entities/
cp -r project-a/src/screens/user-list.json project-b/src/screens/
cp -r project-a/src/query-library/get-user.json project-b/src/query-library/
# ... copy 50+ more files
# Now maintain duplicates across projects
With Modules (NPM Package Approach)
# Install module
npm install @company/user-management-module
# Use immediately - no configuration needed
# All entities, screens, queries automatically available
Benefits:
- ✅ DRY: Write once, use everywhere
- ✅ Versioned: Semantic versioning for changes
- ✅ Tested: Test once, trust everywhere
- ✅ Maintainable: Update in one place
- ✅ Shareable: Distribute via NPM registry
Core Modules
Stack9 provides essential core modules:
stack9-core-module
The foundational module required by all Stack9 applications.
{
"name": "@april9/stack9-core-module",
"version": "5.0.0",
"description": "Stack9 core module"
}
Provides:
- Core entities (User, UserGroup, Media, etc.)
- Settings app
- User management screens
- System administration screens
- Core queries
- Base automations
stack9-email-module
Email functionality and transactional email management.
{
"name": "@april9au/stack9-email-module",
"version": "1.1.0",
"dependencies": {
"@april9/stack9-core-module": "5.0.0",
"@april9/stack9-sdk": "5.0.0"
}
}
Provides:
- Email template entities
- Email log entities
- Email sending automations
- Template management screens
- Email connector
stack9-marketing-module
Marketing automation and campaign management.
{
"name": "@april9au/stack9-marketing-module",
"version": "1.0.0",
"dependencies": {
"@april9/stack9-core-module": "5.0.0"
}
}
Provides:
- Campaign entities
- Lead management
- Marketing automation workflows
- Campaign analytics screens
stack9-pages-module
CMS functionality for managing web pages.
{
"name": "@april9au/stack9-pages-module",
"version": "1.0.0",
"dependencies": {
"@april9/stack9-core-module": "5.0.0"
}
}
Provides:
- Page entities
- Content management
- Page builder screens
- Publishing workflows
Module Structure
A Stack9 module follows this directory structure:
my-module/
├── package.json # NPM package configuration
├── tsconfig.json # TypeScript configuration
├── src/
│ ├── index.ts # Module entry point
│ ├── app.json # Module configuration
│ ├── entities/
│ │ ├── custom/ # Custom entities
│ │ │ ├── product.json
│ │ │ └── category.json
│ │ └── native/ # Native Stack9 entities
│ ├── screens/
│ │ ├── product-list.json
│ │ └── product-detail.json
│ ├── query-library/
│ │ ├── get-products.json
│ │ └── get-categories.json
│ ├── automations/
│ │ └── when-product-created.json
│ ├── action-types/
│ │ └── syncProductData.ts
│ ├── entity-hooks/
│ │ └── product.vat.ts
│ ├── connectors/
│ │ └── product-api.json
│ ├── apps/
│ │ └── products.json
│ ├── models/
│ │ └── stack9/ # Generated TypeScript models
│ └── utils/ # Utility functions
└── dist/ # Compiled output
├── index.js
├── index.d.ts
└── [all compiled resources]
Creating a Module
Step 1: Initialize Package
{
"name": "@company/product-management-module",
"version": "1.0.0",
"description": "Product management module",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist/**"
],
"dependencies": {
"@april9/stack9-core-module": "^5.0.0",
"@april9/stack9-sdk": "^5.0.0",
"knex": "^2.5.1",
"runtypes": "^6.7.0"
},
"devDependencies": {
"@april9/tsconfig": "^5.0.0",
"typescript": "^5.6.3",
"tsup": "^6.2.2"
},
"scripts": {
"build": "tsup",
"dev": "tsup --watch"
}
}
Step 2: Create app.json
{
"name": "Product Management Module",
"dateFormat": "DD-MM-YYYY",
"timeFormat": "h:mm a",
"timezone": "UTC",
"apps": [],
"cronJobs": [],
"mqHandlers": []
}
Step 3: Add Resources
Create entities, screens, queries as you normally would in a Stack9 app:
src/
├── entities/custom/
│ └── product.json
├── screens/
│ └── product-list.json
├── query-library/
│ └── get-products.json
└── apps/
└── products.json
Step 4: Build Module
# Build TypeScript and bundle resources
npm run build
# Output in dist/
dist/
├── entities/custom/product.json
├── screens/product-list.json
├── query-library/get-products.json
└── index.js
Step 5: Publish Module
# Publish to NPM registry
npm publish
# Or private registry
npm publish --registry=https://npm.pkg.github.com
Installing Modules
Install from NPM
npm install @company/product-management-module
Add to package.json
{
"dependencies": {
"@april9/stack9-core-module": "^5.0.0",
"@company/product-management-module": "^1.0.0"
}
}
Stack9 Auto-Discovery
Stack9 automatically discovers and loads modules from node_modules/:
// No configuration needed!
// Stack9 scans node_modules for *-module packages
// Automatically loads all resources
Module Configuration
Module Metadata (app.json)
{
"name": "Product Management",
"dateFormat": "DD/MM/YYYY",
"timeFormat": "HH:mm",
"timezone": "Australia/Sydney",
"logo": "https://example.com/logo.png",
"brandColor": "#3498db",
"theme": "light",
"apps": [
{
"name": "Products",
"key": "products",
"icon": "InboxOutlined"
}
],
"cronJobs": [
{
"name": "Sync products daily",
"schedule": "0 2 * * *",
"automationKey": "sync_products"
}
],
"mqHandlers": [
{
"queue": "process_product",
"actionTypeKey": "process_product_queue"
}
]
}
Module Dependencies
Modules can depend on other modules:
{
"name": "@company/advanced-products-module",
"dependencies": {
"@april9/stack9-core-module": "^5.0.0",
"@company/product-management-module": "^1.0.0",
"@company/inventory-module": "^2.0.0"
}
}
Stack9 resolves dependencies and loads in correct order.
Module Versioning
Follow semantic versioning:
{
"version": "1.2.3"
// MAJOR.MINOR.PATCH
// 1 = Breaking changes
// 2 = New features (backward compatible)
// 3 = Bug fixes
}
Version Ranges
{
"dependencies": {
"@company/product-module": "^1.0.0", // >=1.0.0 <2.0.0
"@company/inventory-module": "~1.2.0", // >=1.2.0 <1.3.0
"@company/shipping-module": "1.5.0" // Exact version
}
}
Module Best Practices
1. Single Responsibility
// ✅ Good - Focused module
{
"name": "@company/product-management-module",
"description": "Product catalog and management"
}
// ❌ Bad - Too broad
{
"name": "@company/everything-module",
"description": "Products, orders, customers, inventory, shipping..."
}
2. Clear Dependencies
// ✅ Good - Explicit dependencies
{
"dependencies": {
"@april9/stack9-core-module": "^5.0.0",
"@company/base-entities-module": "^1.0.0"
},
"peerDependencies": {
"@april9/stack9-sdk": "^5.0.0"
}
}
// ❌ Bad - Missing dependencies
{
"dependencies": {
// Assumes stack9-core-module is installed
}
}
3. Semantic Versioning
# Patch release (bug fixes)
1.0.0 → 1.0.1
# Minor release (new features, backward compatible)
1.0.1 → 1.1.0
# Major release (breaking changes)
1.1.0 → 2.0.0
4. Document Breaking Changes
# Changelog
## v2.0.0 (BREAKING)
- Renamed `Product` entity to `CatalogProduct`
- Changed query `getproducts` to require `category_id` parameter
- Removed deprecated `ProductCategory` entity
## v1.5.0
- Added `ProductReview` entity
- New query: `getproductreviews`
5. Test Before Publishing
# Link locally for testing
cd my-module
npm link
cd my-stack9-app
npm link @company/my-module
# Test in your app
npm start
# Unlink when done
npm unlink @company/my-module
6. Use Namespace Packages
# ✅ Good - Namespaced
@company/product-module
@company/inventory-module
@company/shipping-module
# ❌ Bad - Global namespace collision risk
product-module # Could conflict with other packages
inventory # Very generic name
Module Examples
Simple Module: Product Catalog
@company/product-catalog-module/
├── package.json
├── src/
│ ├── entities/custom/
│ │ ├── product.json
│ │ └── category.json
│ ├── screens/
│ │ ├── product-list.json
│ │ ├── product-detail.json
│ │ └── category-list.json
│ ├── query-library/
│ │ ├── get-products.json
│ │ └── get-categories.json
│ └── apps/
│ └── products.json
Complex Module: E-commerce
@company/ecommerce-module/
├── package.json
├── src/
│ ├── entities/custom/
│ │ ├── product.json
│ │ ├── cart.json
│ │ ├── order.json
│ │ ├── payment.json
│ │ └── shipping.json
│ ├── screens/
│ │ ├── product-catalog.json
│ │ ├── shopping-cart.json
│ │ ├── checkout.json
│ │ └── order-history.json
│ ├── automations/
│ │ ├── when-order-created.json
│ │ ├── when-payment-completed.json
│ │ └── when-order-shipped.json
│ ├── action-types/
│ │ ├── processPayment.ts
│ │ ├── calculateShipping.ts
│ │ └── sendOrderConfirmation.ts
│ ├── entity-hooks/
│ │ ├── order.vat.ts
│ │ └── payment.vat.ts
│ └── connectors/
│ ├── payment-gateway.json
│ └── shipping-api.json
Troubleshooting
Module Not Loading
Problem: Module installed but resources not appearing
Solutions:
- Verify package is in
node_modules/ - Check module name ends with
-module - Restart Stack9 application
- Check logs for loading errors
Version Conflicts
Problem: Multiple modules require different versions of same dependency
Solutions:
- Use
npm lsto see dependency tree - Update modules to compatible versions
- Use
resolutionsin package.json (Yarn)
Resource Conflicts
Problem: Two modules define same entity/screen key
Solutions:
- Rename resources with module prefix
- Use unique keys:
module1_customervsmodule2_customer - Choose which module to use
Next Steps
Now that you understand Modules, learn about:
- Entities - Define data models in modules
- Screens - Create reusable UI components
- Apps - Package navigation structures
- How-To: Create a Reusable Module