Skip to the content.

Architecture Decision Record (ADR)

ADR-0030: Framework-Agnostic Frontend Development with Thin UI

We will adopt a framework-agnostic frontend core architecture, where all business logic and application behavior are implemented outside Angular and UI frameworks act only as data visualizer.

1. Status

Draft | Accepted

2. Context

Problem / Need

The frontend application is built using Angular (currently Angular 21). The application is expected to be long-lived, evolve over time, and undergo framework upgrades (Angular major versions) and potentially framework changes (e.g., React, Vite-based UI) with minimal risk and cost. Key challenges identified:

To address these challenges, the team is required to hold a frontend architecture that:

3. Decision

We will adopt a framework-agnostic frontend core architecture, where all business logic and application behavior are implemented outside Angular and UI frameworks. These act only as data visualizers.

Name it as: Service For Component (SFC) (like Backend For Frontend: BFF).

Key decisions:

  1. Framework-Agnostic Core

    • Business logic, workflows, validation, and state transitions are implemented in service layers.
    • The core must not import or depend on Angular or any UI framework.
    • Use browser APIs and standard libraries for cross-framework compatibility instead of Framework-specific libraries.
  2. Layered Responsibility Model

    UI Presenter (Components in frameworks like Angular / React / VueJS / Other)
            ↓
    Application Services (Domain Logic, non [depends on other InversifyJS, TSyringe, ... or plain JS/TS] or less depending from framework)
            ↓
    Resource (HTTP, storage, browser APIs)
    
    • (Angular) components are thin and UI-only.
    • Application services coordinate use cases and expose behavior to the UI. Service layer prepares data for visualization.
    • Domain logic contains pure business rules and is implemented in the service layer.
    • Resource access are data sources.
  3. Thin UI Components

    • UI components must not contain business logic.
    • Components delegate all behavior to application services.
    • Components are responsible only for rendering, event binding, and user interaction.
  4. Service per Component aka SF

    • Feature-level or complex components must have a corresponding application service (facade).
    • Simple presentational components may omit a facade when no behavior exists.
  5. UI-Independent Executability

    • Application services must be executable without Angular or any UI framework.
    • Services can be instantiated and invoked directly using JavaScript or TypeScript.
  6. Developer Console Accessibility

    • In development environments, selected application services may be explicitly exposed on the browser window object for interactive testing and exploration.
    • No Angular services or framework internals may be exposed.
    • This exposure must be disabled in production builds.
  7. Testing Strategy

    • The primary test target is the application service and domain layers.
    • Tests must not require DOM, Angular TestBed, or browser automation.
    • UI tests are limited to wiring, smoke tests, and critical user journeys.
  8. Angular as an data visualizer

    • Angular is treated as an implementation detail of the UI layer.
    • Angular dependency injection may wrap or adapt application services but must not own business logic.

4. Rationale (Justification)

Explain why this decision was made.

4.1. Advantages

4.2. Known drawbacks / accepted risks

5. Alternatives Considered / Considered Options

  1. Traditional Angular Architecture
    • Rejected due to tight coupling, challenging upgrades, and heavy UI-based testing.
  2. UI-First Development with E2E Testing
    • Rejected due to brittle tests, slow feedback, and high maintenance cost.
  3. Micro-Frontends
    • Does not solve core testability and coupling issues by itself.

6. Consequences, Impacts & Follow-up Actions

Describe the consequences of this decision.

Consequences

Positive

Negative / Trade-offs

Enforcement and Guardrails

To ensure the architecture is consistently applied:

Notes

This ADR intentionally prioritizes long-term maintainability, upgradeability, and developer experience over short-term simplicity. The architecture is particularly suitable for large, long-lived frontend applications with complex business logic.