Data Management & Flow
Relevant source files
The following files were used as context for generating this wiki page:
Data Management & Flow in Furin governs how the framework handles state transfer between the server and client, manages route-specific loader data, and synchronizes mutations. The system supports multiple rendering modes including SSR, SSG, and ISR, while maintaining full TypeScript type inference across the network boundary.
Sources: AGENTS.md, packages/core/README.md
Server-to-Client State Transfer
Furin transfers data from the server to the client using serialized JSON injected into the HTML document. The framework uses specific script tags to hold synchronization data, route data, and head configurations.
Serialization and Injection
The framework serializes data into script tags with specific IDs to ensure the client-side React application can hydrate with the correct state.
| Element ID | Purpose | Data Type |
|---|---|---|
__FURIN_SYNC__ | Idempotent mutation and sync state | JSON |
__FURIN_DATA__ | Route loader data for the current page | JSON |
__FURIN_HEAD__ | Meta, link, and script configurations | JSON |
Sources: packages/core/src/client/document.tsx:162-184
Execution Flow: Document Hydration
The following diagram illustrates how the client retrieves state from the server-rendered HTML during hydration.
The client-side router parses the __FURIN_DATA__ element to extract the loader payload and logical navigation state.
Sources: packages/core/src/client/router/spa-response.ts:85-98
Data Fetching and Transport
Furin supports two primary transport mechanisms for Single Page Application (SPA) navigation and data revalidation.
Data Endpoints
- Runtime Mode (SSR/ISR/Dev): Data is fetched via a central API endpoint:
/_furin/data?path=<logicalHref>. - Static Mode (SSG): Data is fetched from pre-rendered NDJSON files:
<logicalPathname>/__furin_data.ndjson.
Sources: packages/core/src/client/router/spa-response.ts:108-121
Response Classification
The framework classifies responses into four categories to determine the appropriate client-side action:
- ok: Successful data retrieval (Status 200-299).
- error: Contains a
__furinErrorpayload with digest and status. - not-found: Server returns a 404 status or a
__furinStatus: 404sentinel. - bail: The response is invalid or missing data; the browser takes over for a full reload.
Sources: packages/core/src/client/router/spa-response.ts:25-49
Mutation Synchronization (Furin Sync)
Furin implements replayable mutations through the furinSync plugin. This system ensures mutations are idempotent, requiring an Idempotency-Key header for non-streaming effects.
Sync Adapters and Persistence
Sync state can be stored in different backends depending on the environment:
- SQLite (:memory:): Restricted to development and testing.
- File-backed SQLite: Used for single-host deployments.
- PostgreSQL/Redis: Recommended for multi-host replicas to maintain consistency.
Sources: packages/core/README.md:32-38
Sync Flow Diagram
Revalidation headers (x-furin-revalidate) are used to trigger targeted data refreshes in the client after mutations occur.
Sources: packages/core/tests/runtime/multi-instance/multi-instance.integration.test.ts:167-175
Development Mode Data Flow
In development, Furin manages a specialized data flow to support Hot Module Replacement (HMR) and error reporting without full server restarts.
Module Virtualization
The framework uses a virtual namespace (furin-dev-page) to keep page modules out of Bun's native --hot watcher. This prevents a full server process restart when only a React component changes.
Error Propagation
Errors occurring during transformation or rendering are captured and pushed to the client via WebSockets.
| Endpoint | Purpose |
|---|---|
/_furin/dev/errors | WebSocket for real-time error events |
/_furin/dev/error-overlay.js | Client-side script to render the UI overlay |
Sources: packages/core/src/client/dev-error-overlay.js:4-10, 241-260
Multi-instance Isolation
Furin supports mounting multiple framework instances within a single Elysia parent. Data flow is isolated per instance using URL prefixes.
- Instance Prefixing: Each instance manages its own routes and data endpoints under a unique prefix (e.g.,
/admin). - State Isolation: Revalidation headers and sync streams are scoped to the specific instance ID and prefix.
- Collision Guard: The framework throws an error if two instances attempt to mount on the same prefix.
Sources: packages/core/tests/runtime/multi-instance/multi-instance.integration.test.ts:133-157
Summary
Data Management & Flow in Furin is characterized by a strong separation between the server-side loader execution and client-side hydration. By leveraging serialized JSON injection, idempotent sync adapters, and virtualized module loading in development, Furin provides a predictable environment for high-performance React applications built on Elysia and Bun.