> For the complete documentation index, see [llms.txt](https://voyzu.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://voyzu.gitbook.io/docs/customising-and-extending-voyzu/architecture.md).

# Architecture

## Architecture

Voyzu Accounting is an open source, modern web application serving two functions:

* A headless, ERP grade Accounting system
* A tenant based rapid application development (RAD) framework

## Database

The application design tries to find a middle ground between using Postgres to store business logic (which rather belongs in the application) and treating the database solely as a data store. There are a few rules around table design, to ensure a consistent experience for all who work on the project:

### Data table rules

All tables, except for reference tables must contain an auto-incrementing integer `id` column

All tables must contain a text `code`column, this is the business key of the object and must be unique

All tables must contain the standard Audit fields

All tables (except for the audit tables themselves) must be connected to the global audit trigger

### Database Design

Database tables should contain validation constraints, where reasonable. Use foreign keys to enforce relationship. As a general rule it should not be possible to put the database in an invalid state, even by using SQL statements directly. The principles of robust, scalable database design apply

## Application Layers

The application architecture uses a layers approach, each layer (represented by a folder) contains files with the same architectural purpose. Below is the high level directory structure

```json
docs/                         # project documentation and architecture notes
  common/                     # shared cross-tenant developer and meta documentation
  tenants/                    # tenant specific developer documentation including DDMs
  public/                     # public facing documentation including user guides

infra/                        # database, deployment and infrastructure configuration
  common/                     # shared infrastructure definitions
  tenants/                    # tenant specific infrastructure

public/                       # publicly served static assets
  common/                     # shared public assets
  tenants/                    # tenant specific public assets

scripts/                      # developer and operational scripts
  common/                     # shared helper automation scripts
  tenants/                    # tenant specific scripts

src/                          # main application source code
  app/                        # Thin Next.js routing adapters layer
    (web)/                    # browser routes and layouts
      (common)/               # shared web layouts or wrappers
      (tenants)/              # tenant scoped web route groups
    api/                      # HTTP API route adapters
      (tenants)/              # tenant scoped API routing

  client/                     # client side application code.
    common/                   # shared client utilities and UI
    tenants/                  # tenant specific client features

  dto/                        # shared request and response data contracts
    common/                   # shared DTO definitions
    tenants/                  # tenant scoped DTO contracts

  reference/                  # static reference data
    tenants/                  # tenant specific reference data

  server/                     # backend business logic modules
    common/                   # shared backend utilities
    tenants/                  # tenant owned backend modules
      {tenant name}/          # specific tenant capability area
        {module name}/        # discrete tenant business feature module
          api/                # HTTP handlers for module
          db/                 # persistence and repositories
          lib/                # services mapping validation
          ui/                 # module owned SSR pages

tests/                        # automated testing suites
  functional/                 # end to end functional tests
    tenants/                  # tenant scoped test suites

package.json                  # project dependencies and scripts
README.md                     # project overview and guidance
```

### No additional layers

The above folders, down to the level of “tenants” are sufficient. Do not add any additional folders above the ‘common’ or ‘tenant’ level.

## Multi-tenancy

Voyzu is a multi tenant system. This gives application developers confidence that features they develop will not be adversely affected by other developers developing separate functionality. That is, they offer the benefits of isolation. Because tenants must conform to a fixed specification they provide a development pattern that enables rapid, accurate development, including AI assisted development.

### Tenants and modules

A tenant is a set of application functionality and is composed of one or more modules. A module represents a discrete unit of functionality. For example the “Companies” module of the “Accounting” Voyzu tenant allows users to manage companies. It is up to you as a developer if and how you divide tenants into modules - if your tenant is user-facing then a logical way of grouping functionality is to have one module per menu navigation item.

Some layer folders such as `server/tenants` require file grouping by module, if your tenant will have files in these folders then your tenant must have at least one module. If your tenant is not large enough to warrant more than one module, enclose all functionality in a module named `core`

Note - terminology: "module" is used in this document to mean a tenant module, or domain module In the UI it is common to call the screenset associated with a top or left nav item a "module". The "Users module", the "Finance module" etc. These are not tightly coupled to tenant modules. To avoid confusion refer to these front facing functionality sets as "UI Modules"

### How the tenant system works within the Voyzu application architecture

As described above, the Voyzu application is divided into layers. Each layer is represented by a top level folder, and layers can contain sub layers. These layers can be thought of a “slots”, and you as a tenant author need to distribute your tenant functionality across the appropriate slots.

Put tenant functionality (grouped by module as required) into the appropriate layer. For example if your tenant has static files then these would reside within `public`, Next.js application routes reside within `/src/app`, Data Transfer Objects (DTOs) reside within `/src/dto` and so on. This means that your tenant will be split across many folders. What binds your tenant and its modules together across these folders is a strict naming system:

* Your tenant must be named consistently everywhere and within your tenant module names must be consistent
* Tenant names must be unique across the application - duplicate tenant names are not allowed
* All tenant functionality must be contained within an existing `tenants` folder, a sub-folder of every architecturally significant folder
* Tenant modules must be direct children of the tenant, module nesting is not permitted. Module names must be unique within a tenant.
* Your tenant does not have to have files present in every layer. For example you may have a tenant that does not have a UI and is available only via API calls. In this case the tenant would not have any folders inside the `src/client` folder.

### Listing of significant folders

Below a listing of layer folders, their purpose and a brief description of the tenant pattern to use. Within a tenant, module structure describes how files within a tenant folder should be grouped. Files can be organized in one of two ways:

* **No module structure required**. Files are not required to be organized into module sub-folders. Of course good naming and structure is important, and you are free to use module sub-folders if you wish, there is just no hard requirement to organize by module.
* **Module structure required.** The tenant folder must have one or more module folders, and these folders are used to logically group files. There must be no files present in the tenant root folder. Modules must be named consistently across tenant folders.

  If functionality does not fit into a particular module, create a top level folder that is not a module. For example you could create a “shared” folder within your tenant directory for functionality that is spans multiple modules. Avoid the name “common” to avoid confusion with Voyzu common folders.

| Slot                                    | Purpose                                                                                                | Module structure                                                       | Tenant structure specifications and patterns                                                                                                                           |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| /docs/tenants/{tenant name}             | tenant documentation                                                                                   | No module structure required                                           | Developer facing tenant documentation, including DDMs                                                                                                                  |
| /docs/public                            | public documentation                                                                                   | No module structure needed                                             | Public knowledge base including User Guides                                                                                                                            |
| /infra/tenants/{tenant name}            | tenant infrastructure including database schema scripts                                                | No module structure required                                           | use `./db/schema` for table creation scripts                                                                                                                           |
| /public/tenants/{tenant name}           | Static, publicly available files                                                                       | No module structure required                                           | Because the Next.js framework allows css files to be bundled,, this folder is generally used only for static assets such as images                                     |
| /scripts/tenants/{tenant name}          | Tenant scripts. These can be run from the command line with `npx tsx scripts\tenant\{tenant name}\.`.. | No module structure required                                           | use `./db/seed` to seed tenant tables                                                                                                                                  |
| /src/app/(web)/({tenant name})          | Web page routes                                                                                        | No module structure required. Organize routes to suit desired page URL | Web pages routes. In Next.js the directory structure of files within this folder maps to browser paths                                                                 |
| /src/app/api/{tenant name}              | Api routes                                                                                             | No module structure required. Organize routes to suit desired API URL  | API routes. In Next.js the directory structure of files within this folder maps to api paths                                                                           |
| /src/client/tenants/{tenant name}       | Client side functionality                                                                              | Module structure required.                                             | Primarily jsx pages and components. All files in this folder must begin with ‘use client’, meaning that full NodeJS functionality is not available to tenants here     |
| /src/dto/tenants/{tenant name}          | Data Transfer Objects                                                                                  | No module structure required.                                          | Tenant Data Transfer Objects. These are interfaces and type files only.                                                                                                |
| /reference/tenants/{tenant name}        | Tenant reference data                                                                                  | No module structure required.                                          | In general, because reference data is contained within database tables, this folder is not often used by tenants                                                       |
| /server/tenants/{tenant name}           | All tenant server side functionality                                                                   | Module structure required.                                             | <p>All tenant server-side functionality including:<br>• Server Side Rendered (SSR) Web pages<br>• Database connection and data mutation code<br>• API handlers<br></p> |
| /tests/functional/tenants/{tenant name} | Functional tenant tests                                                                                | Module structure required.                                             | <p>Tenant tests including:<br>• Data manipulation tests<br>• API route tests</p>                                                                                       |

#### /docs/tenants/{tenant name}

**Purpose**

Use this directory for developer facing tenant documentation. Use `docs/public` for documentation you want to be publicly available.

**File and Directory organization**

No module structure is required.

**Patterns and Technical requirements**

All doc files should be written in markdown (.md files). Use the `/docs/tenants/{tenant name}/ddm` folder for Domain Data Model (DDM) files. These should have a file name ending in `.ddm.md`

#### /docs/public

**Purpose**

Use this folder for public facing documentation.;

**File and Directory organization**

No module structure is required. Structure documents in a way that is logical for users seeking information.;

**Patterns and Technical requirements**

A DDM document should have at least two downstream documentation files - a user guide and an operations document. See the "Documentation" section for more information.

All doc files should be written in markdown (.md files).

Note that the `/doc/public` folder is currently available online at <https://voyzu.gitbook.io/docs/> and a real time pipeline from github to gitbook is in place. This means that any change you make within the `/docs/public` folder will be immediately available online.

#### /infra/tenants/{tenant name}

**Purpose**

Use this directory for tenant infrastructure files

**File and Directory organization**

No module structure is required

**Patterns and Technical requirements**

If your tenant has database objects such as tables they must be described as sql files in `infra/tenants/{tenant name}/db/schema`

Create the database table by placing a PostgreSQL `CREATE TABLE` sql script within this folder This script should first delete the table if it exists (`DROP TABLE IF EXISTS`). This applies to all database objects such as triggers.

***Note: because database table creation scripts drop existing tables the database creation process is therefore a destructive operation and should be treated carefully.***

The script can be executed withing a tool such as PGAdmin, or for convenience the Voyzu script command `npx tsx scripts/framework/db/run-schema {tenant name} {sql script name}` can be used to run the script against the application database.

#### /public/tenants/{tenant name}

**Purpose**

Use this directory for publicly available static assets. Because the Next.js framework allows css folders to be bundled,, this folder is generally used only for static assets such as images

**File and Directory organization**

Module structure is not required

**Patterns and technical requirements**

The directory path and file name define the end URL. For example a file located in:

`/public/tenants/{tenant name}/sub/dir/file.png`

will be avaialble at

`http(s)://{application base url}/tenants/{tenant name}/sub/dir/file.png`

#### /scripts/tenants/{tenant name}

**Purpose**

Use this directory for any scripts you want your tenant to make available.

**File and Directory organization**

Module structure is not required

**Patterns and technical requirements**

Use `/scripts/tenants/{tenant name}/db` for scripts that work with your tenant’s database objects. The `db` folder must contain:

**init.ts**

To allow for tenants to be set up efficiently you must provide an `init.ts` script in the root of the `/db` sub-directory that creates and attaches all tenant database objects (tables, triggers, views etc). Be sure to create database objects in order of dependency, to avoid this script crashing due to trying to refer to an object that hasn’t yet been created

**/seed sub-directory**

Use the `/seed` sub-directory to seed whatever data you need to in your tenant database tables. Seed scripts should be idempotent, i.e. use upsert type commands not insert type commands.

If you do need to seed any data then to allow for tenants to be set up efficiently you must provide an `init.ts` script in this folder that runs all seeding scripts.

Scripts need to be able to be run from the command line via the `npx tsx` command. Your scripts can accept command line arguments - see `\scripts\common\db\run-schema.ts` for an example of this.

#### /src/app/(web)/({tenant name})

**Purpose**

This directory contains all browser paths available to your tenant's users. `/src/app` is a special folder to the Next.js framework - all files with special Next.js names within this folder will be served to end users. The browser path is formed from the directory structure. Directories in brackets do not form part of the user facing path and thus can be used to organize files and folders into logical groups without affecting the URL.

A handful of file names are special to the Next.js built in router and will be served:

| File           | Purpose                                                                                               |
| -------------- | ----------------------------------------------------------------------------------------------------- |
| `page.tsx`     | <p>The actual route UI (what renders at the URL). Example:<br>app/dashboard/page.tsx → /dashboard</p> |
| `layout.tsx`   | Shared layout wrapper for routes below                                                                |
| `template.tsx` | Like layout but re-renders on navigation                                                              |
| `route.ts`     | API endpoint (GET/POST/etc handler)                                                                   |

**File and Directory organization**

Place all page routes within the `/src/app/(web)/({tenant name})` directory. Because Next.js will not render segments in brackets, neither ‘web’ nor the tenant name will appear in the final URL. Structure folders and files to match the final path you want the page to be available on.

**Patterns and Technical requirements**

Files within the Next.js `/app` sub-directory are only permitted to be very thin wrappers over either:

* React pages (tsx files) contained in `/src/client/tenants/{tenant name}`
* React SSR pages (tsx files) contained in `/src/server/tenants/{tenant name}/ui`

For example the entire code file `src\app\(web)\(tenants)\accounting\companies\page.tsx` contains only one line:

`export { default } from "@/server/tenants/finance-core/companies/ui/companies.page";`

#### /src/app/api/{tenant name}

**Purpose**

This directory contains all API routes available to your tenant's users. As described above in the “/src/app/(web)/({tenant name})” section `/src/app` is a special folder to the Next.js framework

**File and Directory organization**

Place all API routes within the `/src/app/(web)/{tenant name}` directory. Note that your tenant name is not enclosed in brackets, and will thus form part of the API path. This is a deliberate Voyzu design decision, and makes for a clear API structure.

**Patterns and Technical requirements**

API route files within the Next.js `/app` sub-directory are only permitted to be very thin wrappers over API functionality contained in `/src/server/tenants/{tenant name}/api`

For example the entire code file `src\app\api\(tenants)\accounting\companies\route.ts` contains only three lines of code:

```json
import { handleList, handleCreate } from "@/server/tenants/finance-core/companies/api/company.http.handlers";

export const GET = handleList;
export const POST = handleCreate;
```

#### /src/client/tenants/{tenant name}

**Purpose**

This folder contains all tenant client side functionality.

**File and Directory organization**

Files must be organized by module. As described above if your tenant has only one module, call it `core`. This means that there must not be any files at the root of `/src/client/tenants/{tenant name}` . In our example of a small tenant, you would expect to see client files in `/src/client/tenants/{tenant name}/core` )

