Skip to content

Studio Backend

Generative AI Tools, Video Workbench, AI pipelines etc.

Directory Structure

The application follows a modular architecture where each feature is organized into its own directory with consistent file naming:

studio-backend/
├── src/
│   ├── [feature]/               # Each feature follows this pattern:
│   │   ├── [feature].router.ts    # API route definitions
│   │   ├── [feature].controller.ts # HTTP request/response handling
│   │   ├── [feature].service.ts    # Business logic
│   │   ├── [feature].validator.ts  # Input validation (Zod schemas)
│   │   └── [feature].middleware.ts # Authentication/authorization
│   ├── models/                  # MongoDB schema definitions
│   ├── shared/                  # Common utilities, types, constants
│   ├── thirdPartyServices/      # External API integrations
│   ├── utilityServices/         # Standalone services for common operations
│   ├── [product]Templates/        # Email or Prompt templates etc.
│   └── [other-features]/        # Additional feature modules
├── tests/                       # Test files mirroring src structure
├── dist/                        # Compiled JavaScript output
└── config files                 # TypeScript, Biome, Vitest, etc.

Core Files: index.ts (app entry), router.ts (main router), mongoDBClient.ts, redisClient.ts, mailer.ts, errorLogger.ts

Architecture Overview

Router, Controllers, Validators, and Service Functions

The application follows a layered architecture pattern:

  1. Routers (*.router.ts): Define API endpoints and route requests to controllers
  2. Controllers (*.controller.ts): Handle HTTP requests/responses and input validation
  3. Validators (*.validator.ts): Validate request data using Zod schemas
  4. Services (*.service.ts): Contain business logic and database operations
  5. Middleware (*.middleware.ts): Handle cross-cutting concerns like authentication and authorization

MongoDB Integration

The src/models/ directory contains MongoDB schema definitions for all data entities. The application uses multiple mongoDB databases:

  • Primary Database: Studio database for main application data
  • Story Database: Rendarigo database for stories data (to be updated when storydesk is up)
  • Connection Management: mongoDBClient.ts handles connections to both databases
  • Collection Access: Provides methods for accessing collections in both databases

Webhooks

The webhook system (src/webhooks/) handles external service callbacks:

  • Webhook Router: Defines webhook endpoints
  • Webhook Middleware: Validates webhook signatures and authenticity
  • Webhook Controller: Processes incoming webhook payloads
  • Webhook Service: Contains webhook processing business logic

Activity Logging

The activity logging system tracks user-facing actions across projects (scene generation, shot edits, collaborator changes, etc.) and surfaces them in the frontend activity panel.

  • Collection: projectActivities in MongoDB
  • Service: src/projectActivities/projectActivities.service.ts — fire-and-forget helpers (logActivity, logProjectLifecycleActivity)
  • Enum: ProjectActivityAction in src/shared/sharedTypes.ts — single source of truth for all action types
  • Frontend: Mirrored enum + ACTION_LABELS in studio-frontend, displayed in a dropdown panel

Activity logging is a cross-cutting concern wired in the service layer (not controllers). When adding new user-facing features, activity logging must be added(also write tests). See src/projectActivities/README.md for the full checklist and conventions.

Test Library

The application uses Vitest as the testing framework:

  • Configuration: vitest.config.ts with TypeScript path aliases and experimental fsModuleCache
  • Test Structure: Tests organized by module in tests/ directory
  • Global Setup: tests/globalSetup.ts — starts a shared MongoMemoryServer instance (one mongod for all test files)
  • Test Helpers: tests/testHelpers.ts — connects to shared mongod, provides unique DB per file via getDb()
  • Mockers: Reusable mock objects in tests/mockers/
  • Test Constants: Shared test constants in tests/testConstants.ts

Performance: 527 tests run in ~7.5s locally thanks to: - Shared MongoMemoryServer (one mongod process, unique DB name per file for full parallelism) - fsModuleCache: true (experimental Vitest feature for faster module resolution) - Fire-and-forget activity logging with flush() pattern (no sleeps in tests)

Running tests:

npm test              # Run all tests
npx vitest           # Run in watch mode
npx vitest --run     # Run once (CI mode)

Lefthook Checks

Lefthook is configured for pre-commit and pre-push hooks (lefthook.yml):

pre-commit:
  commands:
    biome-format:   # formats staged files, auto-stages fixes
    biome-lint:     # lints staged files, blocks commit on errors
    no-console-log: # checks for console.log in staged files (opt-in)

pre-push:
  commands:
    build:          # TypeScript compilation check

This ensures code quality by running:

  • Formatting (priority 1): Biome auto-formats staged files and re-stages the fixes
  • Linting (priority 2): Biome lints staged files — blocks commit if lint errors exist
  • No Console Log: Prevents accidental console.log (opt-in via CHECK_CONSOLE_LOG=1)
  • Build (pre-push): TypeScript compilation verification before pushing
  • Tests: Run in GitHub Actions only (not in git hooks)

