# web reference

> Reference for the code under `web`: what it exports, how it is invoked, its options and defaults, and its error cases.

- Repository: egoist/lorca
- GitHub: https://github.com/egoist/lorca
- Human docs: https://grok-wiki.com/public/docs/egoist-lorca-2cf67495e5e6
- Complete Markdown: https://grok-wiki.com/public/docs/egoist-lorca-2cf67495e5e6/llms-full.txt

## Source Files

- `web/content/docs/cli.mdx`
- `crates/cli/src/api.rs`
- `web/src/router.tsx`
- `web/src/routeTree.gen.ts`

---

---
title: "web reference"
description: "Reference for the code under `web`: what it exports, how it is invoked, its options and defaults, and its error cases."
---

`web/` is the Lorca marketing site and product docs app: a private Bun workspace package (`"name": "web"`) built with TanStack Start + Vite, file routes under `web/src/routes`, Fumadocs MDX under `web/content/docs`, and a Cloudflare Worker entry from `web/wrangler.jsonc`. Production host constant: `https://lorca.app`.

## Invoke

From the repo root (about one command each):

| Command | Effect |
| --- | --- |
| `bun run web` | `bun run --cwd web dev` → Vite on port **3000** |
| `bun run web:build` | Production build in `web/` |
| `bun run web:deploy` | `bun run build && wrangler deploy` in `web/` |

Inside `web/package.json`:

| Script | Command | Default |
| --- | --- | --- |
| `dev` | `vite dev --port 3000` | Port `3000` |
| `generate-routes` | `tsr generate` | Regenerates `src/routeTree.gen.ts` |
| `build` | `vite build` | Cloudflare SSR + assets |
| `preview` | `vite preview` | Local preview of build |
| `deploy` | `bun run build && wrangler deploy` | Worker name `lorca` |

Success signal for local work: `http://localhost:3000` serves `/`, `/docs`, and `/download`.

## Package layout

:::files
web/
  package.json          # scripts, #/* → ./src/*
  vite.config.ts        # fumadocsMdx, cloudflare SSR, tanstackStart, react, tailwind
  wrangler.jsonc        # Worker name lorca, nodejs_compat, observability
  tsr.config.json       # TanStack Router target: react
  content/docs/         # MDX product docs + meta.json / meta.zh.json
  public/               # install-cli.sh|.ps1, screens, favicon, _headers
  src/
    router.tsx          # getRouter()
    routeTree.gen.ts    # generated route tree (do not edit)
    lib/source.ts       # docs source, i18n, llms helpers
    components/docs/    # DocsPage loader + Fumadocs UI shell
    components/site/    # Home, Download, Nav, sections
    routes/             # file routes (en + zh_ pathless layout)
:::

Import alias: `"#/*": "./src/*"`.

## Router defaults

`getRouter()` in `web/src/router.tsx` creates the TanStack Router with:

| Option | Value |
| --- | --- |
| `routeTree` | Generated `routeTree` from `routeTree.gen.ts` |
| `scrollRestoration` | `true` |
| `scrollRestorationBehavior` | `'instant'` |
| `defaultPreload` | `'intent'` |
| `defaultPreloadStaleTime` | `0` |

SSR is registered with TanStack Start (`ssr: true` in the generated module augmentation).

## HTTP routes

English is the default locale (no `/en` prefix). Chinese lives under `/zh`. Pathless `zh_` route files keep Chinese pages out of the `/zh` landing layout.

| Path | Role |
| --- | --- |
| `/` | English landing (`Home`) |
| `/zh` | Chinese landing |
| `/download` | English download page |
| `/zh/download` | Chinese download page |
| `/docs/$` | English docs HTML (splat) |
| `/zh/docs/$` | Chinese docs HTML |
| `/docs/{$}.md` | English docs as Markdown |
| `/zh/docs/{$}.md` | Chinese docs as Markdown |
| `/llms.txt` | English docs index for LLMs |
| `/llms-full.txt` | English full Markdown dump |
| `/zh/llms.txt` | Chinese docs index |
| `/zh/llms-full.txt` | Chinese full Markdown dump |
| `/api/search` | Docs search (Orama via Fumadocs) |

Static public files (examples): `/install-cli.sh`, `/install-cli.ps1`, `/favicon.png`, `/screens/group.png`.