**Patterns and Technical requirements**

All files muse include the `use client` directive at the top of the code file. This means that full NodeJS functionality is not available to client files. If you need NodeJS functionality, create a file within the `src/server` directory (described below).

Client side files may import from the `src/dto` directory but must not import from the `src/server` directory.

#### /src/dto/tenants/{tenant name}

**Purpose**

This folder contains all tenant Data Transfer Object (DTO) definitions

**File and Directory organization**

Files must be organized by module. As described above if your tenant has only one module, call it `core`. Again, this means that there must not be any dto files at the root of `/src/dto/tenants/{tenant name}`

**Patterns and Technical requirements**

For an overview of what a Data Object is in the context of the Voyzu framework, see the separate “Data Objects” section earlier in this document

A DTO file is a simple interface or type that defines the shape of a Data Object, in the context of manipulating that Data Object (e.g. updating it, creating a new object). It must not contain any business logic or validation (beyond expected fields and types). Because DTOs are used in the context of data manipulation across domains, they are divided into two categories Request DTOs and Response DTOs

Request DTOs define the shape of Business Objects send from the client to the server. They must be named `{business object name}.{verb}.request.dto.ts`, for example `company.patch.request.dto.ts`.

Response DTOs define the shape of Business Ojbects sent from the server to the client. They must be named `{business object name}.[{optional verb}].response.dto.ts`, for example `company.response.dto.ts`.

