> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reflections.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# ADR-0014: Frontend state and realtime architecture

> Balance server-state correctness, local UI responsiveness, and realtime ingest visibility in the web client.

<Info>**Status:** Accepted **Date:** 2026-02-06 **Deciders:** Reflections Maintainers</Info>

## Context

The web app needs predictable data fetching/caching, lightweight local UI state, and realtime awareness of ingestion/pipeline updates without over-complicating architecture.

## Decision

Adopt a layered frontend state model:

* **Next.js App Router** for route/layout composition.
* **TanStack React Query** for server-state fetching, caching, and invalidation.
* **Zustand** for UI/session-local state slices.
* **Supabase Realtime** broadcast subscription for pipeline status updates, mapped to targeted React Query invalidations.

## Alternatives considered

### Alternative 1: React context + custom fetch cache only

Pros:

* Fewer external dependencies.

Cons:

* Reinvents stale/cache/invalidation semantics.
* More bespoke code and consistency risk.

### Alternative 2: Global Redux-only state for everything

Pros:

* Single state container.

Cons:

* Higher boilerplate for server-state workflows.
* Less natural fit for request lifecycle caching.

### Alternative 3: Polling-only for pipeline updates

Pros:

* Simpler than realtime subscriptions.

Cons:

* Slower UI freshness or higher API load.
* Inferior user feedback during ingestion lifecycle changes.

## Consequences

**Benefits:**

* Clear split between server state and UI-local state.
* Efficient invalidation-based updates for pipeline events.
* Familiar patterns for frontend developers.

**Costs:**

* Multiple state technologies to maintain and document.
* Realtime dependency requires client env and connection health handling.

## Implementation notes

* Query client initialization is in the providers layer.
* Zustand stores handle UI-local state like voice sessions, sidebar, and graph visualization.
* Realtime subscription and cache invalidation are implemented in a dedicated hook that maps pipeline events to React Query invalidations.
* Supabase realtime client lifecycle is encapsulated in a dedicated module.

## Related ADRs

* [ADR-0008: Authentication and RBAC model](/decisions/adr-0008)
* [ADR-0009: API architecture and authorization enforcement](/decisions/adr-0009)
* [ADR-0011: Observability and tracing strategy](/decisions/adr-0011)
