Skip to main content
Openinary is a pnpm monorepo orchestrated by Turbo. It holds both the AGPL-3.0 self-hosted product and the source of the managed Cloud service, so a fix to the shared engine lands in both at once. The engine itself is packages/core, not apps/api.
Everything is AGPL-3.0 except apps/cloud/, which is source-available under a commercial license, and apps/marketing/, which is MIT. Self-hosting needs nothing from apps/cloud/.

packages/

The apps consume core and ui through workspace:*, so nothing has to be published between fixing something and shipping it. Both were published to npm up to @openinary/core 1.6.0 and @openinary/ui 0.8.1, and both are marked private now, so those versions are frozen. To use them in your own app, go through the shadcn registry.

packages/core

Nearly all media, storage and queue logic lives here rather than in apps/api. That is what lets the self-hosted API and the Cloud’s media container share one implementation.
Key dependencies: sharp, fluent-ffmpeg, @aws-sdk/client-s3, @webtoon/psd, fflate, hono, better-sqlite3, pino

apps/api

The self-hosted server. It wires the engine to HTTP: startup, auth, rate limiting, and the three routes specific to a self-hosted instance. Everything else is mounted from @openinary/core.
Key dependencies: hono, @openinary/core, shared, better-sqlite3, heic-convert, zod

apps/web

The Next.js 15 admin dashboard, for uploads, API keys and video queue status.
Key dependencies: next, react, @tanstack/react-query, better-auth, Radix UI, Tailwind CSS v4

packages/shared

Consumed by both api and web. It keeps auth configuration and the SQLite instance in one place, so both apps always use the same database.
The SQLite instance is created inside auth.ts; there is no separate db.ts. Both apps import through the "shared" and "shared/*" path aliases defined in packages/shared/package.json.

Dependency flow

Next steps

Local Development

Run the monorepo locally with pnpm.

Security

Auth architecture, API keys, and route reference.