The DTO folder can be used by both the client and the server. This makes it a powerful ‘contract’ between client side and server side functionality.

#### /reference/tenants/{tenant name}

**Purpose**

This folder contains all tenant reference data

**File and Directory organization**

Files must be organized by module.

**Patterns and Technical requirements**

The reference folder is used to contain data used by a tenant that is not stored in the database. Because almost all reference data is stored in the database using this folder would be unusual for a tenant. The accounting tenant uses this folder to store document type definitions and posting policy rules. This is done because these files are JSON schema and typescript, and a file system is a better fit for these than a database for this specific use case.

#### /server/tenants/{tenant name}

**Purpose**

This folder contains all server side tenant functionality, including SSR pages, API handlers and logic.

**File and Directory organization**

Files must be organized by module.

**Patterns and Technical requirements**

A typical folder and file structure for a tenant that manages business data is shown below (the “companies” module of the “accounting” tenant is used as the example):

```json
server/tenants/finance-core/companies/
  api/
    company.http.handlers.ts
  db/
    company.repo.ts
    company.row.types.ts
  lib/
    company.mapper.ts
    company.service.ts
    company.validator.ts
  ui/
    companies.page.tsx
```

A brief description of each file is below. These are actual files present in the application, so the exact implementation can be easily viewed.