Error Logging to New Relic

The application integrates with New Relic for error monitoring:

  • Configuration: newrelic.js with license key and settings
  • Error Logger: src/errorLogger.ts with Winston integration
  • Log Forwarding: Errors automatically forwarded to New Relic
  • File Logging: Local error logs stored in .errorLogs/ directory
  • Queue Processing: Asynchronous error log processing

Redis Client for RBAC & Permissions

Redis is used for caching and session management:

  • Redis Client: src/redisClient.ts with singleton pattern
  • Connection Management: Automatic reconnection and error handling
  • RBAC Integration: Caches user permissions and roles
  • Session Storage: Stores user sessions and authentication tokens

Websocket Integration

The application uses Socket.IO for real-time communication with the frontend:

Deprecated (in progress): New realtime flows are being migrated to JaduSpine (Centrifugo). Keep Socket.IO usage only for legacy paths until migration is complete.

  • Socket Service: src/socketService.ts - Singleton pattern implementation
  • Event Definitions: src/shared/socketEvents.ts - Centralized event constants
  • Authentication: JWT token verification for socket connections
  • CORS Support: Configured for frontend communication
  • User-based Messaging: sendToUser(userId, event, ...) function sends messages to all socket connections for a specific user (handles multiple tabs/devices)

Available Events:

  • assetGenResponse: Response with generation status and results
  • Connection events: connect, disconnect, error

Usage Example:

// Frontend connection
const socket = io('http://localhost:8081', {
  auth: { token: 'your-jwt-token' },
  transports: ['websocket', 'polling'],
});

// Listen for responses
socket.on('assetGenResponse', (response) => {
  console.log('Asset generation result:', response);
});

// Backend usage - send to all user connections
socketService.sendToUser(userId, 'assetGenResponse', 200, 'Job completed', true, { job });

JaduSpine (Centrifugo) Integration

JaduSpine is a pub/sub messaging system built on Centrifugo for real-time backend-to-frontend communication:

  • SDK: @scenarix/jaduspine-sdk (private package)
  • Backend Singleton: JaduSpineBackend - initialized once at server startup
  • Publishing: Backend publishes messages to user-specific channels
  • Frontend: Connects via WebSocket to Centrifugo, receives messages in real-time

Initialization (in src/index.ts):

import { JaduSpineBackend } from '@scenarix/jaduspine-sdk';

// During server startup
await JaduSpineBackend.init({
  apiUrl: process.env.CENTRIFUGO_API_URL!,
  apiKey: process.env.CENTRIFUGO_API_KEY!,
  debug: process.env.NODE_ENV === 'development',
});

Publishing Messages:

import { JaduSpineBackend, FrontendChannel, FrontendChannels } from '@scenarix/jaduspine-sdk';

// Publish to a specific user
await JaduSpineBackend.publish(new FrontendChannel(FrontendChannels.MINIMATICS, userId), { topic: 'guruResponse', data: { message: 'Hello!' } });

