pianorhythm-ssr

Architecture Overview

PianoRhythm is a sophisticated multiplayer musical collaboration platform built with a modern, multi-layered architecture designed for real-time performance and scalability.

System Architecture Diagram

graph TB
    subgraph "Client Layer"
        UI[SolidJS UI Components]
        Services[Service Layer]
        Audio[Audio Service]
        WS[WebSocket Service]
    end
    
    subgraph "Core Engine (Rust/WASM)"
        Core[pianorhythm_core]
        Synth[Audio Synthesizer]
        Renderer[Bevy 3D Renderer]
        Proto[Protocol Buffers]
    end
    
    subgraph "Server Layer"
        SSR[Vinxi SSR Server]
        API[REST API Endpoints]
        WSServer[WebSocket Server]
        Auth[Authentication]
    end
    
    subgraph "Data Layer"
        MongoDB[(MongoDB)]
        Assets[Asset Storage]
        CDN[CDN/GitHub Pages]
    end
    
    UI --> Services
    Services --> Audio
    Services --> WS
    Audio --> Core
    WS --> Core
    Core --> Synth
    Core --> Renderer
    Core --> Proto
    
    WS --> WSServer
    Services --> API
    API --> SSR
    SSR --> MongoDB
    API --> Auth
    Auth --> MongoDB
    
    CDN --> Assets
    SSR --> CDN

Core Components

1. Frontend Layer (SolidJS)

Technology Stack:

Key Responsibilities:

2. Core Engine (Rust/WebAssembly)

Technology Stack:

Key Responsibilities:

3. Server Layer

Technology Stack:

Key Responsibilities:

4. Data Layer

Technology Stack:

Key Responsibilities:

Communication Patterns

1. Frontend ↔ Core Engine

// Service Layer communicates with Rust core via WASM
const coreService = appService().coreService();
coreService?.send_app_action(action);

// Core engine emits events back to frontend
window.addEventListener("app_events", (event) => {
  handleCoreEvent(event.detail);
});

2. Client ↔ Server

// WebSocket for real-time communication
websocketService().connect(wsIdentity);
websocketService().emitServerCommand(["JoinRoom", roomName]);

// REST API for data operations
const response = await fetch("/api/v1/rooms", {
  method: "POST",
  body: JSON.stringify(roomData)
});

3. Protocol Buffer Serialization

// Efficient binary serialization for real-time data
const action = AppStateActions.create({
  action: AppStateActions_Action.SynthAction,
  audioSynthAction: AudioSynthActions.create({
    action: AudioSynthActions_Action.NoteOn,
    // ... note data
  })
});

Key Architectural Patterns

1. Service-Oriented Architecture

The frontend uses a service layer pattern with dependency injection:

// Services are registered and injected via solid-services
const appService = useService(AppService);
const audioService = useService(AudioService);
const websocketService = useService(WebsocketService);

2. Event-Driven Communication

// Event buses for loose coupling
const appStateEvents = createEventBus<AppStateEvents>();
appStateEvents.emit(AppStateEvents.UserJoined);

3. Dependency-Based Initialization

// Robust initialization system prevents race conditions
await initializationService().executeStep(InitializationStep.AudioService, {
  execute: async () => {
    await audioService().initialize();
  }
});

4. Reactive State Management

// SolidJS reactive primitives with Immer for immutability
const [users, setUsers] = createImmerSignal<UserClientDomain[]>([]);
setUsers(users => {
  users.push(newUser);
});

Performance Considerations

1. WebAssembly Optimization

2. Real-time Audio

3. 3D Rendering

4. Network Optimization

Scalability Features

1. Horizontal Scaling

2. Caching Strategy

3. Resource Management

Security Architecture

1. Authentication & Authorization

2. Data Protection

3. Real-time Security

Cross-Platform Support

1. Web Application

2. Desktop Application

3. Environment Detection

// Adaptive features based on platform
const COMMON = {
  IS_WEB_APP: !IS_DESKTOP_APP,
  IS_DESKTOP_APP: self["__TAURI__"] != null,
  IS_MOBILE: /android|ios/.test(navigator.userAgent)
};

Next Steps