# Web, API, and GPUI Desktop Under Moon

> How the monorepo is wired: Vite and TanStack-style routing on web, a thin TypeScript API with health and echo routes, a Rust desktop entry on gpui, and moon/proto task orchestration across apps.

- Repository: OpenCut-app/OpenCut
- GitHub: https://github.com/OpenCut-app/OpenCut
- Human wiki: https://grok-wiki.com/public/wiki/opencut-app-opencut-2bfee888b2cd
- Complete Markdown: https://grok-wiki.com/public/wiki/opencut-app-opencut-2bfee888b2cd/llms-full.txt

## Source Files

- `apps/web/src/routes/__root.tsx`
- `apps/web/vite.config.ts`
- `apps/api/src/index.ts`
- `apps/desktop/src/main.rs`
- `apps/desktop/Cargo.toml`
- `.moon/workspace.yml`

---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [.moon/workspace.yml](.moon/workspace.yml)
- [apps/api/src/index.ts](apps/api/src/index.ts)
- [apps/desktop/Cargo.toml](apps/desktop/Cargo.toml)
- [apps/desktop/src/main.rs](apps/desktop/src/main.rs)
- [apps/web/src/routes/__root.tsx](apps/web/src/routes/__root.tsx)
- [apps/web/vite.config.ts](apps/web/vite.config.ts)

</details>

# Web, API, and GPUI Desktop Under Moon

OpenCut’s monorepo is not one fat app—it is three thin runtimes under a shared workspace root. Moon discovers projects under `apps/*`. The web client is a Vite + TanStack Start stack aimed at Cloudflare SSR. The API is a small Elysia service with health and echo routes. The desktop binary is a GPUI “shell scaffold” that opens a window and paints a title. Understanding that split is the difference between hunting for features that do not exist yet and reading the wiring as it actually is.

This page maps how those pieces are declared and connected: workspace discovery, web plugins and root route shell, API surface, and the desktop entrypoint. It stays on what the source shows—no assumed product depth, auth model, or shared library layer beyond what is present.

Sources: [.moon/workspace.yml:1-6](), [apps/web/vite.config.ts:1-21](), [apps/api/src/index.ts:1-15](), [apps/desktop/src/main.rs:31-50]()

## Page shape

| Aspect | Value |
|--------|--------|
| Classification | Architecture pattern (monorepo app surfaces + orchestration) |
| Scope | Workspace discovery, web/API/desktop entry wiring |
| Non-goals | Feature inventory of the editor, deployment runbooks, CI, shared crates (not in evidence) |
| Source of truth | Repository files listed above |

## Why the monorepo layout matters

Moon’s workspace config is deliberately minimal: discover every project under `apps/*`. A comment leaves room for a future `crates/*` glob when shared Rust crates appear—those are not registered today. That means the current “system” is three app packages side by side, not a deep crate graph.

```text
.moon/workspace.yml
        │
        ▼  projects: apps/*
┌───────────────┬───────────────┬────────────────┐
│  apps/web     │  apps/api     │  apps/desktop  │
│  Vite/TanStack│  Elysia + CF  │  GPUI binary   │
│  React Start  │  Worker adapter│  opencut-desktop│
└───────────────┴───────────────┴────────────────┘
```

Sources: [.moon/workspace.yml:1-6]()

## System map

```mermaid
flowchart TB
  subgraph moon_ws["Moon workspace"]
    WS[".moon/workspace.yml<br/>projects: apps/*"]
  end

  subgraph web_layer["apps/web"]
    VITE["vite.config.ts"]
    ROOT["routes/__root.tsx"]
    VITE --> ROOT
  end

  subgraph api_layer["apps/api"]
    API["src/index.ts<br/>Elysia + CloudflareAdapter"]
  end

  subgraph desktop_layer["apps/desktop"]
    CARGO["Cargo.toml<br/>opencut-desktop"]
    MAIN["src/main.rs<br/>GPUI Application"]
    CARGO --> MAIN
  end

  WS --> web_layer
  WS --> api_layer
  WS --> desktop_layer
```

Sources: [.moon/workspace.yml:3-6](), [apps/web/vite.config.ts:10-18](), [apps/api/src/index.ts:1-5](), [apps/desktop/Cargo.toml:1-13]()

