Skip to main content

Structuring Your Application

Learn how to organize and structure your Stack9 application for scalability, maintainability, and team collaboration. This guide covers architecture patterns, folder organization, naming conventions, and best practices for building production-grade applications.

What You'll Learn

  • ✅ Application architecture patterns
  • ✅ Module organization strategies
  • ✅ Entity folder structure
  • ✅ Screen organization
  • ✅ Query library organization
  • ✅ Code organization best practices
  • ✅ Naming conventions
  • ✅ Scalability considerations

Time Required: 45-60 minutes

Prerequisites

Stack9 Project Structure Overview

A typical Stack9 application follows this structure:

stack9-stack/
├── src/
│ ├── entities/ # Data models
│ │ ├── custom/ # Your entities
│ │ └── core/ # System entities
│ ├── screens/ # UI definitions
│ ├── query-library/ # Data queries
│ ├── apps/ # Navigation apps
│ ├── automations/ # Workflows
│ ├── entity-hooks/ # Business logic
│ ├── action-types/ # Custom actions
│ ├── connectors/ # External APIs
│ ├── services/ # Reusable services
│ ├── document-templates/ # PDF/email templates
│ └── modules/ # Reusable packages
├── package.json
├── tsconfig.json
└── .env

Architecture Patterns

Pattern 1: Domain-Driven Design (DDD)

Organize by business domain/module:

src/
├── entities/
│ ├── custom/
│ │ ├── crm/ # Customer management domain
│ │ │ ├── customer.json
│ │ │ ├── customer_contact.json
│ │ │ ├── customer_note.json
│ │ │ └── customer_group.json
│ │ ├── sales/ # Sales domain
│ │ │ ├── sales_order.json
│ │ │ ├── order_item.json
│ │ │ ├── invoice.json
│ │ │ └── payment.json
│ │ ├── inventory/ # Inventory domain
│ │ │ ├── product.json
│ │ │ ├── category.json
│ │ │ ├── warehouse.json
│ │ │ └── stock_movement.json
│ │ └── hr/ # HR domain
│ │ ├── employee.json
│ │ ├── department.json
│ │ └── timesheet.json
├── screens/
│ ├── crm/
│ │ ├── customer_list.json
│ │ ├── customer_detail.json
│ │ └── customer_dashboard.json
│ ├── sales/
│ │ ├── order_list.json
│ │ ├── order_detail.json
│ │ └── invoice_list.json
│ └── inventory/
│ ├── product_list.json
│ └── stock_report.json
└── query-library/
├── crm/
│ ├── getcustomerlist.json
│ └── getcustomer.json
├── sales/
│ ├── getorderlist.json
│ └── getorderdetails.json
└── inventory/
├── getproductlist.json
└── getstocklevels.json

Benefits:

  • ✅ Clear domain boundaries
  • ✅ Easy to find related code
  • ✅ Team can work on different domains independently
  • ✅ Easier to extract domains into separate services

Pattern 2: Feature-Based Structure

Organize by feature/capability:

src/
├── entities/
│ └── custom/
│ ├── customer_management.json
│ ├── order_processing.json
│ ├── inventory_tracking.json
│ └── reporting.json
├── screens/
│ ├── customer_management/
│ │ ├── list.json
│ │ ├── detail.json
│ │ └── analytics.json
│ └── order_processing/
│ ├── order_entry.json
│ ├── order_fulfillment.json
│ └── order_tracking.json
└── query-library/
├── customer_management/
└── order_processing/

Benefits:

  • ✅ Feature-focused organization
  • ✅ All related files in one place
  • ✅ Easy to add/remove features
  • ✅ Clear feature boundaries

Pattern 3: Layer-Based Structure

Organize by technical layer (traditional approach):

src/
├── entities/
│ └── custom/
│ ├── customer.json
│ ├── order.json
│ └── product.json
├── screens/
│ ├── customer_list.json
│ ├── order_detail.json
│ └── product_catalog.json
├── query-library/
│ ├── getcustomerlist.json
│ ├── getorderdetails.json
│ └── getproductcatalog.json
└── entity-hooks/
├── customer.vat.ts
├── order.vat.ts
└── product.vat.ts

Benefits:

  • ✅ Simple and straightforward
  • ✅ Good for small applications
  • ✅ Familiar structure
  • ✅ Easy to learn

Module Organization

Modules are reusable packages that can be shared across Stack9 applications.

Creating a Module

