Development Guide
Project Style
Eco Manager is a contract-driven modular monolith.
The codebase should be easy for one or two developers to understand, maintain, and extend.
Prefer simple vertical slices over abstract enterprise layering.
Workspace Structure
.
├── apps/
│ ├── backend/
│ ├── frontend/
│ └── admin/
│
├── packages/
│ ├── contracts/
│ ├── db/
│ ├── auth/
│ ├── permissions/
│ └── shared/
│
└── docs/App Responsibilities
apps/backend
Owns API routes, services, transactions, authorization checks, audit events, Vault operations, and integrations.
apps/frontend
Owns the normal engineer and operations user experience.
apps/admin
Owns Admin Studio: the super-user CRUD/configuration interface for the Universal Entity Platform.
Admin Studio should not bypass the backend. It uses contracts and API calls like any other frontend app.
Suggested Backend Module Structure
apps/backend/src/modules/
├── entities/
│ ├── entities.routes.ts
│ ├── entities.service.ts
│ ├── entities.permissions.ts
│ ├── entities.validators.ts
│ │
│ ├── use-cases/
│ │ ├── create-entity.ts
│ │ ├── update-entity.ts
│ │ ├── move-entity.ts
│ │ ├── soft-delete-entity.ts
│ │ ├── restore-entity.ts
│ │ └── purge-entity.ts
│ │
│ ├── hierarchy/
│ │ ├── get-children.ts
│ │ ├── get-descendants.ts
│ │ ├── get-ancestors.ts
│ │ ├── get-path.ts
│ │ └── validate-reparent.ts
│ │
│ ├── groups/
│ ├── properties/
│ ├── tags/
│ └── relationships/
│
├── admin/
│ ├── admin.routes.ts
│ ├── admin.permissions.ts
│ └── use-cases/
│ ├── preview-bulk-operation.ts
│ ├── perform-bulk-operation.ts
│ ├── inspect-entity-config.ts
│ └── restore-deleted-record.ts
│
├── vault/
├── assets/
├── customers/
├── sites/
├── buildings/
├── remote-connectivity/
├── audit/
└── simpro/Suggested Admin App Structure
apps/admin/src/
├── routes/
│ ├── entity-types/
│ ├── entities/
│ ├── property-groups/
│ ├── tag-groups/
│ ├── templates/
│ ├── groups/
│ ├── relationships/
│ └── audit/
│
├── features/
│ ├── command-palette/
│ ├── entity-explorer/
│ ├── hierarchy-tree/
│ ├── property-builder/
│ ├── tag-builder/
│ ├── template-builder/
│ ├── relationship-explorer/
│ ├── bulk-operations/
│ └── audit-inspector/
│
├── components/
├── lib/
│ └── api.ts
└── main.tsxNo Generic Repository Layer By Default
Do not hide Drizzle behind generic repositories unless there is a clear need.
Prefer:
- services,
- use-case functions,
- query helpers,
- explicit transactions.
This keeps Drizzle autocomplete, inference, relation loading, and SQL composition available to developers.
Contracts
Contracts live in packages/contracts and are shared by backend, frontend, and admin.
Contracts should include:
- Zod request schemas,
- Zod response schemas,
- DTO types,
- route contract definitions,
- shared constants.
Contracts must not include database code.
Database Code
Database schema lives in packages/db.
Application behaviour belongs in backend modules, not in the database package.
Use Cases
A use case should represent a meaningful user or system action.
Examples:
- create entity,
- move asset,
- create credential,
- reveal secret,
- restore deleted site,
- apply asset template,
- add asset to commissioning group,
- preview Admin Studio bulk update,
- update property definition.
Use cases should be small, testable, and transaction-aware.
Transactions
Operations that change multiple tables must run inside a transaction.
Examples:
- create customer entity and customer record,
- move entity and update descendant paths,
- soft delete subtree,
- restore subtree,
- create secret and audit event,
- perform Admin Studio bulk update.
Documentation Rule
When a change affects architecture, data model, security, or product behaviour, update docs in the same pull request or commit.
For small solo development, this can simply mean updating the relevant markdown file before marking the feature done.