viuex server only architecture
Vibex Server-Only Architecture Proposal
Section titled “Vibex Server-Only Architecture Proposal”Current Architecture Issues
Section titled “Current Architecture Issues”Current State:
- VibexDataManager runs on both client and server
- Client:
VibexDataManager→DatabaseDataAdapter→ API routes →SupabaseDatabaseAdapter→ DB - Server:
VibexDataManager→SupabaseDatabaseAdapter→ DB (direct) - React hooks directly call
VibexDataManagermethods
Problems:
- DatabaseDataAdapter depends on API routes - creates circular dependency concerns
- Complex client/server detection logic -
getVibexDataManager()has branching logic - Security concerns - client bundle includes data access logic
- Unclear boundaries - where does client logic end and server logic begin?
Proposed Architecture
Section titled “Proposed Architecture”Core Principle: Vibex = Server-Only, React = Client-Only
Section titled “Core Principle: Vibex = Server-Only, React = Client-Only”┌─────────────────┐│ React Client │ (Client Components)│ - useVibex* ││ - UI Logic │└────────┬────────┘ │ │ HTTP / Server Actions │ ▼┌─────────────────┐│ API Routes / │ (Server Components)│ Server Actions ││ - Auth ││ - Validation │└────────┬────────┘ │ ▼┌─────────────────┐│ Vibex Core │ (Server-Only)│ - DataManager ││ - Space ││ - XAgent ││ - Storage │└────────┬────────┘ │ ▼┌─────────────────┐│ Database / ││ File System │└─────────────────┘Benefits
Section titled “Benefits”1. Clear Separation of Concerns
Section titled “1. Clear Separation of Concerns”- Server: Data access, business logic, agent orchestration
- Client: UI, user interactions, state management
2. Better Security
Section titled “2. Better Security”- No database credentials in client bundle
- All data access goes through controlled API routes
- Easier to add authentication, authorization, rate limiting
3. Simpler Architecture
Section titled “3. Simpler Architecture”- Remove
DatabaseDataAdapterentirely - Remove client/server detection logic
- Single code path: API → Vibex → Database
4. Better Next.js Alignment
Section titled “4. Better Next.js Alignment”- Uses Server Actions for mutations
- Uses API routes for queries
- Leverages React Server Components
5. Easier Testing
Section titled “5. Easier Testing”- Server logic can be tested independently
- Client logic is pure UI
- Clear boundaries for mocking
Implementation Plan
Section titled “Implementation Plan”Phase 1: Create Server Actions Layer
Section titled “Phase 1: Create Server Actions Layer”New File: app/src/vibex/server/actions.ts
"use server";
import { getVibexDataManagerServer } from "../data/manager";
export async function getSpace(spaceId: string) { const manager = getVibexDataManagerServer(); return await manager.getSpace(spaceId);}
export async function listSpaces(filters?: SpaceFilters) { const manager = getVibexDataManagerServer(); return await manager.listSpaces(filters);}
export async function createSpace(space: Partial<Space>) { const manager = getVibexDataManagerServer(); return await manager.createSpace(space);}
export async function updateSpace(spaceId: string, updates: Partial<Space>) { const manager = getVibexDataManagerServer(); return await manager.updateSpace(spaceId, updates);}
// ... more actionsPhase 2: Update React Hooks to Use Server Actions
Section titled “Phase 2: Update React Hooks to Use Server Actions”Update: app/src/vibex/react/hooks.ts
"use client";
import { use, useState, useEffect } from "react";import * as vibexActions from "../server/actions";
export function useVibexSpace(spaceId: string | null | undefined) { const [space, setSpace] = useState<Space | null>(null); const [loading, setLoading] = useState(true); const [error, setError] = useState<Error | null>(null);
useEffect(() => { if (!spaceId) { setSpace(null); setLoading(false); return; }
setLoading(true); vibexActions.getSpace(spaceId) .then(setSpace) .catch(setError) .finally(() => setLoading(false)); }, [spaceId]);
const updateSpace = async (updates: Partial<Space>) => { if (!spaceId) throw new Error("No space ID"); setLoading(true); try { const updated = await vibexActions.updateSpace(spaceId, updates); setSpace(updated); return updated; } finally { setLoading(false); } };
return { space, loading, error, updateSpace };}Phase 3: Remove Client-Side Vibex Code
Section titled “Phase 3: Remove Client-Side Vibex Code”Remove:
DatabaseDataAdapter(no longer needed)getVibexDataManager()client detection logic- Client-side VibexDataManager instantiation
Keep:
SupabaseDatabaseAdapter(server-only)LocalDataAdapter(for CLI/server scripts)VibexDataManager(server-only)
Phase 4: Update API Routes
Section titled “Phase 4: Update API Routes”Current API routes already use server-side adapters - no changes needed!
import { getServerDataAdapter } from "@/vibex/data/factory";
export async function GET() { const adapter = getServerDataAdapter(); // Already server-only! const spaces = await adapter.getSpaces(); return NextResponse.json({ spaces });}Migration Strategy
Section titled “Migration Strategy”Step 1: Create Server Actions (Week 1)
Section titled “Step 1: Create Server Actions (Week 1)”- Create
app/src/vibex/server/actions.ts - Wrap all VibexDataManager methods
- Add error handling and validation
Step 2: Update React Hooks (Week 1-2)
Section titled “Step 2: Update React Hooks (Week 1-2)”- Replace
useVibex()calls with server actions - Update all hooks to use
vibexActions.* - Test with existing components
Step 3: Remove Client Code (Week 2)
Section titled “Step 3: Remove Client Code (Week 2)”- Remove
DatabaseDataAdapter - Simplify
VibexDataManager(remove client detection) - Update factory to only create server adapters
Step 4: Add Real-Time Support (Week 3)
Section titled “Step 4: Add Real-Time Support (Week 3)”- Use WebSockets or Server-Sent Events
- Or use Supabase Realtime subscriptions
- Update hooks to subscribe to changes
Real-Time Updates
Section titled “Real-Time Updates”Option A: Server-Sent Events (SSE)
Section titled “Option A: Server-Sent Events (SSE)”export async function GET(request: NextRequest) { const stream = new ReadableStream({ start(controller) { const manager = getVibexDataManagerServer(); const unsubscribe = manager.subscribeToSpace(spaceId, (space) => { controller.enqueue(`data: ${JSON.stringify(space)}
`); });
request.signal.addEventListener('abort', () => { unsubscribe(); controller.close(); }); }, });
return new Response(stream, { headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', }, });}Option B: Supabase Realtime
Section titled “Option B: Supabase Realtime”// Use Supabase Realtime subscriptions// VibexDataManager can subscribe to database changes// React hooks can use SWR with revalidationTrade-offs
Section titled “Trade-offs”✅ Pros
Section titled “✅ Pros”- Simpler: One code path, no client/server branching
- Secure: No DB access from client
- Maintainable: Clear boundaries
- Scalable: Easy to add caching, rate limiting
⚠️ Cons
Section titled “⚠️ Cons”- Network overhead: Every action requires HTTP round-trip
- Less optimistic: Can’t update UI immediately
- More API routes: Need to expose all operations
- Real-time complexity: Need WebSockets/SSE for subscriptions
Mitigations
Section titled “Mitigations”- Optimistic updates: Use React state + server confirmation
- Caching: Use SWR/React Query for client-side caching
- Batching: Combine multiple operations in single request
- Streaming: Use Server Actions with streaming responses
Recommendation
Section titled “Recommendation”✅ YES - Make Vibex server-only
This aligns with:
- Next.js App Router best practices
- Security best practices
- Clear separation of concerns
- Easier to maintain and test
The trade-offs (network overhead, optimistic updates) can be mitigated with:
- Server Actions (Next.js built-in)
- SWR/React Query (client-side caching)
- Optimistic UI patterns
- Streaming responses
Next Steps
Section titled “Next Steps”- Create server actions layer
- Update React hooks
- Remove DatabaseDataAdapter
- Test with existing components
- Add real-time support if needed