Environment Variables:

  • CENTRIFUGO_API_URL: Centrifugo HTTP API URL
  • CENTRIFUGO_API_KEY: API key for authentication
  • GITHUB_PKG_TOKEN: GitHub Personal Access Token for installing private @scenarix/* packages (required for npm install, see .npmrc)

See src/agenticGuru/io/ for the guru chat implementation using JaduSpine.

Docker (Preview Environments)

A multi-stage Dockerfile is provided for building and deploying preview environments via Coolify (or any container platform).

Build the image:

docker build --build-arg GITHUB_PKG_TOKEN=<your-github-pat-with-read:packages> -t studio-backend-preview .

Run locally:

docker run -p 8081:8081 --env-file .env studio-backend-preview

The app will be available at http://localhost:8081.

Notes: - The GITHUB_PKG_TOKEN build arg is required to install private @scenarix/* packages during build. It is not present in the final image. - Runtime env vars (MongoDB, Redis, API keys, etc.) must be injected at runtime via --env-file or the deployment platform — they are not baked into the image. - The production image includes vips (runtime dependency for sharp).

CI / GitHub Actions

The repository uses GitHub Actions for continuous integration:

Workflow Trigger What it does
test.yml Push to main/staging, PRs targeting main/staging Runs Vitest, posts test results check + coverage comment on PR
staging_to_main_validation.yml PR from stagingmain Runs TypeScript build to catch type errors
staging-to-main-pr.yml Weekly (Tuesday 10:30 AM IST) + manual Auto-creates release PR from stagingmain

Test workflow outputs: - Test Results (Check Run via dorny/test-reporter@v3) — pass/fail counts, failed test details with code annotations - Coverage Report (PR comment via davelosert/vitest-coverage-report-action@v2) — coverage table with per-file breakdown

Requirements: - Node 24 (matches local dev environment) - SCENARIX_GITHUB_PKG_TOKEN secret — for installing private @scenarix/* packages

Deploy Build Commands

# Development
npm run dev          # Start development server with nodemon

# Production
npm run build        # Compile TypeScript to JavaScript
npm start           # Start production server with New Relic

# Code Quality
npm run lint        # Check with Biome (lint + format check)
npm run lint:fix    # Auto-fix all issues
npm run format      # Format codebase with Biome
npm run test        # Run Vitest tests

# Setup
npm run setup       # Install lefthook hooks

Linting & Code Formatting

The application uses Biome as an all-in-one linter and formatter:

  • Config: biome.json
  • Editor: .vscode/settings.json — Biome as default formatter, format on save, organize imports on save
  • VS Code Extension: Install the Biome VS Code extension for in-editor linting, formatting, and auto-fix on save. See the official docs for setup instructions.
  • VCS Integration: Respects .gitignore, can process only staged/changed files

Key Rules:

  • Biome recommended rules enabled
  • noConsole: Warns on console.log usage (use winston logger)
  • noExplicitAny: Off (use any when needed)
  • noUnusedImports / noUnusedVariables: Warn (auto-fixable)
  • organizeImports: Auto-sorts imports on save and in pre-commit
  • TypeScript noImplicitReturns: Enabled in tsconfig.json

Commands:

npm run lint            # Check entire codebase (no writes)
npm run lint:fix        # Fix all auto-fixable issues
npm run format          # Format entire codebase
npm run format:staged   # Check + fix only staged files
npm run format:changed  # Check + fix only files changed vs main

Mailer Integration

The application uses Resend for email delivery:

  • Mailer Service: src/mailer.ts with Handlebars templating
  • Email Templates: Templates in src/emailTemplates/
  • Resend Integration: src/thirdPartyServices/resend.service.ts
  • Supported Emails: OTP emails, bug report notifications

Third-Party Services

The application integrates with multiple external services:

  • AI Services: OpenAI, FalAI, xAI, Replicate
  • Voice Generation: ElevenLabs
  • File Storage: B2 Cloud Storage
  • Email: Resend
  • Monitoring: New Relic
  • Project Management: Jira
  • Video Processing: Vidu
  • Workflow: Prefect

Bedrock Usage Notes

BedrockService is implemented in src/thirdPartyServices/bedrock.service.ts and called with BedrockService.generateText(...).

  • Auth uses AWS_BEARER_TOKEN_BEDROCK as a bearer token.
  • Bedrock model IDs are defined in BedrockModelId (src/shared/sharedTypes.ts).
  • Current BedrockModelId values are inference profile ARNs (global inference profile ARNs), not plain foundation model IDs.
  • Requests use Bedrock Converse API: POST /model/{modelId}/converse.
  • A cachePoint with ttl: "1h" is currently added in the system block when systemPrompt is provided.

JSON schema output support

BedrockService.generateText supports optional jsonSchema, which is sent in Converse outputConfig.textFormat as json_schema.

Example:

const response = await BedrockService.generateText({
  userPrompt: 'Generate character metadata',
  systemPrompt: 'Return valid JSON only',
  modelId: BedrockModelId.CLAUDE_SONNET_4_6,
  jsonSchema: {
    name: 'CharacterOutput',
    description: 'Structured character response',
    schema: {
      type: 'object',
      properties: {
        title: { type: 'string' },
        age: { type: 'number' },
      },
      required: ['title'],
      additionalProperties: false,
    },
  },
});

Utility Services

The application provides utility services for common operations:

  • Asset Scoring: assetScoring.service.ts - AI-powered asset evaluation and scoring
  • Prompt Rewrite: promptRewrite.service.ts - Intelligent prompt optimization and rewriting
  • Voice Generation: voiceGen.service.ts - Text-to-speech and voice synthesis utilities

Environment Variables

See example in .env.local

API Endpoints

  • /api/auth/* - Authentication endpoints
  • /api/rbac/* - Role-based access control
  • /api/assetGen/* - Asset generation (see src/assetGen/README.md for voice settings flow)
  • /api/stories/* - Story management
  • /api/workbench/* - Workbench functionality
  • /api/webhooks/* - Webhook endpoints
  • /api/pipeline/* - Pipeline management (via Prefect)
  • /api/bugReport/* - Bug reporting
  • /api/imageEdit/* - Image editing
  • /api/llmChat/* - LLM chat functionality

Contributing

  1. Follow the existing code structure (router → controller → validator → service)
  2. Add appropriate tests for new functionality if applicable
  3. Ensure all lefthook checks pass before committing
  4. Follow the established error logging patterns
  5. Update this README for significant architectural changes