File: src/modules/customer-management/module.json

{
"key": "customer_management",
"name": "Customer Management Module",
"version": "1.0.0",
"description": "Complete CRM functionality",
"author": "Your Company",
"dependencies": [],
"includes": {
"entities": [
"customer",
"customer_contact",
"customer_note",
"customer_address"
],
"screens": [
"customer_list",
"customer_detail",
"customer_dashboard"
],
"queries": [
"getcustomerlist",
"getcustomer",
"getcustomercontacts"
],
"apps": [
"crm"
],
"automations": [
"customer_welcome_email"
]
}
}

Module Folder Structure

src/modules/customer-management/
├── module.json # Module definition
├── entities/
│ ├── customer.json
│ ├── customer_contact.json
│ └── customer_note.json
├── screens/
│ ├── customer_list.json
│ ├── customer_detail.json
│ └── customer_dashboard.json
├── query-library/
│ ├── getcustomerlist.json
│ └── getcustomer.json
├── apps/
│ └── crm.json
├── entity-hooks/
│ ├── customer.vat.ts
│ └── customer.bat.ts
├── automations/
│ └── customer_welcome_email.json
├── document-templates/
│ └── customer_statement.html
└── README.md # Module documentation

Module Best Practices

1. Keep Modules Focused

✅ Good - Focused modules:
- customer-management
- order-processing
- inventory-tracking

❌ Bad - Too broad:
- business-logic
- utilities
- everything

2. Define Clear Dependencies

{
"dependencies": [
"customer-management@^1.0.0",
"product-catalog@^2.1.0"
]
}

3. Version Modules

Follow semantic versioning:

  • 1.0.0 - Initial release
  • 1.1.0 - New features (backward compatible)
  • 2.0.0 - Breaking changes

4. Document Modules

Include comprehensive README.md:

# Customer Management Module

## Overview
Complete CRM functionality for managing customer relationships.

## Features
- Customer CRUD operations
- Contact management
- Customer notes and history
- Customer segmentation

## Installation
1. Copy module to `src/modules/customer-management`
2. Run `npm run dev` to load entities
3. Configure app navigation

## Configuration
Set environment variables:
- `CRM_NOTIFICATION_EMAIL` - Email for notifications
- `CRM_DEFAULT_SALES_REP` - Default sales representative

## Usage
Navigate to `/crm/customer-list` to access customer management.

Entity Organization

Entity Naming Conventions

File Names

✅ Good:
- customer.json
- sales_order.json
- product_category.json
- order_line_item.json

❌ Bad:
- cust.json
- so.json
- cat.json
- oli.json

Entity Keys

{
"head": {
"key": "customer", // ✅ Singular, lowercase
"pluralisedName": "customers" // ✅ Plural
}
}

Field Keys

{
"fields": [
{
"key": "first_name", // ✅ snake_case
"label": "First Name" // ✅ Human-readable
},
{
"key": "email_address", // ✅ Descriptive
"label": "Email Address"
},
{
"key": "is_active", // ✅ Boolean prefix
"label": "Active"
}
]
}

Entity Organization Patterns

Pattern 1: Core + Custom Entities

entities/
├── core/ # System entities (don't modify)
│ ├── user.json
│ ├── user_group.json
│ └── security_role.json
└── custom/ # Your entities
├── customer.json
├── order.json
└── product.json

Pattern 2: Domain Subfolders

entities/custom/
├── crm/
│ ├── customer.json
│ ├── lead.json
│ └── opportunity.json
├── sales/
│ ├── order.json
│ ├── invoice.json
│ └── payment.json
└── inventory/
├── product.json
├── warehouse.json
└── stock_movement.json

Pattern 3: Prefixed Names

entities/custom/
├── crm_customer.json
├── crm_lead.json
├── sales_order.json
├── sales_invoice.json
├── inv_product.json
└── inv_warehouse.json

Entity Relationship Organization

Keep related entities close together:

// customer.json
{
"head": {
"key": "customer",
"name": "Customer"
},
"fields": [
{
"key": "contacts",
"type": "Grid",
"relationshipOptions": {
"ref": "customer_contact"
}
},
{
"key": "addresses",
"type": "Grid",
"relationshipOptions": {
"ref": "customer_address"
}
}
]
}

// customer_contact.json (child entity)
{
"head": {
"key": "customer_contact",
"name": "Customer Contact"
},
"fields": [
{
"key": "customer_id",
"type": "SingleDropDown",
"relationshipOptions": {
"ref": "customer"
}
}
]
}