---

## Moon workspace discovery

`.moon/workspace.yml` points at the Moon schema and lists a single project glob:

| Setting | Value | Notes |
|---------|--------|--------|
| Schema | `https://moonrepo.dev/schemas/workspace.json` | Declared at top of file |
| Projects | `apps/*` | Auto-discover apps |
| Future | `crates/*` | Mentioned in comment only; not configured |

There is no further task graph, toolchain pin, or proto config in this evidence block. Orchestration *around* apps is implied by Moon’s role as workspace root; the concrete app behavior lives in each `apps/*` tree.

Sources: [.moon/workspace.yml:1-6]()

---

## Web: Vite, Cloudflare SSR, TanStack Start

### Build and plugin stack

`apps/web/vite.config.ts` composes a Cloudflare-oriented Start app:

| Plugin / option | Role in config |
|-----------------|----------------|
| `resolve.tsconfigPaths: true` | Path resolution via tsconfig |
| `@tanstack/devtools-vite` (`devtools()`) | Devtools Vite integration |
| `@cloudflare/vite-plugin` with `viteEnvironment: { name: 'ssr' }` | Cloudflare SSR environment |
| `@tailwindcss/vite` | Tailwind |
| `@tanstack/react-start/plugin/vite` (`tanstackStart()`) | TanStack Start |
| `@vitejs/plugin-react` (`viteReact()`) | React |

Order in source: `devtools` → `cloudflare` → `tailwindcss` → `tanstackStart` → `viteReact`.

Sources: [apps/web/vite.config.ts:1-21]()

### Root route and document shell

The TanStack root route (`createRootRoute`) owns document head and the HTML shell:

- **Meta:** `utf-8`, viewport, title `OpenCut rewrite | beta.opencut.app`
- **Links:** favicon, Google Fonts preconnects, Playfair Display stylesheet, app CSS via `../styles.css?url`
- **Shell:** `RootDocument` renders `<html lang="en">`, `HeadContent`, body with `TooltipProvider` wrapping `{children}`, TanStack Devtools (bottom-right, Router panel), and `Scripts`

That is a classic Start/router pattern: root route defines the document chrome; child routes (not shown in evidence) would render inside `{children}`.

```tsx
// apps/web/src/routes/__root.tsx (excerpt)
export const Route = createRootRoute({
  head: () => ({
    meta: [
      { charSet: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { title: 'OpenCut rewrite | beta.opencut.app' },
    ],
    // links: favicon, fonts, appCss ...
  }),
  shellComponent: RootDocument,
})
```

Sources: [apps/web/src/routes/__root.tsx:1-75]()

### What builders should notice (web)

- The stack is **TanStack Start + React + Tailwind + Cloudflare SSR**, not a plain CRA or Next.js layout.
- Document title and font choices are already product-branded in the root route; CSS enters as a Vite `?url` stylesheet link.
- Devtools are first-class (Vite plugin + in-page TanStack Devtools with Router panel).

Sources: [apps/web/vite.config.ts:10-18](), [apps/web/src/routes/__root.tsx:8-70]()

---

## API: thin Elysia surface on Cloudflare Workers

`apps/api/src/index.ts` exports a single Elysia app with `CloudflareAdapter`. Routes are intentionally small:

| Method | Path | Behavior |
|--------|------|----------|
| `GET` | `/` | `{ status: "ok" }` |
| `GET` | `/health` | `{ healthy: true, timestamp: <ISO string> }` |
| `POST` | `/echo` | Echoes validated body; body schema `{ message: string }` |

The file ends with `.compile()`, with a comment that compile is required and triggers AoT compilation at startup.

```ts
// apps/api/src/index.ts (structure)
export default new Elysia({ adapter: CloudflareAdapter })
  .get("/", () => ({ status: "ok" }))
  .get("/health", () => ({ healthy: true, timestamp: new Date().toISOString() }))
  .post("/echo", ({ body }) => body, {
    body: t.Object({ message: t.String() }),
  })
  .compile();
```

There is no auth middleware, database client, or OpenCut domain model in this file—only health-style and echo endpoints suitable as a Worker skeleton.

Sources: [apps/api/src/index.ts:1-15]()

