Inkdown
Start writing

Bonkers

1 file·0 subfolders

Shared Workspace

Bonkers
A-Z

A-Z

Shared from "Bonkers" on Inkdown

CREATOR.md - Bonkers Monorepo Architecture Document

System: Bonkers Monorepo Date: March 2026 Author: Principal Engineering Team Purpose: Zero-compromise architecture and engineering knowledge transfer


1. SYSTEM OVERVIEW

1.1 What Is Bonkers

Bonkers is a TypeScript monorepo containing a multi-platform AI application stack.

Applications:

  1. Website (apps/website) - Next.js 14 web application (port 3001)
  2. Extension (apps/extension) - Chrome Extension (Manifest V3, Vite)
  • Arcane (apps/arcane) - Express.js API server (port 8080)
  • Session Manager (apps/session-manager) - Session state synchronization service
  • Shared Packages:

    • packages/app-config - Configuration (models, prompts, feature flags)
    • packages/components - Reusable React components
    • packages/hooks - Custom React hooks
    • packages/types - Shared TypeScript types
    • packages/utils - Utility functions
    • packages/config - ESLint, Prettier, TypeScript configs
    • packages/assets - Static assets

    Infrastructure:

    • Package Manager: pnpm 9.15.5 (workspaces)
    • Build System: Turborepo
    • Backend Framework: Express-Zod-API
    • Database: Firestore (GCP)
    • Cache: Redis
    • Deployment: Vercel (frontend), Cloud Run (backend)
    1.2 Architecture Layers
    Plain text

    2. REPOSITORY STRUCTURE

    2.1 Monorepo Layout
    Plain text
    2.2 Key Configuration Files

    Root package.json:

    JSON

    turbo.json:

    JSON

    pnpm-workspace.yaml:

    YAML

    3. APPLICATION ARCHITECTURE

    3.1 Website (apps/website/)

    Tech Stack: Next.js 14, React 18, TypeScript, Tailwind CSS, shadcn/ui

    Key Files:

    FilePurpose
    middleware.tsAuth routing, locale prefixing, cookie management
    navigation.tsCustom navigation (replaces next/link)
    auth/auth.config.tsNextAuth configuration, token refresh
    auth/auth.cookies.tsCookie configuration for production
    next.config.jsTranspile packages, image domains
    tailwind.config.tsTheme, plugins, typography

    Middleware Flow:

    TypeScript

    Project Requirements:

    • Do NOT use next/link - use custom navigation.ts
    • Do NOT use useRouter from next/navigation - use wrapper
    • All API calls use axios
    • All React queries wrapped in react-query
    3.2 Extension (apps/extension/)

    Tech Stack: Vite, React 18, Manifest V3, Tailwind CSS

    Key Files:

    FilePurpose
    manifest.config.tsExtension manifest (permissions, content scripts)
    src/background/index.tsService worker entry point
    src/background/background.messages.tsMessage handler
    src/contents/index.tsContent script (injected into pages)
    src/lib/storage.tsLocalStorageInstance (NOT chrome.storage)

    Architecture:

    Plain text

    Project Requirements:

    • Do NOT use chrome.storage - use LocalStorageInstance
    • All API calls proxied through background script
    • Content scripts run at document_end
    3.3 Arcane Backend (apps/arcane/)

    Tech Stack: Express, Express-Zod-API, TypeScript, Firebase Admin

    Entry Point: src/index.ts

    TypeScript

    Directory Structure:

    Plain text

    Middleware Chain (execution order):

    TypeScript
    3.4 Session Manager (apps/session-manager/)

    Tech Stack: Express, Express-Zod-API, Firebase Admin, jose

    Purpose: Real-time session state synchronization across devices

    Key Dependencies:

    • express-zod-api - API framework
    • firebase-admin - Auth verification
    • jose - JWT handling
    • @panva/hkdf - Key derivation

    4. BACKEND DEEP DIVE

    4.1 Middleware Architecture

    Init Context (middlewares/initContext/initContext.ts):

    TypeScript

    Auth (middlewares/auth/auth.ts):

    TypeScript

    Usage Limits (middlewares/usageLimits/usageLimits.ts):

    TypeScript

    Thread Preware (middlewares/threadPreware/threadPreware.ts):

    TypeScript
    4.2 Request Context (AsyncLocalStorage)
    TypeScript
    4.3 Models

    User Model (models/user.ts):

    TypeScript

    Thread Model (models/thread.ts):

    TypeScript
    4.4 Repositories

    Context (repositories/context/requestContext.ts):

    TypeScript

    Schema (repositories/engine/schema.ts):

    TypeScript

    Side Actions (repositories/sideActions/sideActions.ts):

    TypeScript

    Streamer (repositories/streamer/streamer.ts):

    TypeScript

    Inter-Request Communication (repositories/irc/irc.ts):

    TypeScript

    5. DATA MODELS

    5.1 User Document
    TypeScript
    5.2 Thread Document
    TypeScript
    5.3 Message Document (V2)
    TypeScript

    6. API ROUTES

    6.1 Public Routes
    RouteMethodDescription
    /v1/public/healthGETHealth check
    /v1/rewardsGETGet rewards
    /v1/register-adsPOSTRegister ad views
    6.2 Private Routes (Auth Required)

    Thread:

    RouteMethodDescription
    /v1/thread/unifiedPOSTMain endpoint
    /v1/thread/stopPOSTStop generation
    /v1/thread/messagePOSTSend message

    Canvas:

    RouteMethodDescription
    /v1/user/canvas/:canvasIdGETGet canvas content
    /v1/user/canvas/:canvasIdPOSTUpdate canvas content

    Canvas Architecture:

    • Canvas content stored in GCP Storage (GCS) as JSON
    • Path: {uid}/canvas/{canvasId}.json
    • Structure: { values: TCanvasValues[], history: { undos: [], redos: [] } }
    • Supports version history with undo/redo
    • Content type: application/json (gzipped)

    User:

    RouteMethodDescription
    /v1/user/statusGETGet user status
    /v1/user/historyGETList history
    /v1/user/settingsGET/POSTGet/set settings
    /v1/user/shareChatPOSTShare chat

    Projects:

    RouteMethodDescription
    /v1/projectsGETList projects
    /v1/projects/createPOSTCreate project
    /v1/projects/:idGET/DELETEGet/archive project

    Tools:

    RouteMethodDescription
    /v1/tools/text/:toolIdPOSTText tools
    /v1/tools/image/:toolIdPOSTImage tools
    /v1/tools/ai-detectorPOSTAI detection

    Wallflower (Image Generation):

    RouteMethodDescription
    /v1/wallflower/image-generationPOSTGenerate images
    /v1/wallflower/imagesGETGet image history
    /v1/wallflower/likePOSTLike image
    /v1/wallflower/pin-imagePOSTPin image

    Full Route List: apps/arcane/src/config/routing.ts


    7. TEMPLATES (WALLFLOWER)

    7.1 Available Templates

    Templates are pre-configured image generation presets:

    Template IDNameModelDescription
    ghibli-styleGhiblifygpt-image-1-mediumConvert to Studio Ghibli style
    watermark-removerWatermark Removergemini-2.0-flash-expRemove watermarks
    product-photographyProduct Photographygpt-image-1-highProfessional product shots
    make-me-baldMake Me Baldgemini-2.0-flash-expBald transformation
    minecraft-styleMinecraft Stylegpt-image-1-mediumMinecraft block style
    simpson-styleSimpson Stylegpt-image-1-highSimpsons cartoon style
    pixar-stylePixar Stylegpt-image-1-highPixar 3D animation style
    humanize-my-petHumanize My Petgpt-image-1-mediumPet to human transformation
    7.2 Template Structure
    TypeScript
    7.3 Template Processing

    Controller: endpoints/wallflower/unified-generation.controller.ts

    TypeScript

    Usage Limits: Templates inherit model config from presets, usage calculated based on model + numberOfImages.


    8. FALLBACK STRATEGIES

    8.1 Generic Fallback Pattern

    Utility: utilities/call-function-with-fallback.ts

    TypeScript
    8.2 Image Generation Fallbacks

    Fal.ai ↔ Replicate Fallback:

    TypeScript

    Fallback Models Map (constantsSchemasAndTypes/wallflower/unified-generation.constants.ts):

    TypeScript
    8.3 Deep Research Fallbacks

    Serp Query Fallback (features/deepResearch/firecrawlSerp.ts):

    1. Primary: Bing-based scraping
    2. Fallback 1: Firecrawl scraping
    3. Fallback 2: Basic URL fetch
    TypeScript

    Google Search Fallback (features/deepResearch/generateSerpQueries.ts):

    TypeScript
    8.4 AI Detection Fallback

    Service: services/aiDetection.ts

    TypeScript

    Usage:

    • endpoints/tools/aiDetection.ts
    • endpoints/tools/public/aiDetectionPublic.ts
    • endpoints/tools/aiEssayMetricsGenerator.ts
    8.5 RAG Embeddings Fallback

    File: endpoints/unified/features/rag.ts

    TypeScript
    8.6 Model Selection Fallback (Merlin Magic)

    File: endpoints/unified/features/merlinMagic.ts

    TypeScript
    8.7 YouTube Transcription Fallback

    File: utilities/youtube/youtube.ts

    TypeScript
    8.8 MCP Tool Result Fallback

    File: utilities/mcp/functions/zapMCPToolResult.ts

    TypeScript
    8.9 Progress Event Fallback Index

    File: constantsSchemasAndTypes/streamer/streamer.constants.ts

    TypeScript

    Usage: When tool result index is not specified, defaults to 0.


    9. CRITICAL ARCHITECTURE DECISIONS

    9.1 Why Express-Zod-API?

    Decision: Use express-zod-api over raw Express, NestJS, Fastify

    Rationale:

    • Type safety with Zod schemas
    • Auto-generated OpenAPI documentation
    • Type-safe API client generation
    • Clean middleware composition
    • Built-in error serialization

    Trade-offs:

    • ✅ Pros: Type safety, auto-docs, less boilerplate
    • ❌ Cons: Learning curve, vendor lock-in
    9.2 Why AsyncLocalStorage?

    Decision: Use Node.js AsyncLocalStorage for request context

    Rationale:

    • No prop drilling across 6+ middleware layers
    • Global access without parameters
    • Request isolation
    • Minimal overhead

    Risk: Single point of failure - if initContext fails, all context access returns empty object

    9.3 Why Firestore?

    Decision: Use Firestore (NoSQL) over PostgreSQL/MySQL

    Rationale:

    • Flexible schema for varying message structures
    • Auto-scaling without sharding
    • Nested data model (Thread → Messages)
    • Firebase Auth integration

    Limitations:

    • No SQL joins (must denormalize)
    • Transactions limited to 25 documents
    • Eventual consistency
    9.4 Why SSE Over WebSockets?

    Decision: Use Server-Sent Events for streaming

    Rationale:

    • HTTP-based, no upgrade handshake
    • Auto-reconnect built-in
    • Firewall friendly
    • One-way is sufficient for streaming

    Trade-offs:

    • ✅ Pros: Simple, low overhead, auto-reconnect
    • ❌ Cons: One-way only, no binary data
    9.5 Why Monorepo?

    Decision: Use pnpm monorepo with Turborepo

    Rationale:

    • Code sharing across apps
    • Atomic commits
    • Consistent tooling
    • Efficient builds (caching, parallelization)

    Trade-offs:

    • ✅ Pros: Code sharing, atomic commits, efficient builds
    • ❌ Cons: Larger repo, coupled deployments

    10. SECURITY

    10.1 Authentication Flow
    Plain text

    Security Measures:

    1. JWT verification (Firebase Admin SDK)
    2. Custom claims for RBAC
    3. User document for additional permissions
    4. Token refresh via NextAuth

    Vulnerabilities:

    VulnerabilityRiskStatus
    JWT token theftHigh✅ Mitigated (short expiry, HttpOnly cookies)
    Custom claims tamperingCritical✅ Mitigated (server-side only)
    Firestore rule bypassCritical✅ Mitigated (all queries through backend)
    CSRFMedium⚠️ Needs review
    10.2 Rate Limiting

    Current: Only guest users rate limited (50 requests / 15 min via Redis)

    Gaps:

    • No rate limiting for authenticated users
    • IP-based (bypassable with rotating IPs)
    • No endpoint-specific limits
    10.3 Input Validation

    Layers:

    1. Zod schemas (all API inputs)
    2. Content moderation (async side action)
    3. Token limits (query size validation)
    4. File type validation (MIME type)

    11. SCALABILITY

    11.1 Current Scaling

    Horizontal Scaling (Cloud Run):

    • arcane (primary)
    • arcane-copy (failover)
    • arcane-deepresearch (specialized)

    Bottlenecks:

    ComponentCurrentAt ScaleSolution
    Firestore writes~1K/secSharding neededShard by user ID
    RedisSingle instanceConnection pool exhaustedRedis Cluster
    LLM APIsRate limited per keyMultiple keysRound-robin keys
    11.2 Performance Optimizations

    Implemented:

    • Async side actions (non-blocking)
    • Redis caching (user settings, model configs)
    • SSE streaming (reduced time-to-first-token)
    • Skip embeddings for large contexts (>6000 tokens)
    • Pre-calculated token counts

    Opportunities:

    • Response caching (identical queries)
    • Embedding caching (RAG queries)
    • Database indexing
    • Connection pooling
    11.3 Memory Management

    Cloud Run Limits: 16GB max, 60min timeout, 4 vCPU

    Memory Leaks to Watch:

    • AsyncLocalStorage context not cleaned up on error
    • Redis IRC subscriptions not cleaned up
    • PassThrough streams not destroyed on error

    Monitoring:

    TypeScript

    12. FAILURE MODES

    12.1 Single Points of Failure
    ComponentImpactRecovery
    Firebase AuthComplete auth failure5-10 min
    FirestoreAll data operations fail10-30 min
    RedisRate limiting, IRC failsImmediate (bypass)
    OpenAI APIGPT models unavailableImmediate (fallback)
    12.2 Error Handling

    Current Pattern:

    TypeScript

    Issues:

    • No retry logic for transient failures
    • No circuit breakers
    • No graceful degradation
    12.3 Database Conflict Resolution

    Retry Logic (Firestore document conflicts):

    TypeScript

    13. DEPLOYMENT

    13.1 Pipelines

    Backend (Cloud Run via cloudbuild.yaml):

    YAML

    Website (Vercel):

    • Auto-deploy on push to develop/review branches
    • Environment variables in Vercel dashboard
    13.2 Environment Variables

    Backend:

    Bash

    Website:

    Bash

    Critical: Environment variables NOT validated at startup - missing vars cause runtime errors.

    13.3 Rollback
    Bash

    14. PRINCIPAL ENGINEER INTERVIEW Q&A

    Q1: How do you ensure atomic writes for related documents?

    Problem: Two Firestore writes can result in orphaned documents if the second fails.

    Current Solution: Retry with document index increment

    TypeScript

    Better Solutions:

    1. Firestore Transactions: Atomic but limited to 25 docs
    2. Outbox Pattern: Write to outbox, process async
    3. Event Sourcing: Store changes as events

    Key Insight: Retry-with-increment is pragmatic for Firestore contention. Not truly atomic but achieves eventual consistency.


    Q2: How would you scale to 100K concurrent users?

    Current Bottlenecks:

    ComponentCurrentSolution
    Firestore writes~1K/secShard by user ID
    RedisSingle instanceRedis Cluster
    LLM APIsRate limitedMultiple keys + round-robin

    Architecture Changes:

    1. Database Sharding:
    TypeScript
    1. Request Queue:
    TypeScript
    1. Response Caching:
    TypeScript

    Key Insight: LLM API rate limits are the biggest bottleneck, not infrastructure. Solution: multi-key rotation + caching.


    Q3: How do you handle slow LLM providers?

    Current: No timeout, no fallback - request hangs.

    Better: Circuit Breaker + Timeout + Fallback

    TypeScript

    Key Insight: Use circuit breakers to fail fast, not just timeouts. Prevents cascading failures.


    Q4: How would you implement fair rate limiting?

    Current: Only guest users limited (50/15min).

    Fair Design:

    TypeScript

    Key Insight: Rate limit by user ID (not IP), apply endpoint-specific costs.


    Q5: How do you prevent prompt injection?

    Current: Basic content moderation, no specific injection detection.

    Defense Layers:

    1. Input Sanitization:
    TypeScript
    1. Prompt Structure:
    TypeScript
    1. Output Validation:
    TypeScript

    Key Insight: Prompt injection is an input validation problem. Defense in depth: sanitize, structure, validate.


    Q6: How would you optimize history retrieval from O(n) to O(1)?

    Current: Linear traversal through threadMap

    TypeScript

    Optimized:

    1. Denormalized Last N Messages:
    TypeScript
    1. Message Index with Pointers:
    TypeScript

    Key Insight: For chat, you almost always need recent messages first. Denormalize last N, lazy load older.


    Q7: How do you handle concurrent edits from multiple devices?

    Current: Last-write-wins with Firestore server timestamp. No conflict resolution.

    Solutions:

    1. Optimistic Concurrency Control:
    TypeScript
    1. Queue-Based Serialization:
    TypeScript

    Key Insight: For chat, optimistic concurrency + client-side merge is sufficient.


    Q8: What's the cost structure per request?

    GPT-4o (15x query cost):

    ComponentCost
    Input tokens (1K)$0.0075
    Output tokens (500)$0.01125
    Embeddings (RAG)$0.0001
    Firestore writes$0.00002
    Cloud Run$0.00001
    Total~$0.02

    Deep Research (Claude 3 Opus, 50x): ~$1.00 per request

    Key Insight: LLM API costs dominate (99%+). Optimize: reduce tokens, cache responses, use cheaper models.


    Q9: What would cause catastrophic failure?

    Answer: Firebase Auth + Firestore simultaneous outage.

    Why:

    • No auth fallback → all requests rejected
    • No database fallback → can't read any data
    • No offline mode → complete failure

    Mitigation:

    1. Session Cache (Immediate):
    TypeScript
    1. Read-Only Fallback:
    TypeScript

    Key Insight: System has no graceful degradation. Any Firebase failure causes complete outage.


    15. QUICK REFERENCE

    Commands
    Bash
    Key Files
    PurposeFile
    API Routesapps/arcane/src/config/routing.ts
    Main Endpointapps/arcane/src/server/endpoints/unified/unified.ts
    Auth Middlewareapps/arcane/src/server/middlewares/auth/auth.ts
    User Modelapps/arcane/src/server/models/user.ts
    Thread Modelapps/arcane/src/server/models/thread.ts
    Schema Builderapps/arcane/src/server/repositories/engine/schema.ts
    Website Middlewareapps/website/middleware.ts
    Troubleshooting
    SymptomFix
    401 UnauthorizedCheck Authorization header
    429 Rate LimitedWait 15 minutes or upgrade
    500 Internal ErrorCheck Cloud Logging
    Streaming failsCheck network, retry

    Last Updated: March 27, 2026 Version: 6.0.0 (Complete Architecture + Canvas + Templates + Fallbacks) Document Status: ✅ Complete — Bonkers monorepo architecture with all critical systems