Screen Organization

Screen Naming Conventions

✅ Good naming:
- customer_list.json # List view
- customer_detail.json # Detail view
- customer_create.json # Create drawer
- customer_edit.json # Edit drawer
- sales_dashboard.json # Dashboard
- monthly_sales_report.json # Report

❌ Bad naming:
- screen1.json
- customers.json
- view.json
- report.json

Screen Organization Patterns

Pattern 1: Entity-Based Organization

screens/
├── customer/
│ ├── customer_list.json
│ ├── customer_detail.json
│ ├── customer_create.json
│ ├── customer_edit.json
│ └── customer_dashboard.json
├── order/
│ ├── order_list.json
│ ├── order_detail.json
│ ├── order_create.json
│ └── order_fulfillment.json
└── product/
├── product_list.json
├── product_detail.json
└── product_catalog.json

Pattern 2: App-Based Organization

screens/
├── crm/
│ ├── customer_list.json
│ ├── customer_detail.json
│ ├── lead_list.json
│ └── opportunity_pipeline.json
├── sales/
│ ├── order_list.json
│ ├── quote_list.json
│ └── sales_dashboard.json
└── reports/
├── sales_report.json
├── inventory_report.json
└── customer_analytics.json

Pattern 3: Type-Based Organization

screens/
├── lists/
│ ├── customer_list.json
│ ├── order_list.json
│ └── product_list.json
├── details/
│ ├── customer_detail.json
│ ├── order_detail.json
│ └── product_detail.json
├── dashboards/
│ ├── sales_dashboard.json
│ └── operations_dashboard.json
└── reports/
├── sales_report.json
└── inventory_report.json

Screen Route Patterns

Maintain consistent route patterns:

{
"head": {
// List views
"route": "customer-list"
"route": "order-list"

// Detail views
"route": "customer-detail/:id"
"route": "order-detail/:id"

// Create screens
"route": "customer-create"
"route": "order-create"

// Dashboards
"route": "sales-dashboard"
"route": "crm-dashboard"

// Reports
"route": "sales-report"
"route": "inventory-report"
}
}

Query Library Organization

Query Naming Conventions

Use descriptive, action-based names:

✅ Good:
- getcustomerlist.json
- getcustomer.json
- getactiveorders.json
- searchproducts.json
- getmonthlysales.json
- getcustomerwithorders.json

❌ Bad:
- query1.json
- customers.json
- list.json
- data.json

Query Organization Patterns

Pattern 1: Entity-Based

query-library/
├── customer/
│ ├── getcustomerlist.json
│ ├── getcustomer.json
│ ├── searchcustomers.json
│ └── getcustomerorders.json
├── order/
│ ├── getorderlist.json
│ ├── getorder.json
│ └── getorderitems.json
└── product/
├── getproductlist.json
├── getproduct.json
└── getproductsbycategory.json

Pattern 2: Purpose-Based

query-library/
├── lists/
│ ├── getcustomerlist.json
│ ├── getorderlist.json
│ └── getproductlist.json
├── details/
│ ├── getcustomer.json
│ ├── getorder.json
│ └── getproduct.json
├── reports/
│ ├── getsalesreport.json
│ ├── getinventoryreport.json
│ └── getcustomeranalytics.json
└── searches/
├── searchcustomers.json
├── searchorders.json
└── searchproducts.json

Pattern 3: Flat with Prefixes

query-library/
├── getcustomerlist.json
├── getcustomer.json
├── getorderlist.json
├── getorder.json
├── getproductlist.json
└── getproduct.json

Query Folders

Use query folders for organization:

File: src/query-folders.json

{
"folders": [
{
"key": "customer_queries",
"name": "Customer Queries",
"description": "Queries related to customer management",
"order": 1
},
{
"key": "order_queries",
"name": "Order Queries",
"description": "Queries for order processing",
"order": 2
},
{
"key": "report_queries",
"name": "Report Queries",
"description": "Queries for reports and analytics",
"order": 3
},
{
"key": "search_queries",
"name": "Search Queries",
"description": "Full-text search queries",
"order": 4
}
]
}

Reference in queries:

{
"key": "getcustomerlist",
"name": "getCustomerList",
"folderKey": "customer_queries",
"connector": "stack9_api"
}

App Navigation Organization

App Structure Best Practices

