Reusable Base Template for EnFlexIT web applications.
web.template provides:
- reusable technical capabilities
- reusable React application-platform functionality
- standard Agent.Workbench functionality
- an explicit integration contract for concrete Applications
The authoritative dependency direction is:
Application --> Template --> Core
Standard Agent.Workbench functionality belongs to the Base Template.
Concrete products such as HEMS are Applications that consume the Base Template.
- About
- Architecture
- AgentWorkbench Ownership
- Repository Model
- Requirements
- Local Development
- Application Configuration
- Feature Selection
- Application Navigation
- Application Screens
- Creating a Concrete Application
- Application Integration
- Project Structure
- State Management
- Navigation
- Authentication
- Server Infrastructure
- Update System
- Design System
- API Ownership
- Build and Deployment
- Manual Web Build
- Production Release
- Test Release
- Architecture Validation
- Architecture Decisions
- Documentation
- Architecture Summary
web.template is the reusable EnFlexIT web application platform.
The repository contains two reusable architecture layers:
Template
Core
and the in-repository Agent.Workbench Application composition under:
src/application/
The current Agent.Workbench Application composition validates the Application integration contract.
It is not Agent.Workbench.
Reusable platform functionality includes areas such as:
- Application bootstrap
- authentication and session handling
- server selection
- technical server checks
- navigation
- Redux infrastructure
- design system
- notifications
- update infrastructure
- dynamic content
- reusable screens
- runtime utilities
- technical Core capabilities
- standard Agent.Workbench functionality
The authoritative dependency direction is:
Application
|
v
Template
|
v
Core
The layers represent architectural responsibility.
They are not merely directory names.
Application contains concrete product composition.
Typical responsibilities include:
- Application identity
- Application metadata
- semantic Template feature selection
- Application-specific navigation extensions
- Application-specific screens
- Application translations
- optional Application-specific Redux state
- concrete product business logic
- concrete product backend integration
- product branding
- product-specific build configuration
- product-specific deployment configuration
Application may use supported Template and Core surfaces.
Template and Core must not depend on concrete Application implementation.
Template contains the reusable application platform.
Typical responsibilities include:
TemplateAppcreateTemplateAppApplicationConfigApplicationConfigContext- React application shell
- navigation infrastructure
- Template navigation definitions
- Template screen registry
- Redux infrastructure
- authentication and session orchestration
- server selection
- settings
- design system
- notifications
- update orchestration
- localization infrastructure
- reusable screens
- reusable hooks
- reusable components
- standard Agent.Workbench functionality
- Agent.Workbench state
- reusable Agent.Workbench API integration where appropriate
Template may depend on Core.
Template must not depend on a concrete Application.
Core contains focused reusable technical capabilities.
Current high-level areas include:
src/core/authentication/
src/core/runtime/
src/core/server/
src/core/update/
Typical Core responsibilities include:
- technical authentication helpers
- authentication-related technical types
- runtime helpers
- server normalization
- server validation
- technical server checks
- environment detection
- technical update helpers
- framework-independent technical behavior
Core must not depend on:
Template
Application
React presentation and Redux application orchestration generally do not belong in Core.
Standard Agent.Workbench functionality is intentionally part of the Base Template.
The ownership decision is:
Agent.Workbench standard functionality
-> Template
Examples include:
Program Start
Data Analyzing
Database configuration
Server configuration
Live Console
Settings
Agent.Workbench navigation
Agent.Workbench state
reusable Agent.Workbench API integration
Agent.Workbench is not a separate concrete Application in the accepted architecture.
The architecture therefore does not require:
a separate Agent.Workbench Application
a separate Agent.Workbench Application repository
Agent.Workbench state extraction
Agent.Workbench screen extraction
Agent.Workbench navigation extraction
Agent.Workbench-related naming alone does not make functionality Application-owned.
Ownership follows responsibility.
The current repository contains:
web.template
|
+-- src/application/
|
+-- src/template/
|
+-- src/core/
Responsibilities are:
src/application/
Agent.Workbench Application composition
src/template/
reusable Base Template
including standard Agent.Workbench functionality
src/core/
reusable technical capabilities
Future concrete Applications such as HEMS may consume the Base Template from their own repositories.
Conceptually:
web.template
Base Template
^
|
+-------+-------+
| |
HEMS Future Application
Agent.Workbench is not shown as a separate consumer because its standard functionality is already part of the Base Template.
Local development requires:
- Git
- Node.js
- npm
Verify the installed tools with:
git --version
node -v
npm -vThe committed GitHub Actions workflows define the Node.js and npm versions used for automated builds.
When changing release infrastructure, always verify the current workflow YAML rather than relying only on documentation.
Clone the repository:
git clone git@github.com:EnFlexIT/web.template.gitEnter the repository:
cd web.templateInstall dependencies:
npm installGenerate Application configuration:
npm run config:generateStart web development:
npm run webor:
npm startNormal npm startup commands are preferred because project lifecycle hooks may perform required setup before Expo starts.
Run:
npx tsc --noEmitRun the test suite with:
npm test -- --runInBandRun targeted tests when working on a specific subsystem.
A useful validation sequence is:
npm run config:generate
npx tsc --noEmit
npm test -- --runInBand
git diff --check
git status --shortDeveloper-facing Application configuration is located under:
src/application/config/
The current configuration consists of:
application.properties
features.properties
navigation.properties
These files have different responsibilities.
Contains Application identity and metadata.
Conceptually:
ApplicationId=example-application
ApplicationTitle=Application composition example
ApplicationLogo=../assets/bild.png
ApplicationContact=admin@example.com
ApplicationOwner=EnFlexITThe exact supported property set is defined by the configuration tooling.
Application developers should not need to edit TypeScript or JSON for normal metadata configuration.
Controls reusable Template capabilities semantically.
Examples:
feature.notifications.enabled=true
feature.appearance.enabled=true
feature.serverSettings.enabled=true
feature.liveConsole.enabled=true
feature.programStart.enabled=true
feature.dataAnalyzing.enabled=true
feature.database.general.enabled=trueApplication selects the capability.
Template owns the implementation.
Contains Application-specific navigation extensions.
Example:
menu.example.enabled=true
menu.example.caption=exampleApplication
menu.example.parent=settings
menu.example.position=99
menu.example.screen=example-screenApplication navigation extends Template navigation.
It does not replace the complete Template navigation tree.
Configuration tooling is located under:
src/template/config/build/
A central generator is:
src/template/config/build/generateApplicationConfig.mjs
Generated Application artifacts are written under:
src/application/generated/
Generate them with:
npm run config:generateConceptually:
Application .properties
|
v
Template configuration tooling
|
v
generated runtime configuration
|
v
Application composition
|
v
Template runtime
Generated TypeScript is runtime/build output.
It is not the normal developer-facing configuration surface.
Feature ownership and feature enablement are separate concepts.
For example:
Live Console
-> Template-owned
feature.liveConsole.enabled=false
-> Application selection
Disabling a Template feature does not make it Application-owned.
Likewise, enabling a feature does not move its implementation into Application.
Template owns reusable navigation.
Application owns only concrete Application extensions.
The ownership model is:
Template
|
+-- routing
+-- menu rendering
+-- menu tree construction
+-- Template navigation definitions
+-- Template screen registry
+-- visibility integration
+-- standard Agent.Workbench navigation
+-- Template menu ordering
Application
|
+-- Application-specific navigation extensions
+-- Application-specific screen references
+-- optional custom ordering
Conceptually:
Template navigation
+
Application navigation extensions
|
v
runtime navigation
Applications must not reproduce the complete Template menu structure.
Application configuration must not depend on Template-internal numeric IDs.
Application should express semantic intent.
For example:
menu.example.parent=settings
menu.example.screen=example-screenrather than referencing unstable internal implementation details.
The general rule is:
Application describes intent.
Template resolves implementation details.
Normal Template menu positions are derived from sibling order in the Template menu catalog.
Application custom navigation may optionally provide a position.
When no custom position exists, MenuHub uses a deterministic fallback.
Relevant implementation:
src/template/screens/menu/MenuHubScreen.tsx
Application-specific screens live under:
src/application/screens/
The current Agent.Workbench Application composition contains:
src/application/screens/ExampleScreen.tsx
Application screens are discovered automatically.
Discovery implementation:
src/template/config/build/applicationScreenDiscovery.mjs
Examples:
ExampleScreen.tsx
-> example-screen
ExampleScreen2.tsx
-> example-screen2
HemsOverviewScreen.tsx
-> hems-overview-screen
The generated registry is:
src/application/generated/applicationScreenRegistry.generated.ts
Template must not manually import concrete Application screens.
A concrete Application focuses on product-specific composition while consuming reusable Base Template functionality.
HEMS is the primary concrete example.
Conceptually:
HEMS Application
|
v
web.template
|
+-- Template
|
+-- Core
A concrete Application may provide:
application.properties
features.properties
navigation.properties
Application-specific screens
Application translations
optional Application-specific Redux state
product business logic
product-specific APIs
product branding
product build/deployment configuration
The Base Template should not require HEMS-specific implementation.
A future consumer repository may conceptually contain:
HEMS Repository
|
+-- Application configuration
+-- Application screens
+-- Application translations
+-- optional Application state
+-- product business logic
+-- product branding
+-- build/deployment
and consume:
web.template
|
+-- Template
+-- Core
The exact repository integration mechanism should be validated with a real consumer rather than inferred from an old Agent.Workbench extraction model.
Template exposes explicit integration contracts.
Important files include:
src/template/application/ApplicationConfig.ts
src/template/application/ApplicationConfigContext.tsx
src/template/application/createTemplateApp.tsx
src/template/application/TemplateApp.tsx
Conceptually:
Concrete Application
|
v
ApplicationConfig
|
v
createTemplateApp(...)
|
v
TemplateApp
|
v
Template runtime
Template defines the reusable contract.
Application provides concrete composition.
Template does not decide which concrete Application is active.
The following model is intentionally avoided:
Template
|
+-- detect HEMS
+-- detect Product A
+-- detect Product B
+-- select Application
Instead:
Concrete Application
|
v
Base Template
Agent.Workbench is not part of product resolution because standard Agent.Workbench functionality already belongs to Template.
The current main source structure is conceptually:
src/
├── api/
├── application/
│ ├── config/
│ ├── generated/
│ ├── screens/
│ └── state/
├── core/
│ ├── authentication/
│ ├── runtime/
│ ├── server/
│ └── update/
└── template/
├── application/
├── authentication/
├── components/
├── config/
├── hooks/
├── navigation/
├── permissions/
├── runtime/
├── screens/
├── state/
├── styles/
└── update/
Detailed structure documentation is maintained in:
doc/project-structure.md
Contains API definitions and generated API implementations.
Generated API code must not be broadly rewritten during architecture cleanup.
Ownership depends on responsibility.
An Agent.Workbench-related API name does not automatically make code Application-owned.
Contains the in-repository Agent.Workbench Application composition and Application integration.
Important areas include:
src/application/config/
src/application/generated/
src/application/screens/
src/application/state/
The current Agent.Workbench Application composition is not Agent.Workbench.
Contains focused reusable technical capabilities.
Current areas include:
src/core/authentication/
src/core/runtime/
src/core/server/
src/core/update/
Core must remain independent from Template and Application.
Contains the reusable Base Template platform.
Important areas include:
src/template/application/
src/template/authentication/
src/template/components/
src/template/config/
src/template/hooks/
src/template/navigation/
src/template/permissions/
src/template/runtime/
src/template/screens/
src/template/state/
src/template/styles/
src/template/update/
Standard Agent.Workbench functionality belongs here where it is part of the reusable Base Template platform.
The project uses Redux Toolkit.
Redux is an implementation technology, not an architecture layer.
State ownership follows responsibility.
Template
|
+-- reusable Template state
+-- Agent.Workbench state
+-- Redux infrastructure
Application
|
+-- optional concrete product-specific state
Core does not own the application Redux store.
Known store infrastructure includes:
src/template/state/store/
├── createTemplateStore.ts
├── rootReducer.ts
├── store.ts
├── templateReducers.ts
├── types.ts
├── useAppDispatch.ts
└── useAppSelector.ts
Standard Agent.Workbench state belongs to Template.
Known area:
src/template/state/agent-workbench/
This state is not waiting for extraction into a separate Agent.Workbench Application.
Applications may optionally provide product-specific reducers through:
src/application/state/applicationReducers.ts
The current Agent.Workbench Application composition does not require meaningful product-specific Redux state.
That is valid.
Application reducers must not override Template-owned reducer keys.
Detailed documentation:
doc/redux-state-management.md
Reusable React navigation belongs to Template.
Core does not own React navigation infrastructure.
Current navigation ownership is defined by:
doc/architecture/decisions/ADR-0005-navigation-infrastructure-in-template.md
Template owns:
- navigation infrastructure
- Template navigation definitions
- standard Agent.Workbench navigation
- Template screen registration
- reusable visibility integration
- menu ordering
Application owns:
- Application-specific navigation extensions
- Application-specific screens
Authentication responsibilities are split.
Core
|
+-- technical authentication helpers
+-- technical auth types
+-- technical request integration
Template
|
+-- login experience
+-- session orchestration
+-- reusable auth state
+-- logout orchestration
Application
|
+-- concrete product-specific auth behavior where required
Detailed documentation:
doc/authentication.md
Server responsibilities are also split.
Core
|
+-- normalization
+-- validation
+-- technical checks
+-- environment detection
Template
|
+-- server-selection state
+-- connectivity state
+-- server-selection UI
+-- reconnect orchestration
Application
|
+-- product-specific server configuration where required
Detailed documentation:
doc/server-check-and-switching.md
Update ownership follows the same architecture.
Core
|
+-- technical update helpers
Template
|
+-- update state
+-- hooks
+-- watchers
+-- notifications
+-- dialogs
+-- reusable update orchestration
Application
|
+-- product-specific update behavior where genuinely required
Detailed documentation:
doc/update-system.md
Reusable React presentation belongs to Template.
The design system lives under:
src/template/components/design-system/
Important areas include:
icons/
stylistic/
themed/
ui-elements/
Reusable UI elements include components such as:
- buttons
- cards
- dialogs
- dropdowns
- tables
- tabs
- inputs
- modals
- typography
- icons
Core must not import React presentation components.
Detailed documentation:
doc/components.md
Reusable theme infrastructure is located under:
src/template/styles/
The project uses Unistyles for theme-aware styling.
Example:
const styles = StyleSheet.create((theme) => ({
container: {
backgroundColor: theme.colors.background,
},
}));Global visual behavior should be implemented through the reusable theme/design-system infrastructure where appropriate.
Component-specific layout should remain near the owning component.
API ownership follows responsibility.
Conceptually:
generic technical communication
-> Core where appropriate
reusable Base Template / Agent.Workbench integration
-> Template where appropriate
concrete product business API
-> Application
Generated API implementation should be treated carefully.
Do not broadly move or rewrite generated files during unrelated architecture cleanup.
Concrete consumer Applications should own their product-specific build and deployment configuration.
For example, a future HEMS consumer may own:
HEMS release configuration
HEMS deployment destination
HEMS infrastructure configuration
HEMS build workflow
The Base Template may provide reusable tooling.
The current web.template repository also contains release workflows because it remains runnable and testable itself.
This does not require a separate Agent.Workbench Application repository.
Before exporting the web application, generate the Application configuration:
npm run config:generateRun TypeScript validation:
npx tsc --noEmitRun relevant tests:
npm test -- --runInBandExport:
npx expo export -p webExpo writes the web export to:
dist/
Recommended local sequence:
npm run config:generate
npx tsc --noEmit
npm test -- --runInBand
npx expo export -p webThe production workflow is located at:
.github/workflows/export-put-release.yml
Detailed documentation:
doc/release-workflow.md
Before relying on documentation, verify the committed workflow.
A release build should deterministically generate Application configuration before Expo export.
Desired sequence:
npm ci
|
v
npm run config:generate
|
v
npx expo export -p web
|
v
package
|
v
publish
If the current workflow does not contain the explicit generation step, it should be handled as a release-workflow improvement.
The test workflow is located at:
.github/workflows/export-put-test-release.yml
Detailed documentation:
doc/test-release.md
Production and test deployment behavior must remain distinguishable.
The backend/frontend release-type workflow is independent from whether Agent.Workbench is a separate Application.
Useful architecture checks include:
git grep -n "@/application/" -- src/templateTemplate must not import concrete Application implementation.
Review Application imports with:
git grep -n "@/template/" -- src/applicationApplication may use supported Template integration surfaces.
Do not remove imports blindly based only on grep output.
Before an architecture checkpoint:
npm run config:generate
npx tsc --noEmit
npm test -- --runInBand
git diff --check
git status --shortRuntime validation should also be performed when implementation behavior changed.
Architecture Decision Records are stored under:
doc/architecture/decisions/
Current ADRs include:
ADR-0001-core-first.md
ADR-0002-redux-root-reducer.md
ADR-0003-core-base-template-and-product-applications.md
ADR-0004-separate-menu-engine-and-application-menu.md
ADR-0005-navigation-infrastructure-in-template.md
Current status:
ADR-0001 -> Accepted
ADR-0002 -> Accepted
ADR-0003 -> Accepted
ADR-0004 -> Superseded
ADR-0005 -> Accepted
Important architectural decisions include:
Application --> Template --> Core
Agent.Workbench standard functionality -> Template
HEMS -> concrete Application
Navigation infrastructure -> Template
Application navigation -> extensions only
Application screens -> automatic discovery
Application-specific Redux state -> optional
ADR-0004 remains as historical context.
ADR-0005 is authoritative for current navigation ownership.
Project documentation is maintained under:
doc/
- Architecture Vision
- Core Platform
- Current Architecture State
- Application Contract
- Platform Architecture
- Application Separation
- Project Structure
- Authentication
- Server Check and Switching
- Update System
- File Configuration Upload
- Redux State Management
- Components
The following statements do not describe the accepted architecture:
"Agent.Workbench is a concrete Application."
"Agent.Workbench requires its own Application repository."
"Agent.Workbench state inside Template is transitional."
"Agent.Workbench screens must move into Application."
"Agent.Workbench navigation must move into Application."
"Application owns all menu definitions."
"Application owns all tab definitions."
"menu.properties is planned Application configuration."
"tabs.properties is planned Application configuration."
"featureFlags.properties is planned Application configuration."
"menuFeatureFlags.properties defines menu visibility."
"tabFeatureFlags.properties defines tab visibility."
The current developer-facing configuration is:
application.properties
features.properties
navigation.properties
The central architecture rule is:
Application --> Template --> Core
Core provides reusable technical capabilities.
Template provides the reusable application platform.
Standard Agent.Workbench functionality belongs to Template.
Application provides concrete product composition.
The current repository contains:
src/application/
Agent.Workbench Application composition
src/template/
reusable Base Template
standard Agent.Workbench functionality
src/core/
reusable technical capabilities
Developer-facing Application configuration uses:
application.properties
features.properties
navigation.properties
Application navigation extends Template navigation.
Application screens are discovered automatically.
Application-specific Redux state is optional.
HEMS is a concrete consumer Application.
Future concrete consumer repositories may consume the Base Template without requiring Template to import their implementation.
A separate Agent.Workbench Application repository is not part of the accepted architecture.