```mermaid
flowchart LR
  subgraph browser [Browser]
    Home["/ and /zh"]
    Dl["/download"]
    DocsUI["/docs/$"]
  end
  subgraph worker [Cloudflare Worker SSR]
    Source["lib/source.ts"]
    Search["/api/search"]
    Md["/docs/*.md and /llms*.txt"]
    MacFn["latestMacRelease server fn"]
  end
  subgraph content [Repo content]
    MDX["content/docs/*.mdx"]
    Public["public/install-cli.*"]
    Appcast["mac-releases.lorca.app/appcast.xml"]
  end
  Home --> Source
  DocsUI --> Source
  Source --> MDX
  Search --> Source
  Md --> Source
  Dl --> MacFn
  MacFn --> Appcast
  Public --> Dl
```

## Docs source API (`web/src/lib/source.ts`)

| Export | What it is |
| --- | --- |
| `docsRoute` | `'/docs'` |
| `docsI18n` | `defaultLanguage: 'en'`, `languages: ['en','zh']`, `hideLocale: 'default-locale'` |
| `docs` | `defineDocs({ dir: 'content/docs', docs: { async: true, postprocess: { includeProcessedMarkdown: true } } })` |
| `source` | Fumadocs `loader` over `docs.toFumadocsSource()`, Lucide icons plugin, `baseUrl: '/docs'` |
| `docsLlms` | `llms(source, …)` rendering `# {title} ({url})` + processed Markdown body |
| `markdownUrl(slugs, lang?)` | `/docs/bots.md` or `/zh/docs/bots.md`; empty slugs → `index.md` |
| `slugsOfMarkdownUrl(segments)` | Strips trailing `.md`; `index` → `[]` |

Sidebar order comes from `web/content/docs/meta.json` (English section titles) and `meta.zh.json` (Chinese). Pages: `index`, `get-started`, `bots`, `chats`, `group-chats`, `tools`, `memory`, `routines`, `plugins`, `auto-review`, `devices`, `providers`, `mobile`, `security`, `relay`, `cli`. A Chinese file is named `*.zh.mdx` beside the English `*.mdx`; missing translation falls back to English.

### Docs page loader

`loadDocsPage(lang, splat)` → server function `serverLoader`:

1. Resolve `source.getPage(slugs, lang)`.
2. Missing page → `notFound()`.
3. Return `{ path, url, slugs, title, description, markdownUrl, pageTree }`.
4. `docs.getPage(data.path)?.preload()` then render `DocsPage`.

`docsHead(lang, data)` sets title `{page} · {docs.title}`, description, canonical `SITE + data.url`, and `hreflang` alternates for `en` / `zh`.

Theme: system only (`forcedTheme: 'system'`, theme switch disabled). Language picker navigates to the same slugs under the other locale.

MDX components (`web/src/components/mdx.tsx`): Fumadocs defaults plus `Accordion` / `Accordions` / `Step` / `Steps`.

## Search API

:::endpoint GET /api/search Docs full-text search
Built with `createFromSource(source, { localeMap })` from `fumadocs-core/search/server`. The route handler forwards the incoming `Request` to `server.GET(request)`.

**Locale indexes**

| Locale | Config |
| --- | --- |
| `en` | `{ language: 'english' }` |
| `zh` | Mandarin tokenizer from `@orama/tokenizers/mandarin`; `search: { threshold: 0, tolerance: 0 }` |

Query string shape is whatever Fumadocs `createFromSource` accepts on the request URL; this package does not wrap or rename those parameters.
:::

## Download page and Mac release loader

`latestMacRelease` is a TanStack Start server function (`GET`):

| Behavior | Detail |
| --- | --- |
| Feed URL | `https://mac-releases.lorca.app/appcast.xml` |
| Timeout | `AbortSignal.timeout(5000)` |
| Parse | Newest Sparkle `<item>` by `sparkle:version`; enclosure `.zip` rewritten to `.dmg` |
| Success | `{ version, url, minimumSystemVersion, appleSilicon }` |
| Failure | Logs error, returns `null` (Mac button disabled; iOS / CLI still shown) |

Other download links (hardcoded in the download UI):

