OTT Platform — 9 Platforms, 1 Monorepo
Prachyam Sangam is the ground-up rewrite of Prachyam Studios' OTT platform — a project I inherited as a broken, 18-developer codebase and rebuilt solo into a 21-package Nx TypeScript monorepo targeting 9 distinct platforms: Next.js web, React Native iOS and Android, Apple TV, Android TV, Roku, Tizen (Samsung), webOS (LG), and a Tauri desktop admin panel.
The previous platform (see Prachyam Legacy) had accumulated 1,669 commits of technical debt across incompatible stacks. Sangam is the clean-room successor — designed from the monorepo boundary outward, with every cross-platform contract defined at the package layer before a single UI component was written.
The core problem with multi-platform OTT is that each target has fundamentally different rendering, input, and DRM models. A TV remote is not a touchscreen. Roku's SceneGraph XML is not React. Tizen and webOS each have their own app packaging and certification requirements. The naive approach — write one UI, bolt on platform shims — produces an unmaintainable mess at exactly the scale the previous platform had reached.
The constraint I set: shared business logic, typed contracts, zero copy-paste between platform packages.
The monorepo is structured in three layers:
Core packages (@sangam/core) define domain models, API client, auth, and player state as pure TypeScript with no DOM or RN dependencies. Every platform imports from here.
Shared UI packages split by rendering target — @sangam/ui-web (React + Tailwind), @sangam/ui-native (React Native + NativeWind), @sangam/ui-tv (React Native TV). Platform-specific components extend shared primitives; none duplicate logic.
Platform apps (apps/web, apps/ios, apps/android, apps/apple-tv, apps/android-tv, apps/roku, apps/tizen, apps/webos, apps/admin) are thin shells that wire platform entry points to the shared packages.
Nx handles task orchestration, build caching, and affected-project detection. A change to @sangam/core triggers rebuilds only for packages that depend on it — not the full workspace.
Roku required the biggest context switch: SceneGraph XML with BrightScript scripting, a completely different mental model from component trees. The player integration alone took two weeks of Roku device testing.
Tizen and webOS share a React-based renderer but have divergent packaging, signing, and store submission requirements. Both target smart TV input models (D-pad navigation, long-press, focus rings) that need custom focus management — React's synthetic event model doesn't map cleanly to TV remotes.
Apple TV and Android TV use the React Native TV fork with tvOS/leanback-specific navigation. Focus management is handled through a custom useTVFocus hook that wraps the platform's native APIs.
Tauri admin is the desktop management panel for studio staff — content ingestion, scheduling, analytics, and the DRM key management interface.
10 custom Model Context Protocol servers (~280 tools) give Claude Code live read access to the Postgres schema, BullMQ job queues, MinIO buckets, Docker service state, and Prometheus metrics across the stack. This compressed the CLAUDE.md context by 69% and allowed AI-assisted debugging without manually pasting database state into prompts.
Nx over Turborepo — Nx's task graph and affected detection are more granular for a workspace this large. Turborepo's simpler model would have required more manual cache configuration at 21 packages.
Elysia over Hono — Elysia's end-to-end type safety (request → response → client SDK) via the treaty plugin eliminated an entire class of runtime errors between the API and platform consumers.
Bun as runtime — The monorepo toolchain runs entirely on Bun. Script execution and test runs are meaningfully faster than Node across 21 packages, which compounds over hundreds of daily builds.
Nx workspace
~972K LOC
Claude Code integration
India-first OTT platform, 9 native targets
Forensic stabilisation and feature expansion of a production streaming platform across web, mobile, and TV
Did this resonate?