Skip to content

macOS desktop: thin Tauri 2 shell loading memo web UI (remote HTTPS) #19

Description

@chasehuh

Summary

Add a minimal macOS desktop shell for memo that looks nearly identical to the existing Zed-like web UI. Ship a thin Tauri 2 app that loads the live web app over HTTPS in production (https://memo.chasehuh.com) and http://localhost:3000 during tauri dev. Do not redesign the UI, do not introduce a local SQLite / anarlog-style local-first stack, and do not bundle a second Next/static frontend for v1.

Why This Matters

memo already has a dense, editor-like chrome in the Next app. Users want a native window on macOS without maintaining a second product surface. A thin webview shell reuses Postgres + existing APIs + the current UI as the single source of truth, while giving a real macOS app feel (traffic lights / titlebar overlay). This unblocks “open memo as an app” without forking the product into a local-first desktop rewrite.

Conversation Context

Product lock from research / user direction:

  • Goal: fully minimal desktop app that looks almost the same as the current web UI (Zed-like memo chrome already in the Next app).
  • Not a separate native redesign.
  • Not an anarlog-style local-first SQLite product for v1.
  • Architecture SoT:
    • Thin Tauri 2 shell loading the web app over HTTPS in production.
    • Hybrid URL: tauri devhttp://localhost:3000; production build → https://memo.chasehuh.com.
    • Do not bundle static Next export / second frontend for v1.
    • Web (Postgres + APIs + Clerk-when-ready) remains source of truth.
    • Keep in-page shortcuts (⌘B / ⌘N); overlay macOS traffic lights / transparent titlebar if needed so chrome still matches.
    • anarlog is only a layout/packaging reference (e.g. apps/desktop + src-tauri) — ignore local DB, plugin sprawl, custom auth storage for v1.
    • Auto-update / App Store / iOS: non-goals for this issue.

Auth dependency: production identity is moving to Clerk GitHub OAuth via issue #17 / PR #18. The desktop shell can load today’s password login today, but the intended production path is Clerk. Document WKWebView / OAuth popup risks; do not block the shell PR on Clerk landing.

Duplicate check (2026-07-14): no open/closed issues for tauri, desktop, or macOS desktop shell (existing #10 is ⌘⌫ editor behavior only).

Current Behavior

  • Repo is a single Next.js App Router app (not yet an apps/* monorepo), live at memo.chasehuh.com.
  • UI: Zed-like shell in components/memo-app.tsx + app/globals.css (.zed-shell, .zed-titlebar, .zed-panel, etc.).
  • In-page shortcuts already handled in the web app:
    • ⌘N / Ctrl+N → new note
    • ⌘B / ⌘\ → toggle notes sidebar
  • Auth today: shared password gate (MEMO_PASSWORD / session cookie) via app/login + app/api/auth/*.
  • Data: Postgres via lib/db.ts + app/api/notes/*; optional media upload worker.
  • No desktop / Tauri / native packaging exists in-repo.
  • Clerk GitHub auth + per-user note scoping is in flight (Clerk GitHub auth + per-user note sync (new memo Clerk app) #17 / Clerk GitHub auth + per-user note sync #18) but not necessarily merged yet.

Desired Behavior

After this issue:

  1. Monorepo-style path apps/desktop (+ apps/desktop/src-tauri) exists inside chasehuh/memo.
  2. pnpm --filter @memo/desktop tauri dev (or documented equivalent) opens a macOS window that loads http://localhost:3000 when the Next app is running.
  3. Production tauri build produces a macOS .app / DMG that loads https://memo.chasehuh.com (remote URL as frontendDist / app URL — no bundled Next export).
  4. Window chrome is macOS-native with Overlay / transparent titlebar and visible traffic lights; web UI remains the primary chrome so the app still looks like memo.
  5. Existing web shortcuts (⌘B, ⌘N) continue to work inside the webview (do not reimplement as exclusive native menu handlers that steal them).
  6. README documents prerequisites (Rust, Xcode CLT), run/build commands, and the Clerk dependency note.
  7. Scope stays macOS-only for v1 (no Windows/Linux targets required).

Source Of Truth

Internal repo/source

  • components/memo-app.tsx — primary UI + keyboard shortcuts (⌘N, ⌘B, ⌘\).
  • app/globals.css — Zed chrome (.zed-titlebar, .zed-shell, panels). If Overlay titlebar overlaps content, adjust padding / optional data-tauri / CSS env only as needed — do not redesign.
  • app/layout.tsx, app/page.tsx, app/login/ — surfaces the shell will load remotely.
  • app/api/**, lib/db.ts, lib/auth.ts, lib/notes.ts — remain server SoT; desktop must not duplicate.
  • README.md — add Desktop section.
  • package.json / pnpm-workspace.yaml — extend so apps/desktop is a workspace package (today workspace file only lists ignoredBuiltDependencies; promote to real packages if needed).
  • Issue #17 / PR #18 — Clerk GitHub auth dependency for production identity.

External docs/source

Proposed API / Schema

No new HTTP API. Desktop is a client shell only.

Runtime URL matrix

Mode Command Webview URL
Dev tauri dev http://localhost:3000
Prod built .app https://memo.chasehuh.com

Suggested package identity

{
  "productName": "memo",
  "identifier": "com.chasehuh.memo",
  "build": {
    "devUrl": "http://localhost:3000",
    "frontendDist": "https://memo.chasehuh.com"
  }
}

Exact Tauri 2 schema field names must match current @tauri-apps/cli / docs at implement time.

Validation Rules

  • Desktop must not ship DATABASE_URL, MEMO_PASSWORD, or Clerk secrets inside the binary.
  • Desktop must not open IPC to arbitrary remote origins beyond what’s required to load the trusted memo origin (keep capabilities minimal; prefer zero custom commands for v1).
  • Backward compatibility: web app unchanged for browser users.

Implementation Notes

Likely files to modify

  • pnpm-workspace.yaml — include apps/* (or apps/desktop).
  • Root package.json — optional convenience scripts (desktop:dev, desktop:build).
  • README.md — Desktop run/build section + Clerk / OAuth caveat.
  • .gitignore — ignore Tauri/Rust targets (apps/desktop/src-tauri/target, etc.).

New files

  • apps/desktop/package.json@memo/desktop, @tauri-apps/cli scripts.
  • apps/desktop/src-tauri/Cargo.toml, tauri.conf.json, capabilities/, src/main.rs / lib.rs, icons.
  • Minimal stub frontend only if Tauri tooling requires a local index.html for scaffolding; production must still load the remote URL. Prefer config-only remote URL with empty/minimal local assets.
  • Optional tiny CSS/JS bridge only if needed for titlebar safe-area (e.g. detect Tauri user-agent and pad .zed-titlebar for traffic lights). Prefer CSS-only; avoid product redesign.

Flow

  1. Scaffold Tauri 2 app under apps/desktop (macOS focus).
  2. Configure hybrid devUrl / remote frontendDist.
  3. Configure window: decorations on, titleBarStyle: Overlay (or Transparent + documented traffic lights), reasonable default size (~1200×800), product name memo.
  4. Keep capabilities empty/minimal — no filesystem/db plugins.
  5. Wire workspace + README.
  6. Verify tauri build produces a macOS app that opens the remote site; verify tauri dev against local Next.

Tests

  • No unit-test harness required for the shell itself in v1.
  • Manual verification checklist in QA below.
  • Do not add CI notarization / Apple signing in this issue unless already trivial; document residual risk.

Titlebar / chrome guidance

  • Prefer Overlay titlebar so traffic lights sit over / beside existing .zed-titlebar.
  • If overlap is ugly, add a small left padding to .zed-titlebar when running inside Tauri (detect via window.__TAURI_INTERNALS__ or user-agent / data-desktop="tauri" injected once). Do not invent a second custom HTML titlebar system.
  • Do not disable in-page ⌘B/⌘N.

Edge Cases And Risks

  • Clerk OAuth in WKWebView: GitHub/Clerk OAuth may break or behave oddly inside WKWebView (popups, cookie partitions, redirect URIs). Password login works today; production Clerk path needs allowlisted redirect URLs and possibly open external browser for OAuth — follow-up after Clerk GitHub auth + per-user note sync (new memo Clerk app) #17/Clerk GitHub auth + per-user note sync #18. Call this out in README.
  • Cookie / session storage: remote HTTPS origin cookies in the webview should work for same-site session; test login + note CRUD.
  • CSP / Tauri security: loading a remote URL means the app trusts memo.chasehuh.com. Do not enable broad remote IPC.
  • Notarization / signing: local tauri build may produce an unsigned app that Gatekeeper warns on. Non-goal to fully notarize in this issue unless cheap.
  • Localhost only in dev: tauri dev requires Next (pnpm dev) running; document this.
  • Offline: app will fail without network in prod (by design for v1 remote shell).
  • Shortcut collisions: avoid native menus that bind ⌘N/⌘B to File/Window actions without forwarding.

Non-Goals

  • Local SQLite / CRDT / local-first sync (anarlog-style).
  • Bundling a static Next export or second React frontend for v1.
  • Auto-update (Sparkle / Tauri updater).
  • App Store distribution / notarization pipeline (document only).
  • iOS / iPad / Windows / Linux packaging.
  • Redesigning the memo UI away from the current Zed-like web chrome.
  • Implementing Clerk itself (tracked in Clerk GitHub auth + per-user note sync (new memo Clerk app) #17 / Clerk GitHub auth + per-user note sync #18) — only depend / document.
  • Deep links, custom protocol handlers, tray icons, menubar extras.

Acceptance Criteria

  • GitHub issue exists and this PR implements it (Closes #<this-issue>).
  • apps/desktop (+ src-tauri) lands with Tauri 2 macOS-focused thin shell.
  • Dev loads http://localhost:3000; prod build loads https://memo.chasehuh.com.
  • No second bundled Next frontend / no local notes DB in the desktop app.
  • macOS Overlay/transparent titlebar with traffic lights; UI remains recognizably the web memo chrome.
  • ⌘B / ⌘N still work in-app.
  • README documents run/build + Clerk dependency / OAuth risk.
  • No secrets committed; capabilities stay minimal.
  • tauri build succeeds on macOS (or failure is documented with exact error if environment blocks).

QA Plan

  1. From repo root: install workspace deps; install Rust toolchain if needed.
  2. Terminal A: pnpm dev (Next on :3000).
  3. Terminal B: desktop tauri dev → window shows login/app at localhost; log in with password; create note; toggle sidebar with ⌘B; new note with ⌘N.
  4. tauri build → open built .app → confirms https://memo.chasehuh.com (login redirect OK).
  5. Confirm no target/ / secrets staged.
  6. After Clerk (Clerk GitHub auth + per-user note sync (new memo Clerk app) #17/Clerk GitHub auth + per-user note sync #18): re-test GitHub OAuth inside the shell; if broken, file follow-up (external browser / ASWebAuthenticationSession).

Suggested PR Scope

M — one PR: scaffold apps/desktop, workspace wiring, README, minimal titlebar CSS tweak if required. Do not combine with Clerk (#18) unless already merged and trivial to adapt.

Implementer should use a fresh worktree from origin/main, commit, push, and open PR with Closes #<issue>. Do not merge. Do not force-push. Do not commit .env*.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions