עברית
← Back to the home page

Architecture - Markport

Audience: people changing the code. The “why”, not the “how to use it” (that is README.md). A Hebrew version of this document is at docs/he/architecture.md.

What this is

Markport runs Obsidian’s own renderer (the upstream bundle, vendor/obsidian-mobile/) in a standard browser, using shims that stand in for Electron and Capacitor. After the mobile-first collapse there is one core (client-mobile) with a swappable backend, not two runtimes.

Runtime layers

Layer Status Storage Deployment
serverless ★ primary OPFS in the browser + folder vaults (File System Access API) CF Pages static + Worker proxy
server supported, option 2 real files through /api/fs deployments/server/ (node; no Dockerfile in the repo)
desktop kept, future open - vendor/obsidian-desktop, parallel to mobile

What decides between serverless and server is not a probe or capability detection against /api/fs - there is none. It is the local registry (window.__owLocalVaults, loaded synchronously in a <script> before boot.js; see the load order in index.html). If the vault id appears in the registry, its recorded type ('local' / 'folder') selects OPFS. Otherwise the default is 'server' - including on a static deployment with no server at all (boot.js:149-151):

var __owV = window.__owLocalVaults && window.__owLocalVaults.get(VAULT_ID);
var VAULT_TYPE = __owV ? (__owV.type || 'local') : 'server';

So a vault id that was never created or opened locally, and therefore is not in the registry, will try 'server' even on Cloudflare. There is no automatic fallback to OPFS for an unregistered id.

Directory layout

vendor/                    upstream, gitignored, produced by scripts (shared)
  obsidian-mobile/         the active renderer (from the Android APK)
  obsidian-desktop/        second option (parallel)
  plugins/                 LiveSync and friends
scripts/                   shared tooling: update/patch-obsidian-{mobile,desktop}
src/
  core/                    (future) shared base shims: path/os/url/btime + dispatcher
  client-mobile/           the client (the "Mobile" name stays) - OPFS backend, boot, seed, SW
  runtime-server/          server-specific code, isolated:
     server/               Node: /api/fs, watch, bootstrap
     client-shims/         the HTTP backend branch + server-only shims
  deployments/
     cloudflare/           serverless (static + _worker.js)   <- default
     server/               server deployment (node; no Dockerfile in the repo today)

Guiding principles

Obsidian’s bundle (vendor/)