diff --git a/docs/state-management.md b/docs/state-management.md
index 24fa7c6d..6dca54af 100644
--- a/docs/state-management.md
+++ b/docs/state-management.md
@@ -2,10 +2,10 @@
## The Rule
-| Data type | Where it lives |
-| ----------------------------------------------------------------------- | ---------------------------------------- |
-| Server data (creators, holdings, activity feed) | React Query (`useQuery` / `useMutation`) |
-| Ephemeral UI state (modals, input values, selected tabs, loading flags) | Local `useState` |
+| Data type | Where it lives |
+| --- | --- |
+| Server data (creators, holdings, activity feed) | React Query (`useQuery` / `useMutation`) |
+| Ephemeral UI state (modals, input values, selected tabs, loading flags) | Local `useState` |
If the value came from an API response and needs to survive a component unmount or be shared across routes, put it in React Query. If it only controls what the user sees right now and can be re-derived on re-mount, use `useState`.
@@ -20,7 +20,9 @@ queryClient.invalidateQueries({ queryKey: queryKeys.creators.list() });
This marks cached data stale and lets React Query refetch in the background the next time the query is observed. Use this after a buy, sell, or profile update so all subscribers see fresh data automatically.
-**Refetch manually** only when you need to force an immediate reload independent of staleness — for example, a user-triggered "Refresh" button:
+## Refetch manually
+
+Refetch manually only when you need to force an immediate reload independent of staleness — for example, a user-triggered "Refresh" button:
```ts
const { refetch } = useQuery({ queryKey: queryKeys.wallet.holdings(address), ... });
@@ -37,12 +39,9 @@ Storing a React Query result in `useState` breaks cache coherence and causes sta
```tsx
function CreatorProfile({ id }: { id: string }) {
- const { data } = useCreatorDetail(id);
-
- // Never do this — local state diverges from the cache after mutations.
- const [creator, setCreator] = useState(data);
-
- return
;
}
```
## Ephemeral UI State Examples
These belong in `useState`, not React Query:
-
- Modal open/closed: `const [open, setOpen] = useState(false)`
- Controlled input value: `const [query, setQuery] = useState('')`
- Active tab: `const [activeTab, setActiveTab] = useState('overview')`
- Optimistic loading flag: `const [submitting, setSubmitting] = useState(false)`
-None of these values need to survive a page navigation or be shared with another component tree, so there is no reason to put them in the server-state layer.
+---
+
+## Handling Asynchronous States (Loading, Error, Data)
+
+To avoid inconsistent layout shift and unhandled application crashes, every page component introducing server mutations or asynchronous fetching must explicitly handle the three lifecycle states: **Loading**, **Error**, and **Data**.
+
+### 1. The Three-State Pattern Flowchart
+1. **Loading State:** Immediately show a structural fallback layout matching the structural scale of the destination layout. Never present empty blank states or unformatted spinning animations.
+2. **Error State:** Intercept request faults gracefully. Provide an isolated contextual failure notice alongside a trigger to manually execute a `refetch()` query call.
+3. **Data State:** Render layout presentation markup smoothly once the data successfully hydrates.
+
+### 2. Choosing a Skeleton Component
+Match your structural loading fallbacks strictly to your structural data card layout sizes:
+* Use `` for complete full-bleed layout views or single entity profile view roots.
+* Use `` wrapped inside layout grids for multi-item entity dashboards, galleries, or listing blocks.
+
+### 3. Error Architecture Strategy: Boundary vs. Inline States
+* **Error Boundaries (`CreatorPageErrorBoundary`):** Use at the route level to safely isolate catastrophic runtime engine failures, critical layout state breakdowns, or complete backend authorization drops across whole pages.
+* **Inline Contextual States (`SectionErrorBoundary`):** Use for sub-components, standalone layout modules, tabs, or localized search bars where a remote service query issue shouldn't block a user from browsing the remainder of the active application canvas. Always supply the React Query context `refetch` callback method directly to retry controls.
+
+### 4. Code Implementation Blueprint
+
+```tsx
+import React from 'react';
+import { useCreatorDetail } from '@/hooks/useCreatorDetail';
+import { CreatorSkeleton } from '@/components/common/CreatorSkeleton';
+
+interface CreatorDashboardPageProps {
+ creatorId: string;
+}
+
+export function CreatorDashboardPage({ creatorId }: CreatorDashboardPageProps) {
+ const { data: creator, isLoading, isError, error, refetch } = useCreatorDetail(creatorId);
+
+ if (isLoading) {
+ return ;
+ }
+
+ if (isError) {
+ return (
+