1. Organize by Business Domain

File: src/apps/crm.json

{
"name": "Customer Management",
"key": "crm",
"icon": "UserOutlined",
"order": 10,
"children": [
{
"key": "customers",
"name": "Customers",
"nodeType": "menuGroup",
"children": [
{
"key": "customer_list",
"name": "All Customers",
"nodeType": "link",
"link": "/crm/customer-list"
},
{
"key": "customer_segments",
"name": "Customer Segments",
"nodeType": "link",
"link": "/crm/customer-segments"
}
]
},
{
"key": "leads",
"name": "Leads",
"nodeType": "menuGroup",
"children": [
{
"key": "lead_list",
"name": "All Leads",
"nodeType": "link",
"link": "/crm/lead-list"
},
{
"key": "lead_pipeline",
"name": "Sales Pipeline",
"nodeType": "link",
"link": "/crm/lead-pipeline"
}
]
}
]
}

2. Use Consistent Ordering

{
"apps": [
{ "key": "dashboard", "order": 1 },
{ "key": "crm", "order": 10 },
{ "key": "sales", "order": 20 },
{ "key": "inventory", "order": 30 },
{ "key": "reports", "order": 40 },
{ "key": "settings", "order": 999 }
]
}
{
"children": [
{
"key": "data_management",
"name": "Data Management",
"nodeType": "menuGroup",
"children": [
{"key": "customers", "name": "Customers"},
{"key": "products", "name": "Products"},
{"key": "orders", "name": "Orders"}
]
},
{
"key": "analytics",
"name": "Analytics",
"nodeType": "menuGroup",
"children": [
{"key": "dashboards", "name": "Dashboards"},
{"key": "reports", "name": "Reports"}
]
}
]
}

Code Organization (Hooks & Actions)

Entity Hooks Organization

File Naming

entity-hooks/
├── customer.vat.ts # Validation (before transaction)
├── customer.bat.ts # Business logic (after transaction)
├── order.vat.ts
├── order.bat.ts
├── product.vat.ts
└── product.bat.ts

Code Structure

// customer.vat.ts
import {
CustomFunction,
CustomFunctionContext,
CustomFunctionResponse,
HookOperation,
} from '@april9/stack9-sdk';
import { DBCustomer } from '../models/stack9/Customer';

/**
* Customer Validation Hook
*
* Validates customer data before saving to database.
*
* Rules:
* - Email must be unique
* - Phone number format validation
* - Credit limit validation
*/
export class ValidateCustomer extends CustomFunction {
constructor(private context: CustomFunctionContext<DBCustomer>) {
super();
}

entityName = 'customer';

async exec(): Promise<CustomFunctionResponse> {
const { entity, operation, db, services } = this.context;

// Validate email uniqueness
if (operation === HookOperation.create || entity.email) {
const existingCustomer = await this.checkEmailUniqueness(
entity.email,
entity.id
);

if (existingCustomer) {
return {
valid: false,
errors: [{
field: 'email',
message: 'Email address already exists'
}]
};
}
}

// Validate phone number format
if (entity.phone) {
if (!this.isValidPhoneNumber(entity.phone)) {
return {
valid: false,
errors: [{
field: 'phone',
message: 'Invalid phone number format'
}]
};
}
}

// Validate credit limit
if (entity.credit_limit < 0) {
return {
valid: false,
errors: [{
field: 'credit_limit',
message: 'Credit limit cannot be negative'
}]
};
}

return { valid: true, entity };
}

/**
* Check if email address is unique
*/
private async checkEmailUniqueness(
email: string,
excludeId?: number
): Promise<boolean> {
const { db } = this.context;

const query = db('customers')
.where({ email, _is_deleted: false });

if (excludeId) {
query.whereNot({ id: excludeId });
}

const existing = await query.first();
return !!existing;
}

/**
* Validate phone number format
*/
private isValidPhoneNumber(phone: string): boolean {
const phoneRegex = /^\+?[\d\s\-\(\)]+$/;
return phoneRegex.test(phone);
}
}

Action Types Organization

action-types/
├── notifications/
│ ├── SendEmailAction.ts
│ ├── SendSMSAction.ts
│ └── PushNotificationAction.ts
├── integrations/
│ ├── SyncToSalesforceAction.ts
│ ├── CreateHubspotContactAction.ts
│ └── SendToSlackAction.ts
├── business-logic/
│ ├── CalculateDiscountAction.ts
│ ├── UpdateInventoryAction.ts
│ └── GenerateInvoiceAction.ts
└── utilities/
├── GeneratePDFAction.ts
├── ExportToCSVAction.ts
└── ArchiveRecordsAction.ts

