# src-tauri/ — the app window Mathew as a **desktop app** (Tauri 2, Linux / Windows / macOS): the wiki in a window of its own, no browser around it. The shell is deliberately thin — the app *is* the same Nuxt bundle the website serves, written out as plain files and embedded in the binary. Nothing in `frontend/app/` is desktop code; the bundle asks at run time whether it happens to be sitting in a window (`app/utils/desktop.ts`) and only then takes the window's habits: a link leads out to the system's browser instead of replacing the wiki in the only view there is, and the session token and interface language are mirrored into `localStorage` because a webview is not everywhere obliged to keep cookies for its own `tauri://localhost` address. The wiki needs a wiki to talk to: the window holds no server and no database. It calls the **public Mathew** over HTTPS by default — the API base is baked in at build, see the table below. ## Build & run From `frontend/` — these need [Rust](https://rustup.rs) (stable) and the [Tauri prerequisites](https://v2.tauri.app/start/prerequisites/) for your OS; on Linux that is the WebKitGTK stack: `libwebkit2gtk-4.1-dev libgtk-3-dev libssl-dev libxdo-dev librsvg2-dev build-essential`. | Script | What it does | | --- | --- | | `npm run desktop:dev` | `tauri dev` — opens the **Nuxt dev server** (`localhost:3000`, started for you) in the window, hot-reload included; `isDesktop()` is already true inside it | | `npm run desktop:build` | `tauri build` — runs `desktop:generate` (below), compiles the shell, embeds the files, and leaves installers under `src-tauri/target/release/bundle/` (deb/rpm/AppImage on Linux, NSIS/MSI on Windows, .app/.dmg on macOS) | | `npm run desktop:generate` | the bundle the window loads: `MATHEW_DESKTOP=1 nuxt generate` → `dist-desktop/public`, the `frontendDist` this config names (a desktop build never overwrites the web `.output/`) | | `npm run desktop:icons` | re-cuts `src-tauri/icons/` from `desktop/icon-source.png` (redraw that one with `python3 desktop/make-icon.py`) | The desktop shape lives in `nuxt.config.ts` under one flag (`MATHEW_DESKTOP=1`, also implied by the `TAURI_ENV_*` the Tauri CLI passes to its build hooks): `ssr: false`, no `/api` proxy route, and the pre-paint theme script served from `public/preboot.js` instead of inline. The web build takes none of it. Deep routes (`/wiki/en/bayes-theorem`, …) are not files in the bundle — Tauri's own asset serving answers unknown paths with `index.html`, so the client router takes over exactly as it does on a static host. **Dev-server port**: `devUrl` is fixed to `3000`, and Nuxt falls back to `3001` when `3000` is taken (see the main gotchas) — free the port before `desktop:dev`, or the window loads whatever else answers there. ## Where the app reaches | Build variable | Default (desktop) | Meaning | | --- | --- | --- | | `NUXT_PUBLIC_API_BASE` | `https://mathew.aranroig.com` | the wiki the app reads and writes; point it at `http://localhost:5000` to test against this machine | | `NUXT_PUBLIC_LEAN_URL` | empty | the Lean server `/lean` talks to; empty leaves that page saying there is no server here, which is the honest answer on a random laptop. The API's default CORS (`*`) carries the window's `tauri://localhost` origin fine — it sends a bearer header, not cookies | Set them in the environment before `npm run desktop:build`. ## What the shell owns - **one window per launch** — `tauri-plugin-single-instance`: pressing the icon again brings the open window forward instead of stacking a second wiki behind it (`src/lib.rs`). - **the way out** — `tauri-plugin-opener` is the door `app/utils/desktop.ts` hands outward links to the system's browser; `capabilities/default.json` is what grants it. That and `core:default` are the whole permission list: reading and writing the wiki is the webview's own business. - **no CSP** (`csp: null` in `tauri.conf.json`): the window loads no foreign script and talks to one API over HTTPS, and `/lean`'s Monaco wants `eval`-like tricks a strict `script-src` would have to excuse. The one script the page writes itself (the pre-paint theme, `public/preboot.js`) already lives in a **file**, so turning a policy on later is a config line — keep it that way if one is ever set. Nothing here is signed: bundles come out unsigned, and updating is reinstalling. An updater, signing, and a per-machine "which wiki?" setting are the obvious next steps if this ever ships for real. ## Versioning The app's version lives in `tauri.conf.json` (`version`); it names the installers and the platform bundle metadata. Commit `Cargo.lock` once a build has produced one — for an application binary, a locked dependency set is what makes a rebuild reproducible.