Last updated: Aug 12, 2025, 01:09 PM UTC

Architecture Decision Records (ADRs)

Overview

This document captures the key architectural decisions made in the development of Sasha Studio (ClaudeCodeUI), including the context, decision rationale, and implications of each choice.

ADR-001: Single-Page Application with React

Status

Accepted

Context

We needed a modern, responsive web interface that could handle real-time updates, complex state management, and provide a smooth user experience for AI interactions.

Decision

We chose React as our frontend framework with Vite as the build tool.

Rationale

  • React: Mature ecosystem, excellent component model, strong community support
  • Vite: Fast development builds, optimized production bundles, native ES modules
  • SPA Architecture: Seamless navigation, better performance, offline capabilities

Consequences

  • Fast, responsive user interface
  • Rich ecosystem of components and libraries
  • Excellent developer experience
  • Larger initial bundle size
  • SEO challenges (not critical for this application)

ADR-002: WebSocket for Real-time Communication

Status

Accepted

Context

Claude AI responses stream in real-time, and we need bidirectional communication for interactive features like session management and live updates.

Decision

Implement WebSocket using the ws library for server and native WebSocket API for client.

Rationale

  • Real-time streaming of AI responses
  • Bidirectional communication
  • Lower latency than polling
  • Efficient for long-running connections

Implementation

// Server
const wss = new WebSocketServer({ server });
wss.on('connection', handleConnection);

// Client
const ws = new WebSocket(`wss://${host}/ws?token=${token}`);

Consequences

  • Real-time message streaming
  • Efficient long-lived connections
  • Bidirectional communication
  • Connection state management complexity
  • Requires fallback for network issues

ADR-003: SQLite for Single-User Database

Status

Accepted

Context

As a single-user system, we don't need the complexity of a multi-user database. We need simple, reliable persistence that works across different deployment environments.

Decision

Use SQLite with better-sqlite3 driver for all data persistence.

Rationale

  • Zero configuration required
  • Single file database
  • ACID compliant
  • No network overhead
  • Excellent performance for single-user
  • Easy backup and migration

Schema Design

-- Simplified, denormalized for single-user
users (single row)
company_profiles (organizational context)
onboarding_documents (knowledge base)
research_documents (AI-generated content)

Consequences

  • Simple deployment
  • No database server required
  • Excellent performance
  • Easy backup (single file)
  • Not suitable for multi-user
  • Limited concurrent writes

ADR-004: Claude CLI Integration via Child Process

Status

Accepted

Context

We need to integrate with Anthropic's Claude AI, and the Claude CLI provides a robust, maintained interface with built-in features like tool handling and session management.

Decision

Spawn Claude CLI as a child process rather than direct API integration.

Rationale

  • Maintained by Anthropic
  • Built-in tool handling
  • Session management
  • Resume capability
  • Handles streaming naturally
  • Reduces implementation complexity

Implementation Pattern

const claude = spawn('claude', args, {
    cwd: workingDirectory,
    env: processEnv
});
claude.stdout.on('data', handleStreamedResponse);

Consequences

  • Robust, maintained integration
  • Full Claude feature support
  • Simplified implementation
  • Dependency on CLI availability
  • Process management overhead
  • Potential version compatibility issues

ADR-005: JWT-Based Authentication

Status

Accepted

Context

We need a stateless authentication mechanism that works well with our SPA architecture and can be easily validated across different services.

Decision

Implement JWT (JSON Web Tokens) for authentication with refresh token pattern.

Rationale

  • Stateless authentication
  • Works well with SPAs
  • Can include user claims
  • Standard implementation
  • Easy to validate

Implementation

// Token generation
const token = jwt.sign(
    { userId, username },
    JWT_SECRET,
    { expiresIn: '24h' }
);

// Validation middleware
jwt.verify(token, JWT_SECRET);

Consequences

  • Stateless authentication
  • Scalable approach
  • Standard implementation
  • Token size overhead
  • Cannot revoke tokens (until expiry)

ADR-006: Docker Multi-Stage Build

Status

Accepted

Context

We need consistent deployment across different environments while minimizing image size and maximizing security.

Decision

Use multi-stage Docker builds with Alpine Linux base images.

Rationale

  • Smaller final images
  • Better security (minimal attack surface)
  • Build-time optimization
  • Consistent environments
  • Clear separation of concerns

Build Stages

FROM node:20-alpine AS deps     # Dependencies
FROM node:20-alpine AS builder  # Build assets
FROM node:20-alpine AS runner   # Production

Consequences

  • Smaller images (~200MB vs ~1GB)
  • Better security
  • Faster deployments
  • Clear build process
  • More complex Dockerfile
  • Longer initial builds

ADR-007: Component-Based UI Architecture

Status

Accepted

Context

