Frontend Building Blocks

April 18, 2026 · View on GitHub

Typed catalog of building blocks used in this project. Each block has a fixed name, layer, composition rules, and canonical example.

How to Use

Read the rule file for each block you are about to implement. The summaries below are for routing — the rule files contain the full pattern.

Block Catalog

Data Fetching

BlockLayerSummaryFile
mutation-options-factorylib/api/Reusable mutationOptions() factories with domain error translation. Composed by mutation-hook in providers/.rules/mutation-options-factory.md
mutation-hookproviders/Server write via useMutation composed from mutation-options-factory, with cache invalidation. Returns [handler, isPending].rules/mutation-hook.md
query-options-factorylib/api/Reusable queryOptions() factories — no hooks, no useQuery. Hook composition belongs in providers/.rules/query-options-factory.md
query-keys-factorylib/api/Hierarchical as const key tuples per resource. Single source of truth for cache invalidation.rules/query-keys-factory.md
dto-modellib/api/TypeScript interfaces mirroring the raw API wire format. No transformations.rules/dto-model.md

State Management

BlockLayerSummaryFile
storeapplication/Zustand store — small, focused, selector-only subscriptions. Actions live inside the store.rules/store.md
providerproviders/Thin React Context wrapper for dependency injection. No logic — delivers state, doesn't manage it.rules/provider.md

App Orchestration

BlockLayerSummaryFile
use-case-hookapplication/Orchestrates mutation + notification into one feature-level operation.rules/use-case-hook.md

Component Patterns

BlockLayerSummaryFile
notification-hookapplication/Maps operation outcomes to toast notifications. One hook per use case.rules/notification-hook.md
pure-componentcomponents/Props in, JSX out. No side effects, no internal state beyond useMemo.rules/pure-component.md
compound-componentcomponents/Dot-notation sub-components. Composition over configuration — no boolean prop toggles.rules/compound-component.md
formcomponents/Context-driven form via useForm + FormProvider + field components.rules/form.md
hoccomponents/Component in → enhanced component out. For render-level decisions (auth gates, suspense wrappers).rules/hoc.md
error-boundarycomponents/Scoped error handling for a feature component with its own query.rules/error-boundary.md
pagepages/Route-level orchestrator. Only place where router coupling is acceptable.rules/page.md
facade-hookcomponents/Private logic extraction for a single component. Defined below the component, not exported.rules/facade-hook.md
named-effectcomponents/Named function expressions in useEffect. Intent visible at a glance.rules/named-effect.md

Data Modeling

BlockLayerSummaryFile
frontend-modelmodels/UI-friendly domain objects mapped from DTOs. Skip if DTO shape is identical.rules/frontend-model.md
value-objectapplication/Static-method classes grouping domain logic for a single concept. Namespace, not instance.rules/value-object.md

Rules

  • Block files live in rules/ — one file per block.
  • Each file contains: description, constraints, and a canonical code example.
  • Block names are stable identifiers referenced in specs and task breakdowns.