**api/company.http.handlers.ts**

This file handles (receives http input and returns http output) API requests. As per the Voyzu artchitecture, the caller will always be a `route.ts` file located within `/src/app/api/`

**db/company.repo.ts**

The data repository, this file connects directly to the PostgreSQL data to modify and retrieve data.

**db/company.row\.types.ts**

A companion file for `company.repo.ts`, this file contains simple interfaces for the database table rows

**lib/company.mapper.ts**

A companion file for `company.service.ts`, this file maps database rows to the Data Object

**lib/company.service.ts**

This file could be considered the “brains” of the module. This file controls and orchestrates all calls to the Data Object.

**lib/company.validator.ts**

A companion file for `company.service.ts,` this file contains only validation functions.

**ui/companies.page.tsx**

As per the Voyzu architecture, the render function in this page file will always be called by a `page.tsx` file located within `/src/app/(web)/`

**Composite objects**

Some objects that are encapsulated within a single module may map to two or more data tables. For example a Journal object will logically consist of a journal (header) object and associated journal lines. In this case each object can have its own repository, row types, mapper etc file. However a module should contain only one service file. The service file acts as a module access gateway and it is important all server functionality requests pass through the service module.

#### /tests/functional/tenants/{tenant name}

**Purpose**

This folder contains tenant tests