We need a maintainable, scalable frontend architecture that supports code reuse and clear separation of concerns.

Decision

Implement a component-based architecture with clear hierarchy and composition patterns.

Rationale

  • Reusable components
  • Clear data flow
  • Testable units
  • Maintainable code
  • Team scalability

Component Hierarchy

App
β”œβ”€β”€ Router
β”œβ”€β”€ AuthContext
β”œβ”€β”€ ThemeContext
└── Routes
    β”œβ”€β”€ MainContent
    β”‚   β”œβ”€β”€ ChatInterface
    β”‚   β”œβ”€β”€ FileTree
    β”‚   └── Settings
    └── Sidebar
        β”œβ”€β”€ ProjectList
        └── Navigation

Consequences

  • Highly maintainable
  • Reusable components
  • Clear data flow
  • Easy to test
  • Prop drilling challenges
  • Component composition complexity

ADR-008: Session Protection System

Status

Accepted

Context

Automatic project updates from file system watchers were interrupting active chat sessions, causing poor user experience.

Decision

Implement a session protection system that tracks active conversations and pauses non-critical updates.

Rationale

  • Prevents UI disruption
  • Maintains conversation context
  • Better user experience
  • Selective update control

Implementation

// Track active sessions
const activeSessions = new Set();

// Pause updates during active session
if (!activeSessions.has(sessionId)) {
    updateProjects();
}

Consequences

  • Uninterrupted conversations
  • Better user experience
  • Maintained context
  • Potential stale data
  • Complex state management

ADR-009: File-Based Configuration

Status

Accepted

Context

We need flexible configuration that works across different deployment environments and allows runtime changes without rebuilding.

Decision

Use environment variables with .env files for configuration, with fallback chains for different environments.

Rationale

  • Standard approach
  • Works with Docker
  • Easy to manage
  • Secure (not in code)
  • Runtime configurable

Configuration Hierarchy

1. Environment variables
2. .env file in config directory
3. .env file in root
4. Default values in code

Consequences

  • Flexible configuration
  • Environment-specific settings
  • Secure credential management
  • File permission concerns
  • Configuration drift risk

ADR-010: Markdown as Universal Format

Status

Accepted

Context

We need a common format for storing and processing documents that is human-readable, AI-friendly, and preserves formatting.

Decision

Convert all documents to Markdown for storage and processing.

Rationale

  • Human-readable
  • AI-friendly
  • Preserves formatting
  • Version control friendly
  • Universal support
  • Lightweight

Conversion Pipeline

Upload β†’ Validate β†’ Convert to MD β†’ Store β†’ Index

Consequences

  • Consistent format
  • Easy processing
  • Version control friendly
  • Human-readable
  • Complex document fidelity loss
  • Conversion overhead

ADR-011: Monolithic Deployment

Status

Accepted

Context

As a single-user system with moderate complexity, we need to balance operational simplicity with functionality.

Decision

Deploy as a monolithic application with frontend and backend in a single container.

Rationale

  • Operational simplicity
  • Single deployment unit
  • No service coordination
  • Easier debugging
  • Lower latency
  • Reduced infrastructure cost

Deployment Structure

Container
β”œβ”€β”€ Node.js Server (Express)
β”œβ”€β”€ Static Assets (React build)
β”œβ”€β”€ Claude CLI
└── SQLite Database

Consequences

  • Simple deployment
  • Easy to manage
  • Lower costs
  • Better performance
  • Cannot scale independently
  • Single point of failure

ADR-012: Browser LocalStorage for Caching

Status

Accepted

Context

We need client-side caching for better performance and offline capability without adding complexity.

Decision

Use browser LocalStorage for caching messages and user preferences.

Rationale

  • Simple API
  • Synchronous access
  • Persistent storage
  • No additional dependencies
  • 5-10MB capacity sufficient

Implementation

// Safe storage with quota handling
safeLocalStorage.setItem(key, value);
// Automatic compression for large data
// Automatic cleanup on quota exceeded

Consequences

  • Simple implementation
  • Good performance
  • Offline capability
  • Storage quota limits
  • No cross-device sync
  • Manual cleanup required

Future Architectural Considerations

Potential Changes

  1. Multi-user Support: PostgreSQL + Redis
  2. Microservices: Separate API, AI, and file services
  3. Cloud-Native: Kubernetes deployment
  4. Real-time Collaboration: Operational Transformation/CRDTs
  5. Plugin Architecture: Dynamic tool loading
  6. Multi-model AI: Support for different AI providers

Migration Paths

Each current decision has been made with future migration in mind:

  • SQLite β†’ PostgreSQL (standard SQL)
  • Monolith β†’ Microservices (clear boundaries)
  • LocalStorage β†’ IndexedDB/Cloud Sync
  • Claude CLI β†’ Direct API/Multiple Providers