This guide is the architectural and operational reference for the OpenCut-app/OpenCut repository — the ground-up rewrite of the OpenCut video editor. It is written for developers, architects, and operators who need to understand exactly how this codebase is structured, configured, built, and deployed.
Important
Scope check. At this commit, OpenCut is an early-stage rewrite. The repository is a freshly scaffolded TanStack Start web application: an HTML shell, one route that renders nothing, a Tailwind theme, and a complete shadcn/ui component library. The video editor itself — timeline, preview, export, media handling — does not exist in this repository yet. This guide documents the scaffold honestly and completely. Where a capability is planned but not implemented, it is labeled as such. The currently shipping editor is the classic codebase at opencut-app/opencut-classic.
1. Executive Summary
OpenCut is a free, open-source (MIT-licensed) video editor. The project is rebuilding its application from scratch around a new architecture: a plugin-first design, a shared Rust core targeting desktop/mobile/browser, an Editor API, an MCP server for AI agents, and headless automation.
This repository is the web front-end shell of that rewrite. Its current technical profile:
| Attribute | Value |
|---|---|
| Repository type | Monorepo (Bun workspaces + Turborepo) |
| Primary app | apps/web (@opencut/web) |
| Framework | TanStack Start (SSR) + TanStack React Router |
| UI runtime | React 19.2 |
| Build tool | Vite 8 |
| Styling | Tailwind CSS v4 + shadcn/ui (base-mira style) |
| Deployment target | Cloudflare Workers (custom domain new.opencut.app) |
| Package manager | Bun 1.3.11 |
| Language | TypeScript 6 (strict) |
| Test runner | Vitest 4 (configured; no tests yet) |
| License | MIT (© 2026 OpenCut) |
| Source files | 81 files, ~84 KB of source |
The single most important architectural fact for an operator is that this is a server-rendered React application deployed as a Cloudflare Worker — there is no separate backend, database, or API tier in this repository.
2. Architecture
2.1 High-level structure
OpenCut (monorepo root)
│
├── Bun workspaces ──── manages apps/*
├── Turborepo ───────── orchestrates dev / build / deploy across apps
│
└── apps/web (@opencut/web) ← the only app today
│
├── TanStack Start ──── SSR framework (server entry + routing)
│ └── TanStack React Router (file-based routes)
├── React 19 ────────── UI rendering
├── Vite 8 ──────────── dev server + production bundler
├── Tailwind v4 ─────── styling
├── shadcn/ui ───────── 56 prebuilt components
└── Cloudflare plugin ─ builds the app as a Worker (wrangler deploy)
2.2 Request flow (production)
Browser → new.opencut.app (Cloudflare edge)
│
▼
Cloudflare Worker "opencut-web"
main = @tanstack/react-start/server-entry
│
▼
TanStack Start SSR
│ matches route "/" via routeTree.gen.ts
▼
__root.tsx (HTML shell: <head> meta/links, TooltipProvider, Scripts)
│
▼
index.tsx → Home() → returns null (no body content yet)
│
▼
HTML streamed back to browser
The Worker runs with the nodejs_compat compatibility flag, allowing TanStack Start's server entry to use Node.js-style APIs on the Cloudflare runtime.
2.3 The monorepo build pipeline (Turborepo)
turbo.json defines three tasks with their dependency and caching rules:
| Task | dependsOn |
Outputs / behavior |
|---|---|---|
build |
^build (build upstream packages first) |
.output/**, dist/** |
dev |
— | cache: false, persistent: true (long-running) |
deploy |
build |
runs after a successful build |
Because there is only one app today, Turborepo's cross-package orchestration is effectively a pass-through to apps/web, but the pipeline is in place for when the Rust core and additional packages are added.
3. System Requirements
| Component | Requirement |
|---|---|
| Bun | 1.3.11 (the declared packageManager) |
| Node.js | 18+ recommended for tooling; the Worker uses nodejs_compat at runtime |
| TypeScript | ^6.0.2 (provided as a dev dependency) |
| Cloudflare account | Required only for deployment (wrangler) |
| OS | Any platform Bun supports (Linux, macOS, Windows) |
Note
No system-level services are required — no database, message broker, or external API. Local development needs only Bun and a browser.
4. Repository Structure
OpenCut/
├── package.json Root workspace + Turbo scripts
├── turbo.json Turborepo task pipeline
├── bunfig.toml Bun install policy (minimumReleaseAge)
├── bun.lock Bun lockfile
├── LICENSE MIT, © 2026 OpenCut
├── README.md Project status + roadmap
│
└── apps/
└── web/ @opencut/web — the web application
├── package.json App deps + scripts
├── vite.config.ts Vite plugin chain
├── wrangler.jsonc Cloudflare Worker config
├── tsconfig.json TypeScript config
├── components.json shadcn/ui config
├── .cta.json Create-TanStack-App metadata
├── public/ favicon, robots.txt, manifest.json
└── src/
├── router.tsx Router factory
├── routeTree.gen.ts Generated route tree (do not edit)
├── styles.css Tailwind + theme tokens
├── routes/
│ ├── __root.tsx HTML shell + providers + devtools
│ └── index.tsx "/" route → renders null
├── components/ui/ 56 shadcn/ui components
├── hooks/
│ └── use-mobile.ts useIsMobile() (768px breakpoint)
└── lib/
└── utils.ts cn() class-name helper
Note
56 of the repository's source files are shadcn/ui components under
apps/web/src/components/ui/. They are installed and importable but not yet wired into any rendered view. The hand-written application logic is currently confined to__root.tsx,index.tsx,router.tsx,lib/utils.ts, andhooks/use-mobile.ts.
5. Configuration Reference
Every configuration file in the repository, with its exact, source-based values.
5.1 Root package.json
{
"name": "opencut",
"private": true,
"workspaces": ["apps/*"],
"scripts": {
"dev": "turbo dev",
"dev:web": "turbo dev --filter=@opencut/web",
"build": "turbo build",
"deploy": "turbo deploy"
},
"devDependencies": { "turbo": "latest" },
"packageManager": "bun@1.3.11"
}
| Field | Meaning |
|---|---|
workspaces: ["apps/*"] |
Bun treats every directory under apps/ as a workspace package |
packageManager |
Pins Bun 1.3.11 for reproducible installs |
scripts |
Thin Turborepo wrappers; real work happens in apps/web |
5.2 bunfig.toml — install policy
[install]
minimumReleaseAge = 604800 # 7d
minimumReleaseAge = 604800 seconds (7 days) instructs Bun to refuse any dependency version published in the last week. This is a supply-chain attack mitigation: it creates a quarantine window so that a maliciously published package version is likely to be detected and yanked before it can be installed. See §9 (Security).
5.3 turbo.json
See §2.3 for the task table. The schema is https://turbo.build/schema.json.
5.4 apps/web/package.json — scripts
| Script | Command |
|---|---|
dev |
vite dev --port 5173 |
build |
vite build |
preview |
vite preview |
test |
vitest run |
deploy |
bun run build && wrangler deploy |
5.5 apps/web/vite.config.ts — plugin chain
plugins: [
devtools(),
cloudflare({ viteEnvironment: { name: 'ssr' } }),
tailwindcss(),
tanstackStart(),
viteReact(),
]
| Plugin | Role |
|---|---|
devtools() |
TanStack DevTools integration during development |
cloudflare({ viteEnvironment: { name: 'ssr' } }) |
Targets the Cloudflare Workers runtime; binds the SSR environment |
tailwindcss() |
Tailwind CSS v4 via the official Vite plugin |
tanstackStart() |
TanStack Start SSR framework integration |
viteReact() |
React fast-refresh + JSX transform |
resolve: { tsconfigPaths: true } enables the TypeScript path aliases (#/*, @/*) at build time.
5.6 apps/web/wrangler.jsonc — Cloudflare Worker
{
"name": "opencut-web",
"compatibility_date": "2025-09-02",
"compatibility_flags": ["nodejs_compat"],
"main": "@tanstack/react-start/server-entry",
"routes": [
{ "pattern": "new.opencut.app", "custom_domain": true }
]
}
| Key | Value | Meaning |
|---|---|---|
name |
opencut-web |
Worker name in the Cloudflare account |
compatibility_date |
2025-09-02 |
Pins the Workers runtime behavior to that date |
compatibility_flags |
["nodejs_compat"] |
Enables Node.js API compatibility |
main |
@tanstack/react-start/server-entry |
The Worker entry module (provided by TanStack Start) |
routes |
new.opencut.app (custom domain) |
Binds the Worker to the production domain |
Caution
The
routesblock hard-codes the official production domain. Any fork must changenameand remove or replaceroutesbefore deploying, orwrangler deploywill attempt to publish to OpenCut's domain (and fail without permission).
5.7 apps/web/tsconfig.json — TypeScript
| Option | Value | Notes |
|---|---|---|
target / module |
ES2022 / ESNext |
Modern output |
jsx |
react-jsx |
Automatic JSX runtime |
moduleResolution |
bundler |
Vite-style resolution |
strict |
true |
Full strict mode |
noUnusedLocals / noUnusedParameters |
true |
Dead-code linting at compile time |
noFallthroughCasesInSwitch |
true |
Switch safety |
noUncheckedSideEffectImports |
true |
Flags side-effect-only imports |
noEmit |
true |
Vite handles emit; tsc is type-check only |
paths |
#/* → ./src/*, @/* → ./src/* |
Import aliases |
5.8 apps/web/components.json — shadcn/ui
| Field | Value |
|---|---|
style |
base-mira |
tailwind.baseColor |
neutral |
tailwind.cssVariables |
true |
tailwind.css |
src/styles.css |
iconLibrary |
hugeicons |
rsc |
false (not using React Server Components) |
aliases |
components → #/components, utils → #/lib/utils, ui → #/components/ui, lib → #/lib, hooks → #/hooks |
5.9 apps/web/src/styles.css — theme
The stylesheet composes four imports and defines the theme tokens:
@import 'tailwindcss';
@import "tw-animate-css";
@import "shadcn/tailwind.css";
@import "@fontsource-variable/inter";
@custom-variant dark (&:is(.dark *));
@theme inline {
--font-heading: 'Playfair Display', serif;
--font-sans: 'Inter Variable', sans-serif;
/* ...full shadcn CSS-variable color token set... */
}
| Token | Value |
|---|---|
| Heading font | Playfair Display (loaded via Google Fonts in __root.tsx) |
| Body/sans font | Inter Variable (@fontsource-variable/inter) |
| Dark mode | Class-based (.dark ancestor) via @custom-variant |
| Color system | shadcn CSS variables (--color-* mapped to --* theme vars) |
5.10 apps/web/public/
| File | Content |
|---|---|
robots.txt |
User-agent: * / Disallow: (allows all crawlers) |
favicon.ico |
Site icon |
manifest.json |
⚠️ Still the default Create-TanStack-App placeholder — short_name: "TanStack App", name: "Create TanStack App Sample". Not yet customized for OpenCut. |
Warning
public/manifest.jsonhas not been updated from the scaffold default. Before any public launch it should be rebranded (name, short_name, theme color, icons). Tracked in §13.
6. Routing and the Application Shell
6.1 Router factory — src/router.tsx
export function getRouter() {
const router = createTanStackRouter({
routeTree,
scrollRestoration: true,
defaultPreload: 'intent',
defaultPreloadStaleTime: 0,
})
return router
}
| Option | Effect |
|---|---|
scrollRestoration: true |
Restores scroll position on navigation |
defaultPreload: 'intent' |
Preloads a route's data/code on hover or focus intent |
defaultPreloadStaleTime: 0 |
Preloaded data is considered immediately stale (always refetched) |
6.2 Route tree — src/routeTree.gen.ts
Auto-generated by TanStack Router from the files in src/routes/. It registers exactly two routes: the root (__root) and the index (/).
Important
routeTree.gen.tsis machine-generated. Do not edit it by hand — it is regenerated on every build. Add routes by creating files undersrc/routes/.
6.3 Root shell — src/routes/__root.tsx
The root route defines the HTML document: <head> metadata (charset, viewport, title), the favicon link, Google Fonts preconnect + the Playfair Display stylesheet, and the app CSS import. The body wraps all child routes in a TooltipProvider and mounts TanStackDevtools (with the Router DevTools panel) plus the framework Scripts component.
Note
The document
<title>is hard-coded to"OpenCut rewrite — beta.opencut.app". Note that this referencesbeta.opencut.app, while the deployment target inwrangler.jsoncand the README isnew.opencut.app— a naming inconsistency flagged in §13.
Note
TanStackDevtoolsis mounted unconditionally in the shell. In a typical production build it should be gated behind a development-only check; verify this before public launch (§13).
6.4 Index route — src/routes/index.tsx
export const Route = createFileRoute('/')({ component: Home })
function Home() {
return null
}
The home page renders null. This is the placeholder where the editor UI will be mounted. There is no editor component in this repository yet.
7. The UI Component Layer
The repository ships a full shadcn/ui kit (56 components, see §4 / User Guide §5) configured with the base-mira style, the neutral base color, CSS-variable theming, and the Hugeicons icon set. Components are built on Base UI (@base-ui/react) and Radix UI primitives.
Supporting utilities:
| Utility | Location | Purpose |
|---|---|---|
cn(...inputs) |
src/lib/utils.ts |
Merges class names via clsx + tailwind-merge |
useIsMobile() |
src/hooks/use-mobile.ts |
Returns true below a 768px viewport; live-updates on resize |
A large set of interaction libraries is already declared as dependencies, ready for the editor build: react-hook-form + zod + @hookform/resolvers (forms/validation), date-fns + react-day-picker (dates), embla-carousel-react (carousels), cmdk (command palette), sonner (toasts), vaul (drawers), recharts (charts), react-resizable-panels (resizable layout — a likely editor-panel primitive), next-themes (theme switching), and input-otp.
Note
These libraries are installed but not yet consumed by any rendered code. Treat the dependency list as a statement of intent for the editor UI, not as currently active features.
8. Build and Deployment Operations
8.1 Local development
bun install # from repo root
bun run dev # all apps via Turborepo
# or: bun run dev:web (web only)
Vite serves on http://localhost:5173.
8.2 Production build
# repo root
bun run build # turbo build → vite build in apps/web
Outputs land in .output/** and/or dist/** (per turbo.json).
8.3 Deploy to Cloudflare
# from apps/web
wrangler login # one-time auth
bun run deploy # vite build && wrangler deploy
This publishes the Worker opencut-web and binds it to new.opencut.app.
8.4 Inspecting a running deployment
# Stream live logs from the deployed Worker
wrangler tail opencut-web
| Operation | Command |
|---|---|
| Build | bun run build |
| Preview production build locally | bun run preview (from apps/web) |
| Deploy | bun run deploy (from apps/web) |
| Tail logs | wrangler tail opencut-web |
| Roll back | Redeploy a previous build, or use Cloudflare's deployment history in the dashboard |
Tip
Cloudflare retains deployment history per Worker. To roll back, redeploy from a known-good commit or promote a previous version from the Cloudflare dashboard's Worker deployments view.
9. Security Analysis
This is a static, server-rendered shell with no user input, authentication, data storage, or secrets — so the present attack surface is small. The relevant points are about supply-chain posture and what will need hardening as the editor grows.
9.1 Supply-chain controls (present)
| Control | Mechanism | Effect |
|---|---|---|
| Dependency quarantine | bunfig.toml minimumReleaseAge = 604800 |
Refuses dependency versions less than 7 days old, reducing exposure to freshly published malicious releases |
| Pinned package manager | packageManager: bun@1.3.11 |
Reproducible installs; resists tooling drift |
| Lockfile | bun.lock |
Exact, reproducible dependency graph |
Tip
The
minimumReleaseAgepolicy is a strong, low-cost supply-chain control. Keep it in place. If a build fails because a needed version is too new, prefer waiting out the window over lowering the threshold.
9.2 Runtime posture (present)
- No secrets / environment variables. The repository consumes no
.envfiles and.cta.jsondeclares no env var values. There are no credentials to leak in this repository. - No authentication or authorization. There is no login, session, or user model — appropriate for a shell, but the editor's eventual collaboration/cloud features will introduce this surface.
nodejs_compatenabled. This widens the Worker's available APIs; review what the editor build actually uses so the compatibility surface stays minimal.- Permissive
robots.txt. All crawlers are allowed (Disallow:empty), which is fine for a public marketing/editor site.
9.3 Future trust boundaries (planned, not yet present)
The roadmap (§12) introduces the project's most significant future security surfaces:
Warning
First-class third-party plugins and an MCP server for AI agents are planned. Both execute or are driven by untrusted external code/instructions. When these land, they will become the primary trust boundaries and will require sandboxing, capability scoping, and an explicit permission model. None of this exists in the current repository — but it should be designed in from the start of the plugin architecture.
9.4 Development tooling exposure
TanStackDevtools is mounted in the root shell (§6.3). DevTools panels can expose router internals and should not ship enabled in production. Confirm the build strips or gates them before public launch.
10. Code Quality and Conventions
| Convention | Detail |
|---|---|
| Strict TypeScript | strict, noUnusedLocals, noUnusedParameters, noFallthroughCasesInSwitch, noUncheckedSideEffectImports all on |
| Path aliases | Import from #/... (and @/...), both mapping to apps/web/src/ |
| Class composition | Always via cn() (clsx + tailwind-merge) to avoid conflicting Tailwind classes |
| Generated files | routeTree.gen.ts is generated; never edit by hand |
| Component source of truth | UI components follow shadcn conventions (base-mira style, CSS variables, Hugeicons) |
| Module type | apps/web is an ES module ("type": "module") |
The codebase is small, idiomatic, and consistent with current TanStack Start + shadcn scaffolding conventions. There is little custom logic to assess yet.
11. Testing Strategy
The toolchain is configured for testing but no tests exist yet.
| Element | Status |
|---|---|
| Runner | Vitest 4 (vitest run via bun run test) |
| DOM environment | jsdom 28 |
| Component testing | @testing-library/react 16, @testing-library/dom 10 |
| Test files present | None |
Important
bun run testsucceeds vacuously today because there are zero test files. As editor logic lands, establish test coverage from the first feature — the harness is already in place, so there is no setup cost.
12. Roadmap
From the project README, the rewrite is targeting:
- An Editor API — programmatic control of the editor.
- First-class third-party plugins — enabled by a plugin-first architecture.
- One codebase for desktop, mobile, and browser — via a shared Rust core.
- An MCP server — to let AI agents operate the editor.
- Headless mode — automation and batch rendering.
- A scripting tab — in-editor scripting.
Note
None of the above is implemented in this repository. The Rust core, plugin system, MCP server, headless mode, and scripting tab are design goals. This repository is the web shell those features will attach to.
13. Improvements and Known Gaps
Source-based items worth addressing, derived from the current state of the repository.
- [ ] Rebrand
public/manifest.json— it still carries the scaffold defaults ("TanStack App"/"Create TanStack App Sample"). Set OpenCut's name, short_name, theme color, and icons. - [ ] Resolve the domain-name inconsistency —
__root.tsxhard-codes the<title>"OpenCut rewrite — beta.opencut.app", whilewrangler.jsoncand the README usenew.opencut.app. Pick one and align them. - [ ] Gate
TanStackDevtoolsto development — it is mounted unconditionally in the root shell (§6.3). Strip or guard it for production builds. - [ ] Add tests — the Vitest/jsdom/Testing-Library harness is ready but unused (§11). Begin coverage with the first editor feature.
- [ ] Build the editor — the home route renders
null. This is the central piece of work; everything else is foundation. - [ ] Design plugin/MCP trust boundaries up front — the planned plugin system and MCP server are the project's future primary security surfaces (§9.3). Bake sandboxing and a permission model into the architecture rather than retrofitting them.
Note
The community issues filed against OpenCut (export memory usage, playback stutter, audio/text bugs) pertain to the classic editor at
opencut-classic, not to this rewrite repository, which contains none of that code. They are not actionable here.
14. Quick Reference
Commands
| Action | Command | Run from |
|---|---|---|
| Install | bun install |
repo root |
| Dev (all) | bun run dev |
repo root |
| Dev (web only) | bun run dev:web |
repo root |
| Build | bun run build |
repo root |
| Preview build | bun run preview |
apps/web |
| Test | bun run test |
apps/web |
| Deploy | bun run deploy |
apps/web |
| Tail logs | wrangler tail opencut-web |
anywhere (authed) |
Key files
| File | Purpose |
|---|---|
apps/web/wrangler.jsonc |
Cloudflare Worker name, domain, compat flags |
apps/web/vite.config.ts |
Vite + SSR + Cloudflare + Tailwind plugin chain |
apps/web/tsconfig.json |
Strict TS config + path aliases |
bunfig.toml |
Supply-chain install policy (7-day quarantine) |
turbo.json |
Monorepo task pipeline |
apps/web/src/routes/__root.tsx |
HTML shell, providers, devtools |
apps/web/src/routes/index.tsx |
/ route (renders null today) |
apps/web/src/router.tsx |
Router factory + preload config |
apps/web/components.json |
shadcn/ui configuration |
Facts
| Fact | Value |
|---|---|
| Dev port | 5173 |
| Worker name | opencut-web |
| Production domain | new.opencut.app |
| Compatibility flag | nodejs_compat |
| Compatibility date | 2025-09-02 |
| Package manager | bun@1.3.11 |
| Path alias | #/* and @/* → apps/web/src/* |
| Mobile breakpoint | 768px |