From 23ee1377e3cfeeb2ff80a3285d8eafd978a91ff7 Mon Sep 17 00:00:00 2001 From: Adam Haeger Date: Tue, 23 Sep 2025 10:39:26 +0200 Subject: [PATCH 1/5] ADR created --- adr/002-backend-data-initialization.md | 187 +++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 adr/002-backend-data-initialization.md diff --git a/adr/002-backend-data-initialization.md b/adr/002-backend-data-initialization.md new file mode 100644 index 0000000000..55b4841c7b --- /dev/null +++ b/adr/002-backend-data-initialization.md @@ -0,0 +1,187 @@ +# ADR: Move most initial data loading to app-backend + +- **Status:** Proposed +- **Date:** 2025-09-23 +- **Owner:** Team Studio +- **Related:** Altinn/altinn-studio#16309 (Epic) ([GitHub][1]) + +## Context + +Today `app-frontend` bootstraps by mounting a stack of query providers (TanStack Query), each fetching pieces of application/instance/party/config data on load. This creates: + +- Many requests and duplicated invalidation logic +- Complex provider/effect nesting and brittle boot order +- Longer TTFB/TTI and heavier cognitive load for app developers + +Epic #16309 proposes shifting _initial_ data orchestration to `app-backend` and delivering a consolidated payload to the client at bootstrap, reducing round trips and complexity. ([GitHub][1]) + +## Decision + +We will: + +1. **Generate the bootstrap HTML in `HomeController` (app-backend).** + Backend takes ownership of serving the app shell (replaces handcrafted Index.cshtml). ([GitHub][1]) +2. **Adopt path-based routing (no `HashRouter`).** + Backend resolves/serves deep links, delegating route rendering to `app-frontend`. Back-compat preserved for legacy hash URLs (see Rollout). ([GitHub][1]) +3. **Embed immutable “AppData” in the HTML.** + Static, versionable, cross-variant data is serialized into a global (e.g., `window.AltinnAppData = {...}`) in the bootstrap page. ([GitHub][1]) +4. **Provide an “InitialInstanceData” bundle when opening an existing instance.** + When backend detects an instance context, it embeds (or exposes via single endpoint) the static-at-boot instance data adjacent to `AppData`, so the client does not immediately refetch/invalidate. Further interactions use targeted APIs. ([GitHub][1]) +5. **Remove RuleHandler/RuleConfiguration in this major.** + Do not migrate them to the new boot flow (handled by separate task). ([GitHub][1]) + +In scope: catalog and migrate all initial queries across stateless, stateless-anon, and stateful apps. Out of scope: data that must be updated _after_ boot. ([GitHub][1]) + +```mermaid +graph LR +A[User's Browser]:::actor + +subgraph S1["Before — frontend orchestrates boot"] +A --> FFE[app-frontend] +FFE -->|fetch on mount| Q1[GET /texts] +FFE -->|fetch on mount| Q2[GET /app-metadata] +FFE -->|fetch on mount| Q3[GET /profile/party] +FFE -->|fetch on mount| Q4[GET /instances?active=true] +FFE -->|fetch on mount| Q5[GET /orgs] +FFE -->|fetch on mount| Q6[GET /ui-config] +FFE -.-> FX[Complex provider/effect graph] +end + +subgraph S2["After — backend assembles initial payload"] +A --> BE[app-backend HomeController] +BE -->|orchestrates| P1[(Platform APIs)] +P1 --> BE +BE -->|Bootstrap HTML + AppData + InitialInstanceData| A +A --> FFE2[app-frontend hydrate & render] +FFE2 -->|seed query cache| QC[Dehydrated caches] +FFE2 -->|targeted fetch on demand| P2[(Platform APIs)] +end + +subgraph R["Routing change"] +H1[Legacy hash routes] -->|301/compat| PATH[Path-based URLs] +end + +classDef actor fill:#eef,stroke:#77f,color:#000 +``` + +## Rationale + +- **Performance:** Fewer requests and no waterfall; better TTFB/TTI by shipping what the app needs up front. +- **Simplicity:** One place orchestrates initial data; frontend boot becomes deterministic. +- **Reliability:** Backend can decide what to load based on route/instance/party and enforce pagination/limits. +- **Security:** Backend can apply authz, shape data, and set cache headers consistently before client executes. + +## Considered Options + +1. **Status quo (frontend-orchestrated queries).** + Rejected: retains complexity and network overhead. +2. **SSR/streaming React for all routes.** + Rejected for now: higher cost/risk; we only need consolidated data at boot, not full SSR. +3. **Bulk endpoints.** + Rejected: increases backend complexity without clear benefit vs app-backend controller. + +## Technical Notes (non-normative) + +- **Bootstrap contract** + + ```html + + + + + ``` + + Prefer ` ``` - Prefer `