| Surface | Target |
| --- | --- |
| iOS | TestFlight `https://testflight.apple.com/join/WRR2R3y1` |
| CLI (Unix) | `curl -fsSL https://lorca.app/install-cli.sh \| sh` |
| CLI (Windows) | `irm https://lorca.app/install-cli.ps1 \| iex` |
| Windows / Linux desktop, Android | “Soon” placeholders |

## Install scripts (`web/public/`)

Served as UTF-8 plain text via `web/public/_headers`.

### `install-cli.sh` (macOS / Linux)

| Variable | Default / effect |
| --- | --- |
| `LORCA_VERSION` | Latest GitHub release; else `cli-v{version}` |
| `LORCA_INSTALL_DIR` | `$HOME/.local/bin` |
| `LORCA_NO_MODIFY_PATH` | `1` skips profile PATH edit |
| `LORCA_DOWNLOAD_URL` | Override releases root (default `https://github.com/egoist/lorca/releases`) |

Targets: `macos-aarch64`, `linux-aarch64`, `linux-x86_64`. Intel Mac without Rosetta → fatal. Windows shells redirected to the PowerShell script. Verifies `.sha256`, installs by rename so a running `lorca serve` keeps its binary, prints `lorca --version` on success.

### `install-cli.ps1` (Windows)

Same env vars (`$env:LORCA_*`). Target always `windows-x86_64` (Arm Windows runs the x64 build). Installs `lorca.exe`, unblocks the file, refuses to call `exit` so `iex` does not close the window.

## i18n

| Export | Values |
| --- | --- |
| `languages` | `'en'`, `'zh'` |
| `paths` | `en → '/'`, `zh → '/zh'` |
| `htmlLang` | `en`, `zh-Hans` |
| `languageOf(pathname)` | `/zh` or `/zh/…` → `zh`, else `en` |
| `i18nFor(lng)` | Per-language i18next instance; `fallbackLng: 'en'`; `initAsync: false` |

Root shell (`__root.tsx`) sets `<html lang=…>`, Inter font, theme-color meta for light/dark, and production-only analytics script `https://u.egoist.dev/script.js` when `import.meta.env.PROD`.

## Deploy and Worker config

`web/wrangler.jsonc`:

| Key | Value |
| --- | --- |
| `name` | `lorca` |
| `compatibility_date` | `2025-09-02` |
| `compatibility_flags` | `["nodejs_compat"]` |
| `main` | `@tanstack/react-start/server-entry` |
| `observability.enabled` | `true` |

Vite plugins (order): `fumadocsMdx`, TanStack devtools, `@cloudflare/vite-plugin` with `viteEnvironment: { name: 'ssr' }`, Tailwind, `tanstackStart`, React.

A CLI release does **not** require a site deploy. Shipping script or docs changes requires `bun run web:deploy`.

## Error cases

| Case | Behavior |
| --- | --- |
| Unknown docs slug | `notFound()` from loader / Markdown GET |
| `docs.getPage(path)` missing after load | `throw new Error(\`unknown page: ${path}\`)` |
| Appcast HTTP non-OK / empty / timeout / parse miss | `latestMacRelease` → `null`; Mac download disabled |
| Install: unsupported OS/CPU | Script exits / throws with message |
| Install: checksum mismatch | Fatal; ask to re-run installer |
| Install: archive missing binary | Fatal |
| Install: binary fails `--version` | Fatal |
| Install: unwritable install dir | Fatal; set `LORCA_INSTALL_DIR` |
| No `curl`/`wget` (sh) | Fatal |
| Invalid `LORCA_VERSION` | Fatal |

## Related pages

<CardGroup>
  <Card title="Overview" href="/overview">What Lorca exposes and where the site fits beside CLI, macOS, mobile, and relay.</Card>
  <Card title="CLI reference" href="/cli-reference">Commands and flags documented by the product docs under `/docs/cli`.</Card>
  <Card title="Deployment" href="/deployment">Build and `wrangler deploy` for the Worker that serves this package.</Card>
  <Card title="crates/cli reference" href="/ref-crates-cli">The `lorca` binary the install scripts download and the desktop app launches.</Card>
</CardGroup>

Next: open `web/package.json` and run `bun run web`, then hit `http://localhost:3000/docs/cli`.