---

## Desktop: GPUI binary shell

### Package and binary

`apps/desktop/Cargo.toml` defines package `opencut-desktop` (“OpenCut desktop app, built with GPUI”), workspace-inherited `version` / `edition` / `license`, binary name `opencut-desktop` at `src/main.rs`, and a single dependency: `gpui` from the workspace.

Sources: [apps/desktop/Cargo.toml:1-13]()

### Window and UI scaffold

`main.rs` runs a GPUI `Application`, opens a centered windowed bounds of **960×600**, titlebar title **OpenCut**, and mounts a `Root` view whose status string is **`desktop shell scaffold`**.

`Root` implements `Render`: full-size flex column, centered, background `0x111111`, white title text “OpenCut”, secondary gray status line.

```rust
// apps/desktop/src/main.rs (excerpt)
cx.new(|_| Root {
    status: "desktop shell scaffold".into(),
})
```

This is an empty product shell: no editor canvas, no IPC to the API or web app, no feature UI beyond branding and status text.

Sources: [apps/desktop/src/main.rs:1-51]()

---

## Cross-surface comparison

| Surface | Runtime / stack | Entry | Maturity signal in evidence |
|---------|-----------------|-------|------------------------------|
| Web | Vite, TanStack Start/React Router, Tailwind, Cloudflare SSR | `vite.config.ts` + `routes/__root.tsx` | Document shell, fonts, devtools, rewrite title |
| API | Elysia + Cloudflare Worker adapter | `src/index.ts` default export | Health + typed echo only |
| Desktop | Rust GPUI | `opencut-desktop` → `main.rs` | Explicit “shell scaffold” status |
| Workspace | Moon | `projects: apps/*` | Apps only; crates glob deferred |

Shared theme: **Cloudflare appears on web (Vite plugin) and API (Worker adapter)**; desktop is native GPUI and does not share that path in the evidence.

Sources: [apps/web/vite.config.ts:8-16](), [apps/api/src/index.ts:1-5](), [apps/desktop/Cargo.toml:8-13](), [.moon/workspace.yml:5-6]()

---

## Tradeoffs and open questions

**What the layout buys you**

- Clear ownership boundaries: web UI, edge API stub, desktop binary can evolve on different cadences under one Moon discovery rule.
- Edge-oriented TypeScript (Elysia + Cloudflare adapter; Vite Cloudflare SSR) pairs with a separate native GPUI experiment rather than forcing one UI kit everywhere.

**What the evidence does not show**

- Moon task definitions, proto toolchains, or how `moon run` invokes each app
- Shared packages/crates (the workspace comment anticipates `crates/*` later)
- Any HTTP client from web/desktop to the API, or auth/CORS/env config
- Child web routes, editor UI, or desktop features beyond the scaffold window

Treat those as unknown until other wiki pages or files supply them—not as implied architecture.

---

## Plan sketch for extenders

If you are adding a surface feature without inventing structure outside this wiring:

| Concern | Guidance grounded in current layout |
|---------|-------------------------------------|
| Scope | Touch one of `apps/web`, `apps/api`, or `apps/desktop` unless you intentionally introduce shared crates (would require workspace glob changes per the comment) |
| Non-goals | Do not assume the API is a full backend; it is health/echo today |
| Risks | Coupling web and API only on Cloudflare assumptions without shared contracts; desktop remains isolated GPUI |
| Smoke checks | Web root title/devtools shell loads; `GET /` and `/health`, `POST /echo` with `{ "message": "..." }`; desktop opens titled window with scaffold status |

Sources: [.moon/workspace.yml:3-6](), [apps/api/src/index.ts:4-13](), [apps/desktop/src/main.rs:44-46]()

---

## Summary

Under Moon, OpenCut is three apps: a **Vite + TanStack Start** web shell with Cloudflare SSR and a document root at `__root.tsx`; a **thin Elysia API** on `CloudflareAdapter` with `/`, `/health`, and typed `/echo`; and a **GPUI desktop** binary that only claims to be a shell scaffold. The workspace discovers `apps/*` and leaves room for future `crates/*`. Builders should read this as orchestration of entrypoints, not as a finished multi-platform product stack—and extend from those files rather than from assumptions about unlisted layers.