Services Organization

services/
├── email/
│ ├── EmailService.ts
│ └── EmailTemplateService.ts
├── payment/
│ ├── PaymentProcessorService.ts
│ └── PaymentValidationService.ts
├── inventory/
│ ├── StockService.ts
│ └── WarehouseService.ts
└── reporting/
├── ReportGeneratorService.ts
└── ReportExportService.ts

Naming Conventions

General Rules

  1. Be Descriptive
✅ Good: customer_order_history.json
❌ Bad: data.json
  1. Use Consistent Case
✅ Files: snake_case
✅ Keys: snake_case or camelCase
✅ Labels: Title Case
  1. Follow Patterns
✅ Queries: get*, search*, list*
✅ Actions: send*, create*, update*
✅ Hooks: validate*, process*, calculate*

Entity Naming

{
"head": {
"name": "Sales Order", // Title Case
"key": "sales_order", // snake_case
"pluralisedName": "sales orders" // lowercase plural
},
"fields": [
{
"key": "order_number", // snake_case
"label": "Order Number" // Title Case
}
]
}

Screen Naming

{
"head": {
"title": "Customer List", // Title Case
"key": "customer_list", // snake_case
"route": "customer-list" // kebab-case
}
}

Query Naming

{
"key": "getcustomerlist", // camelCase
"name": "getCustomerList" // PascalCase
}

Scalability Considerations

1. Plan for Growth

Start with clean organization:

✅ Good from start:
entities/custom/
├── crm/
│ └── customer.json
├── sales/
│ └── order.json
└── inventory/
└── product.json

❌ Hard to scale:
entities/custom/
├── customer.json
├── customer2.json
├── order.json
├── order_new.json
└── product_v2.json

2. Use Modules for Reusability

Extract common functionality:

modules/
├── customer-management/ # Reusable CRM module
├── product-catalog/ # Reusable product module
└── order-processing/ # Reusable order module

3. Separate Configuration from Code

config/
├── environments/
│ ├── development.json
│ ├── staging.json
│ └── production.json
├── features/
│ └── feature-flags.json
└── integrations/
├── salesforce-config.json
└── stripe-config.json

4. Index Strategic Fields

{
"fields": [
{
"key": "email",
"type": "TextField",
"index": true // ✅ Frequently queried
},
{
"key": "order_date",
"type": "DateField",
"index": true // ✅ Used in filters
},
{
"key": "status",
"type": "OptionSet",
"index": true // ✅ Common filter
}
]
}

5. Optimize Queries

{
"$select": [
"id",
"name",
"email" // ✅ Only needed fields
],
"$limit": 50, // ✅ Reasonable limit
"$where": {
"is_active": true, // ✅ Indexed field
"_is_deleted": false // ✅ Always filter deleted
}
}

6. Use Caching Strategically

// Cache expensive queries
export class ReportService {
async getMonthlyReport(month: string) {
const cacheKey = `monthly_report_${month}`;

// Check cache
const cached = await cache.get(cacheKey);
if (cached) return cached;

// Generate report
const report = await this.generateReport(month);

// Cache for 1 hour
await cache.set(cacheKey, report, 3600);

return report;
}
}

Best Practices Summary

DO ✅

  1. Use clear, descriptive names
  2. Organize by domain or feature
  3. Keep related files together
  4. Document complex logic
  5. Follow consistent patterns
  6. Use modules for reusability
  7. Index frequently queried fields
  8. Plan for scale from the start

DON'T ❌

  1. Use generic names (data.json, screen1.json)
  2. Mix unrelated entities in one folder
  3. Create deep folder hierarchies (>3 levels)
  4. Duplicate code across entities
  5. Hardcode values in entities
  6. Skip documentation
  7. Ignore naming conventions
  8. Create monolithic modules

Example: Well-Structured Application

Let's look at a complete example of a well-structured e-commerce application:

