Architecture
Frontend as Dumb Pipe: No Business Logic in React Layer
Frontend as Dumb Pipe: No Business Logic in React Layer
Principle
The React frontend contains no business logic — only UI/UX behavior. All meaningful data handling is delegated to
the Tauri backend via invoke().
Application to Third-Party Clients
Third-party JS clients (e.g., Supabase JS SDK) are acceptable infrastructure for what they do well — WebSocket lifecycle management, reconnection with backoff, channel subscriptions — but they must act as a dumb pipe.
Correct pattern (Realtime sync):
// realtime-sync.ts — receives event, immediately delegates to backend.on("postgres_changes", { event: "INSERT", table: "block_updates", ... }, () => { // NO payload processing. NO business logic. // Just tell the backend "something changed." invoke("trigger_pull_sync"); })The frontend doesn’t inspect the event payload, doesn’t decide what to do with it, doesn’t transform data. It notifies the backend, and the backend (Rust) handles everything.
Incorrect pattern (anti-pattern):
// DON'T DO THIS — business logic in frontend.on("postgres_changes", { event: "INSERT", table: "block_updates", ... }, (payload) => { const update = parseBlockUpdate(payload.new); // Processing in frontend if (update.deviceId !== currentDeviceId) { // Decision in frontend mergeIntoLocalStore(update); // State mutation in frontend } })Why This Matters
- Single source of truth: All sync logic lives in Rust — no divergent implementations
- Testability: Rust logic is unit-testable without browser environment
- Security: Sensitive operations stay in the backend where they can be audited
- Consistency: The Clean Architecture layers (Domain → Application → Infrastructure) enforce this in Rust; the frontend is just another adapter
Auth Token Bridge
The Supabase JS client needs a valid JWT for RLS-filtered Realtime events. Auth sessions are owned by the Rust backend (keychain). The bridge:
- Tauri command exposes the access token to the frontend
- Frontend calls
supabase.auth.setSession()with the token - On token refresh in Rust, emit a Tauri event so frontend can update
- Frontend never manages tokens directly — it receives them from the backend
References
- Linear: INK-149 (Realtime hookup), INK-150 (auth token bridge)
- Existing:
apps/desktop/src-react/lib/realtime-sync.ts— correct pattern - Existing:
apps/desktop/src-react/hooks/useRealtimeSync.ts— ready but unmounted
Previous
CRDT Binary Must Pass Through Untouched — Never Re-serialize from Materialized Text Next
FTS5 unicode61 Tokenizer Implicitly Indexes Custom Syntax
CRDT Binary Must Pass Through Untouched — Never Re-serialize from Materialized Text Next
FTS5 unicode61 Tokenizer Implicitly Indexes Custom Syntax
Was this page helpful?
Thanks for your feedback!