**File and Directory organization**

Files must be organized by module.

**Patterns and Technical requirements**

Tests use the built in node:test functionality. Tests must test at a minimum

* CRUD data operations
* The full suit of API calls, this by actually starting the Next.js web server

## Example - API POST request

To illustrate some of the layers working together, an example for an API request to create a new company:

```json
POST /api/accounting/companies — client sends JSON body

src/dto/tenants/finance-core/companies/company.create.request.dto.ts defines request body contract
src/dto/tenants/finance-core/companies/company.response.dto.ts defines response contract

src/app/api/(tenants)/accounting/companies/route.ts receives request and calls handler
src/server/tenants/finance-core/companies/api/company.http.handlers.ts receives request, parses body, calls service
src/server/tenants/finance-core/companies/lib/company.service.ts receives input and calls validateCreate
src/server/tenants/finance-core/companies/lib/company.validator.ts validateCreate calls createCreateValidator and returns any validation errors
src/server/tenants/finance-core/companies/lib/company.service.ts calls mapper toInsertRow and repo.insert
src/server/tenants/finance-core/companies/lib/company.mapper.ts builds insert row
c/server/tenants/finance-core/companies/db/company.repo.ts inserts company row into database
src/server/tenants/finance-core/companies/db/company.row.types.ts defines returns row shape (data at rest) used by repo
src/server/tenants/finance-core/companies/lib/company.service.ts receives mapped DTO, validates response output (throw error in dev), and returns response
src/app/api/(tenants)/accounting/companies/route.ts returns http response

POST /api/accounting/companies response - JSON response returns created company
```