stack9-ecommerce/
├── src/
│ ├── modules/
│ │ ├── customer-management/
│ │ │ ├── module.json
│ │ │ ├── entities/
│ │ │ │ ├── customer.json
│ │ │ │ ├── customer_address.json
│ │ │ │ └── customer_wishlist.json
│ │ │ ├── screens/
│ │ │ │ ├── customer_list.json
│ │ │ │ ├── customer_detail.json
│ │ │ │ └── customer_dashboard.json
│ │ │ ├── query-library/
│ │ │ │ ├── getcustomerlist.json
│ │ │ │ └── getcustomer.json
│ │ │ ├── apps/
│ │ │ │ └── customers.json
│ │ │ ├── entity-hooks/
│ │ │ │ ├── customer.vat.ts
│ │ │ │ └── customer.bat.ts
│ │ │ └── README.md
│ │ ├── product-catalog/
│ │ │ ├── module.json
│ │ │ ├── entities/
│ │ │ │ ├── product.json
│ │ │ │ ├── category.json
│ │ │ │ └── product_variant.json
│ │ │ ├── screens/
│ │ │ │ ├── product_list.json
│ │ │ │ ├── product_detail.json
│ │ │ │ └── category_list.json
│ │ │ └── query-library/
│ │ │ ├── getproductlist.json
│ │ │ └── getproduct.json
│ │ └── order-management/
│ │ ├── module.json
│ │ ├── entities/
│ │ │ ├── order.json
│ │ │ ├── order_item.json
│ │ │ └── shipment.json
│ │ ├── screens/
│ │ │ ├── order_list.json
│ │ │ ├── order_detail.json
│ │ │ └── fulfillment_queue.json
│ │ ├── query-library/
│ │ │ ├── getorderlist.json
│ │ │ └── getorder.json
│ │ ├── entity-hooks/
│ │ │ ├── order.vat.ts
│ │ │ └── order.bat.ts
│ │ └── automations/
│ │ ├── order_confirmation.json
│ │ └── shipment_notification.json
│ ├── services/
│ │ ├── payment/
│ │ │ └── PaymentService.ts
│ │ ├── inventory/
│ │ │ └── InventoryService.ts
│ │ └── shipping/
│ │ └── ShippingService.ts
│ ├── action-types/
│ │ ├── ProcessPaymentAction.ts
│ │ ├── UpdateInventoryAction.ts
│ │ └── CreateShipmentAction.ts
│ ├── config/
│ │ ├── payment-gateways.json
│ │ ├── shipping-providers.json
│ │ └── tax-rates.json
│ └── document-templates/
│ ├── order_confirmation.html
│ ├── invoice.html
│ └── shipping_label.html
├── package.json
├── tsconfig.json
├── .env.example
└── README.md

Key Features of This Structure

  1. Module-Based: Clear separation of concerns
  2. Self-Contained: Each module has all its dependencies
  3. Reusable: Modules can be shared across projects
  4. Scalable: Easy to add new modules
  5. Maintainable: Clear where to find/add code
  6. Documented: README files for each module

Migration Strategy

Migrating from Flat Structure

If you have a flat structure, migrate gradually:

Step 1: Create Module Structure

mkdir -p src/modules/customer-management/{entities,screens,query-library}

Step 2: Move Related Files

mv src/entities/custom/customer*.json src/modules/customer-management/entities/
mv src/screens/customer*.json src/modules/customer-management/screens/
mv src/query-library/getcustomer*.json src/modules/customer-management/query-library/

Step 3: Update References Update paths in import statements and configuration files.

Step 4: Test Thoroughly Ensure all functionality still works after migration.

Troubleshooting

Issue: Can't Find Entity

Problem: Stack9 can't load entity after reorganization

Solution:

  1. Restart Stack9: npm run dev
  2. Check file paths are correct
  3. Verify JSON syntax is valid
  4. Check console for errors

Issue: Screen Not Loading

Problem: Screen shows 404 after moving files

Solution:

  1. Check route in screen definition
  2. Verify app navigation links
  3. Clear browser cache
  4. Check screen key is unique

Issue: Query Not Found

Problem: Screen says query doesn't exist

Solution:

  1. Check query key matches screen reference
  2. Verify query file is in correct location
  3. Restart Stack9 to reload queries
  4. Check query JSON is valid

Summary

You now understand:

Architecture Patterns - DDD, feature-based, layer-based ✅ Module Organization - Creating reusable modules ✅ Entity Structure - Organizing entities by domain ✅ Screen Organization - Grouping screens logically ✅ Query Organization - Structuring query library ✅ Naming Conventions - Consistent, clear naming ✅ Scalability - Building for growth ✅ Best Practices - Production-ready organization

Next Steps