Base Template for reusable EnFlexIT web applications.
The repository provides reusable technical capabilities and application-shell functionality for concrete products such as Agent.Workbench, HEMS and future EnFlexIT applications.
The central architecture follows the dependency direction:
Application --> Template --> Core
The Base Template consists of:
Template
Core
Concrete products provide their own Application layer and are intended to live in separate Application repositories.
- About
- Architecture
- Repository Responsibilities
- Requirements
- Working with web.template
- Creating a New Application
- Connecting an Application to web.template
- Updating an Application from web.template
- Application Configuration
- Development
- Build and Deployment
- Project Structure
- Styling
- API
- State Management
- Architecture Decisions
- Documentation
- Architecture Summary
web.template provides reusable functionality for EnFlexIT web applications.
Examples include:
- Application bootstrap
- Authentication and session handling
- Server selection and server checks
- Navigation infrastructure
- Menu and tab infrastructure
- Redux infrastructure
- Design system
- Notifications
- Update infrastructure
- Dynamic content
- Reusable screens
- Runtime utilities
- Technical Core helpers
The repository can currently also be developed and executed as a standalone project.
At the same time, it acts as the Base Template for concrete applications such as Agent.Workbench and HEMS.
The goal is to keep reusable functionality in one common place while concrete products remain independently configurable and developable.
The authoritative dependency direction is:
Application
|
v
Template
|
v
Core
Application contains concrete product functionality.
Examples include:
- Application identity
- Application configuration
- Menus
- Tabs
- Product-specific screens
- Product-specific Redux state
- Branding
- Business logic
- Product-specific backend integration
- Product build configuration
- Product deployment configuration
Application may depend on Template and Core.
Template contains the reusable application shell.
Examples include:
TemplateAppcreateTemplateAppApplicationConfig- Navigation infrastructure
- Menu and tab infrastructure
- Redux infrastructure
- Authentication orchestration
- Session handling
- Server-selection behavior
- Design system
- Notifications
- Update orchestration
- Reusable screens
- Reusable React hooks and components
Template may depend on Core.
Template must not depend on a concrete Application.
Core contains focused reusable technical capabilities.
Examples include:
- Technical authentication helpers
- Technical runtime utilities
- Server normalization and validation
- Technical server detection
- Pure update helpers
- Technical types and utilities
Core must not depend on Template or Application.
The target repository model is:
Base Template Repository
+------------------------+
| Template |
| | |
| v |
| Core |
+-----------+------------+
^
|
+--------------+--------------+
| |
+--------------------------+ +--------------------------+
| Agent.Workbench | | HEMS |
| Application Repository | | Application Repository |
+--------------------------+ +--------------------------+
Future Applications follow the same model.
The Base Template does not contain a runtime mechanism that selects between multiple products.
Each concrete Application supplies its own product configuration and functionality through explicit contracts.
The current repository is still in an incremental migration phase.
Some Agent.Workbench-specific functionality may therefore still physically exist below:
src/template/
Its temporary physical location does not automatically define its final architectural ownership.
To download, install and run the project locally, the following tools are required:
- Git
- Node.js
- npm
The GitHub Actions release workflows currently use:
Node.js 20
npm 10
After installing the required software, verify the installation:
git --version
node -v
npm -vAll three commands should return an installed version.
The Base Template repository can be cloned and executed directly on a developer PC.
Clone the repository:
git clone git@github.com:EnFlexIT/web.template.gitEnter the project directory:
cd web.templateInstall all dependencies:
npm installThe project uses generated Application configuration.
For normal web development, start the application with:
npm run webAlternatively:
npm startThe npm commands should be preferred because npm lifecycle hooks automatically generate the Application configuration before startup.
The application configuration can also be generated manually:
npm run config:generateTypeScript can be checked without generating build output using:
npx tsc --noEmitA typical local setup therefore looks like:
git clone git@github.com:EnFlexIT/web.template.git
cd web.template
npm install
npm run webAfter Metro/Expo has started, the application can be opened in the browser.
The exact development URL is displayed by Expo.
Directly running:
npx expo startis not the preferred normal startup path.
The reason is that direct Expo commands bypass npm lifecycle hooks such as:
prestart
preweb
These hooks currently ensure that the Application configuration is generated before startup.
Concrete products should live in their own Application repositories while
using web.template as their shared Base Template.
Examples are:
Agent.Workbench
HEMS
Future Application
Conceptually:
web.template
βββ Template
βββ Core
Agent.Workbench
βββ Application
HEMS
βββ Application
If the web.template repository provides the GitHub template functionality,
a new Application can initially be created through:
GitHub
|
v
web.template
|
v
Use this template
|
v
Create new repository
The newly created repository is the concrete product repository.
For example:
Agent.Workbench
or:
HEMS
The new repository contains the initial Base Template source while its normal Git remote:
origin
points to the concrete Application repository.
After creating the Application repository, clone it locally:
git clone <application-repository-url>Enter the project:
cd <application-repository-directory>Install its dependencies:
npm installGenerate the Application configuration:
npm run config:generateStart the Application:
npm run webAt this point the Application repository can be developed independently.
The next step is to connect it to the shared web.template repository.
An Application repository uses two Git remotes with different responsibilities.
Conceptually:
Application Repository
|
+-- origin
| |
| +-- concrete Application repository
|
+-- template
|
+-- shared web.template repository
origin points to the concrete product.
For example:
origin -> Agent.Workbench
or:
origin -> HEMS
Application-specific development is pushed to this repository.
template points to the shared Base Template:
EnFlexIT/web.template
Reusable Template and Core changes can be fetched from this repository.
Add web.template as an additional Git remote:
git remote add template git@github.com:EnFlexIT/web.template.gitFetch the Base Template repository:
git fetch templateCreate a local template branch based on the remote Base Template master
branch:
git branch template template/masterThese are the three essential commands for connecting an Application repository with the Base Template:
git remote add template git@github.com:EnFlexIT/web.template.git
git fetch template
git branch template template/masterNo additional setup script is required for this.
Check the configured Git remotes:
git remote -vA correctly configured Application repository should conceptually contain:
origin -> concrete Application repository
template -> EnFlexIT/web.template
You can also inspect all branches:
git branch -aThe Git setup now separates product development from shared Base Template development:
origin
= Application repository
template
= Base Template repository
When reusable functionality changes in web.template, an Application can
retrieve those changes through the template remote.
First fetch the newest Base Template state:
git fetch templateSwitch to the local Template branch:
git switch templateIntegrate the newest remote Template state:
git merge template/masterThe local Template branch now contains the latest fetched Base Template state.
Return to the Application branch.
For example:
git switch masterIf the concrete Application uses another development branch, switch to that branch instead.
Then merge the Template changes into the Application:
git merge templateConceptually:
web.template
|
| git fetch template
v
template/master
|
v
local template branch
|
| git merge template
v
Application branch
Template changes should always be reviewed before completing the merge.
The Application may contain:
- Product-specific configuration
- Product-specific screens
- Product-specific Redux state
- Branding
- Backend integrations
- Build configuration
- Deployment configuration
Merge conflicts therefore have to be resolved according to architectural ownership.
The Git template branch is only a synchronization mechanism.
It is not an additional architecture layer.
The architecture remains:
Application --> Template --> Core
Application-specific developer configuration is stored in:
src/application/config/application.properties
Example:
ApplicationId=agent-workbench
ApplicationTitle=Agent.Workbench
ApplicationLogo=../assets/bild.png
ApplicationContact=admin@xxx
ApplicationOwner=EnFlex.IT
LegalImprintCompanyHomepage=
LegalImprintCompanyName=
LegalImprintEmail=admin@xxxThe configuration intentionally uses simple key-value properties.
Developers should not need to modify TypeScript or JSON files just to configure basic Application metadata.
The configuration generator is located at:
src/template/config/build/generateApplicationConfig.mjs
It generates:
src/application/generated/applicationConfig.generated.ts
Generate the configuration manually with:
npm run config:generateConceptually:
application.properties
|
v
configuration generator
|
v
applicationConfig.generated.ts
|
v
ApplicationConfig
|
v
createTemplateApp(...)
|
v
TemplateApp
The current central Application integration contract is:
ApplicationConfig
Template defines the contract.
Application supplies the concrete values.
The application entry point combines concrete Application configuration with the reusable Template.
Conceptually:
Application
|
v
applicationConfig
|
v
createTemplateApp(applicationConfig)
|
v
TemplateApp
The current application bootstrap is registered through Expo.
When implementing functionality, architectural ownership should be determined before choosing its physical location.
A useful rule is:
Product-specific?
|
+--> Application
Reusable application-shell behavior?
|
+--> Template
Focused technical capability without UI or product ownership?
|
+--> Core
Optionality does not create another architecture layer.
An optional feature may still belong to:
Application
Template
Core
Ownership is determined by responsibility.
The repository currently contains GitHub Actions workflows for production and test releases.
Release and deployment workflows currently still live in web.template
during the architecture migration.
Long term, concrete product release and deployment configuration belongs to the respective Application repository.
Reusable build tooling may remain part of the Base Template.
Before creating a manual web export, generate the Application configuration:
npm run config:generateCheck TypeScript:
npx tsc --noEmitThen export the Expo web application:
npx expo export -p webExpo writes the generated web application to:
dist/
A recommended local validation sequence is therefore:
npm run config:generate
npx tsc --noEmit
npx expo export -p webRelevant automated tests should also be executed before producing a final release.
The current production workflow is located at:
.github/workflows/export-put-release.yml
Workflow name:
Export Put Release
It is started manually through GitHub Actions using:
workflow_dispatch
The currently verified workflow performs:
Checkout
|
v
Setup Node.js 20
|
v
Install npm 10
|
v
npm ci
|
v
Read package version
|
v
Generate timestamp
|
v
npx expo export -p web
|
v
ZIP dist/
|
v
FTP upload
|
v
GitHub release
The production workflow currently requires the following repository secrets:
FTP_UPLOAD_URL
FTP_USER
FTP_PSWD
PROJECT_NAME
PROJECT_PATH
The generated ZIP archive follows this pattern:
<PROJECT_NAME>_<package.version>_<yyyyMMdd-HHmm>.zip
For example:
Agent.Workbench_0.0.4_20260811-0915.zip
The actual project name is supplied through:
PROJECT_NAME
The GitHub release uses:
v<package.version>
For example:
v0.0.4
The production workflow currently executes:
npx expo export -p webdirectly.
It does not currently explicitly execute:
npm run config:generateimmediately before the export.
Direct Expo commands do not invoke npm lifecycle hooks.
Therefore the generated Application configuration is not currently guaranteed to be refreshed immediately before the production export.
The desired production sequence is:
npm ci
|
v
npm run config:generate
|
v
npx expo export -p web
|
v
package
|
v
publish
This workflow change should be implemented and tested separately.
Detailed production release documentation is available at:
doc/release-workflow.md
The test release workflow is located at:
.github/workflows/export-put-test-release.yml
It provides a separate release path for testing and internal validation.
Production and test releases must remain clearly distinguishable.
Detailed documentation is available at:
doc/test-release.md
The current main source structure is:
src/
βββ api/
βββ application/
β βββ config/
β βββ generated/
β βββ state/
βββ core/
β βββ authentication/
β βββ runtime/
β βββ server/
β βββ update/
βββ template/
βββ application/
βββ authentication/
βββ components/
βββ config/
βββ hooks/
βββ navigation/
βββ permissions/
βββ runtime/
βββ screens/
βββ state/
βββ styles/
βββ update/
Contains API definitions and generated API implementations.
Generated API code should not be broadly moved or rewritten without carefully reviewing the resulting changes.
Contains concrete Application integration.
Current areas include:
src/application/config/
src/application/generated/
src/application/state/
config contains developer-facing Application configuration.
generated contains generated TypeScript configuration.
state contains Application-owned Redux integration.
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 reusable application-shell functionality.
Current 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/
Contains the reusable Application bootstrap and integration contract.
Important files include:
ApplicationConfig.ts
ApplicationConfigContext.tsx
createTemplateApp.tsx
TemplateApp.tsx
Contains reusable React Native components.
Important areas include:
design-system/
developer-tools/
dynamic-content/
layout/
localization/
notifications/
rich-text-editor/
Contains reusable UI primitives and presentation components.
Important areas include:
icons/
stylistic/
themed/
ui-elements/
Contains reusable navigation, menu and tab infrastructure.
Concrete Application menu and tab configuration should be supplied by the Application layer.
Contains Redux infrastructure and Template-owned Redux state.
Redux is a technology and not an architecture layer.
State belongs to the architectural owner of the corresponding functionality.
Contains the current Redux store infrastructure.
The existing runtime store and root reducer remain active.
The repository also contains a prepared extensible store composition for combining Template reducers with Application reducers.
This new store factory is prepared infrastructure and must not be treated as the active runtime store until it has intentionally been connected and tested.
Contains reusable theme and styling infrastructure.
Contains reusable update orchestration and update watchers.
The project uses Unistyles for reusable theme-aware styling.
Styling responsibilities are separated between:
Theme definitions
Themed primitives
Stylistic components
Reusable UI elements
Component-specific layout
Reusable styling infrastructure is located under:
src/template/styles/
Theme-specific values such as:
- Colors
- Typography
- Global visual properties
should be defined at the theme level where appropriate.
Component-specific layout properties such as:
- Margin
- Padding
- Alignment
- Flex behavior
- Local component composition
remain close to their corresponding component.
For example, layout behavior for the reusable header is located under:
src/template/components/layout/Header.tsx
The reusable design system is located at:
src/template/components/design-system/
Important areas include:
design-system/
βββ icons/
βββ stylistic/
βββ themed/
βββ ui-elements/
Theme-aware base components are located under:
src/template/components/design-system/themed/
Stylistic components are located under:
src/template/components/design-system/stylistic/
Reusable UI elements are located under:
src/template/components/design-system/ui-elements/
Examples include:
- Buttons
- Cards
- Dialogs
- Dropdowns
- Tables
- Tabs
- Inputs
- Modals
- Common visual building blocks
Detailed component documentation is available at:
doc/components.md
The project uses Unistyles as its current styling solution.
Theme-aware styles can be declared through the Unistyles StyleSheet API.
Example:
const styles = StyleSheet.create((theme) => ({
container: {
backgroundColor: theme.colors.background,
},
}));The current application imports the Unistyles configuration during bootstrap.
When changing global visual behavior, prefer extending the reusable theme or design-system infrastructure instead of duplicating equivalent styles across screens.
API-related source code is located below:
src/api/
OpenAPI-based integrations are generated where appropriate.
A typical API development workflow is:
API specification
|
v
Update local API definition
|
v
Generate API implementation
|
v
Review generated changes
|
v
Use generated client
Generated API files should be reviewed carefully after regeneration.
Broad automated refactoring of generated files should be avoided.
API ownership follows the architecture responsibility model.
Conceptually:
Generic technical API capability
|
+--> Core or Template
Product-specific backend integration
|
+--> Application
The correct owner depends on responsibility, not simply on whether code communicates with a backend.
The project uses Redux Toolkit.
Redux itself is not an architecture layer.
State belongs to the architectural layer that owns the corresponding functionality.
Conceptually:
Template-owned feature
|
v
Template Redux state
and:
Application-owned feature
|
v
Application Redux state
The current runtime store is still based on the existing Template store and root reducer.
A new extensible store factory has been prepared to allow Template and Application reducers to be composed safely.
Conceptually:
Template reducers
+
Application reducers
|
v
Combined store
This new composition is currently prepared infrastructure.
It must not be connected to the runtime until the related typing and hook integration are ready and tested.
Detailed Redux documentation is available at:
doc/redux-state-management.md
Architecture Decision Records are stored under:
doc/architecture/decisions/
Current ADRs:
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
ADR-0004 originally assigned reusable menu infrastructure to Core.
ADR-0005 supersedes that ownership decision.
Reusable React navigation infrastructure now belongs to Template.
Concrete product navigation configuration belongs to Application.
The official project documentation is maintained in the doc directory.
The README provides the main developer entry point and an overview of the architecture, setup and development workflow.
Detailed architecture, runtime, feature and release documentation is maintained in the documents listed below.
doc/
- Architecture Vision
- Core
- Current Architecture State
- Application Contract
- Platform Architecture
- Application Separation
- Project Structure
- Authentication
- Server Check and Server Switching
- Update System
- File Configuration Upload
- Redux State Management
- Components
The central architecture rule is:
Application --> Template --> Core
The Base Template contains:
Template
Core
Concrete products contain:
Application
The intended repository structure is:
Base Template Repository
βββ Template
βββ Core
Agent.Workbench Repository
βββ Application
HEMS Repository
βββ Application
Future Application Repository
βββ Application
A concrete Application repository is connected to the Base Template through two Git remotes:
origin
|
+--> Application repository
template
|
+--> web.template repository
The initial Git setup is:
git remote add template git@github.com:EnFlexIT/web.template.git
git fetch template
git branch template template/masterThe architecture migration is incremental.
Existing functionality should first receive:
clear ownership
stable contracts
clear dependency boundaries
safe extension points
before it is physically moved between repositories.