## Documentation

The Voyzu Framework is heavily documentation driven. At its core is the concept of a Domain Data Model (DDM) - a comprehensive description of a business domain. A DDM will generally map to a module. For example the "Company" DDM maps to the "Company" module in finance-core. The DDM and the code work together; when code changes are made the DDM should be updated, and when DDM changes are made the code should change to reflect the DDM.

DDM documents can also be used to generate user-facing documentation such as user guides. As an open source system, Voyzu documentation is available publicly.

You can find more information on Domain Data Models and how these are formatted at [`\docs\public\development\domain-data-model-specification\README.md`](/docs/customising-and-extending-voyzu/domain-data-model-specification.md)

There is an automated pipeline in place, such that all documents in `\docs\public` are automatically published upon github commit to <https://voyzu.gitbook.io/docs/>

### User Guides

User guides are a valuable asset to users and should be part of every module's development. Whereas a Domain Data Model is a comprehensive document that blends high level context with a large amount of detail, a user guide will meet an end user where they are, telling them what they need to know about the system rather than flooding them with detail. How you structure and format user documentation is up to you as a module author, but the general pattern used is:

* A higher level user guide to the module, stored in `/docs/public/guide/{module name}/README.md`
* A more 'how to', step-by-step type document, stored in `/docs/public/guide/{module name}/operations.md`

### OpenAPI API documentation

Voyzu supports automatic generation of OpenAPI documentation (sometimes referred to as "Swagger" docs). This is done via the ability to put a JSON `api` tag on http handler methods. You can read more about how to tax API methods and generate an OpenAPI document at [`/docs/public/development/api-jsdoc-guide.md`](/docs/customising-and-extending-voyzu/api-jsdoc-guide.md)

## UI

### Application wide styles

Consistency in overall application look and feel is provided at a foundational level by shared global CSS variables. These reside at `src\client\common\ui\css\variables.css`

Note that the brand-primary style is an accent color and used only for:

* Top and Left nav highlighting
* Primary buttons

The system primary color should be taken from the primary (blue) pallet. For example check box controls should be blue with a focus ring. See the Companies module for examples of the standard palette and styles in action.

#### Application Components

A number of components are provided in `src\client\common\ui\components` These include the left hand application menu, as well as page level controls like the searchable select box and data table/

#### Component Styling

`src\client\common\ui\css\components.module.css` provides styling for many basic controls such as the button control, checkbox control etc. Note that you generally won't need to use this css module directly as these styles are built into the page styling.

#### Page Styling

Page styles are provided for the common CRUD pages. These reside in `src\client\common\ui\css`

### Designing a Create, Read, Update, Delete (CRUD) module

In ERP systems a very common use case is a module that allows users to manage business objects. This could be adding new companies in the Accounting tenant, creating invoices in a Billing tenant, managing assets in an Asset Management tenant, and so on. The companies module of the finance-core tenant is a good example of a standard CRUD module. Although the exact features of a CRUD module will vary according to use case, some standard functionality is generally present

#### List screen

The list screen allows users to view and manage business objects. From left to right, top to bottom this screen generally includes:

* Breadcrumbs, showing the navigation path to the item
* Page title with icon, indicating the business object being viewed (e.g. Companies)
* Primary action button, used to create a new record (e.g. “Add Company”)
* Search input, allowing quick filtering by keyword or code
* Secondary actions including delete, refresh and download
* Filter button, opening advanced filtering options. Use the filter-panel control from `src\client\common\ui\components`.
* Note that searching and filtering are mutually exclusive operations that are performed on the entire data set; if a search is performed the filter is cleared, and if a filter is selected the search should clear.
* Shared data table component, displaying and managing the list of records. Use the data table component available from `src\client\common\ui\components`

#### Create screen

The create screen is used to create a new business object e.g. a new company. In general a modal pop out screen is preferred, unless there are a large number of fields or a lot of complexity to adding a new object, in which case a full page view is better. The create screen, at a high level should contain:

* The modal dialog title, in the format “Create a new {business object name}’
* If the business object requires or allows user defined codes, the “Code” field, with a button to auto-generate the code
* The id is not displayed it is auto-generated on object creation
* The various business object screens
* The bottom of the form contains a cancel and save button, the save button should be labelled “Create {business object name}”
* The create operation should always be validated, if validation fails an alert message displays at the top of the modal
* If the save operation succeeds the user is taken back to the list screen, and a toast message is shown - use the toast shared component

#### View / Edit screen

The view / edit screen allows the user to view all relevant business object fields and to edit supported fields. From left to right, top to bottom this screen generally includes:

* Breadcrumbs, showing the navigation path (e.g. Global Settings / Companies /)
* Page title with icon, showing the record name
* Primary actions row, including:
  * Cancel button
  * Delete action (if permitted)
  * Save button
  * If a save or delete operation succeeds the user is taken back to the list screen, and a toast message is shown - use the toast shared component
* Main form card, containing editable business fields (e.g. code, name, attributes, configuration)
* Secondary sidebar card(s), containing:
  * Status control (e.g. Active / Inactive)
  * System information (e.g. ID, created date, updated date)
  * Audit access (e.g. “View audit information”)

## Linting

The application contains a eslint.config.js file which allows standard eslint rules to be enforced. In addition a subset of Voyzu framework rules are enforced.

## Use Framework functionality where available

The Voyzu application can be thought of as a framework, built upon the Next.js and React Frameworks Many layer folders contain files outside of the `tenants` folder, and some folders contain a `common` folder which provides useful functionality to all tenants. For example the `/src/client/ui/framework/components` directory contains a number of useful client side react components like a Data Table, a Data Filter and so on.

As a rule if the Application Framework provides functionality, this should be preferred over developing your own functionality from scratch. To use the above example, a tenant UI should use the common component react data table control rather than provide its own, unless there was a compelling reason for a custom data table. If framework functionality does not go far enough, extend this functionality rather than developing parallel functionality.

## Checklist: Module update

The below checklist can be used when a module update is required. It uses the example of a new field / property addition to a data object. This checklist can also be used when creating a new module as the steps are the same.

### Domain Data Model (DDM) update

If a change is made in a DDM document, below the steps to follow to implement this change. The example of a new field addition is used

### Steps / Checklist

* Data Transfer Object (DTO) updates. Ensure the DTO objects correctly capture the new field. The DTO is the canonical data definition so it makes sense to start with here.
* Database Table creation script. Change the database table create script to include the new field
* Seed script. Update the table seeding to ensure the new field is seeded if necessary
* Update server functionality. Ensure all server files such as API handlers, data repository, mapping and validation files include the new field
* Update UI. Ensure the list, add modal and edit screens include the new field and the field is included in validation
* Update Next.js web routing and navigation if needed. This will only be needed if this is a new module or module routing needs to change
* Update Next.js API routing if needed This will only be needed if this is a new module or routing needs to change
* Update tests
* Update downstream documentation. if the change impacts user operation of the system, update the relevant User Guide and / or operations guide


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://voyzu.gitbook.io/docs/customising-and-extending-voyzu/architecture.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
