[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-80176":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":15,"forks30d":15,"starsTrendScore":17,"compositeScore":18,"rankGlobal":9,"rankLanguage":9,"license":9,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":19,"hasPages":19,"topics":21,"createdAt":9,"pushedAt":9,"updatedAt":22,"readmeContent":23,"aiSummary":24,"trendingCount":15,"starSnapshotCount":15,"syncStatus":16,"lastSyncTime":25,"discoverSource":26},80176,"obsidian-web","MusiCode1\u002Fobsidian-web","MusiCode1","Run Obsidian's desktop app in a standard browser — no Electron needed",null,"JavaScript",105,27,7,5,0,2,6,4.34,false,"main",[],"2026-06-12 02:03:59","# obsidian-web\n\nRun Obsidian's desktop app in a standard browser — no Electron needed.\n\n**[Live Demo →](https:\u002F\u002Fobsidian-web.tzlev.ovh)**\n\nobsidian-web loads Obsidian's original renderer (`app.js`) completely unmodified and replaces every Node.js \u002F Electron dependency with lightweight HTTP shims. The result is real Obsidian running in any modern browser.\n\n### What works\n\n- Full Markdown editing and preview (CodeMirror + Obsidian's renderer)\n- File tree, tabs, split panes, graph view\n- Bidirectional links and backlinks\n- Search and command palette\n- Core plugins (file explorer, tags, bookmarks, outgoing links, etc.)\n- Real-time sync across tabs via WebSocket\n- RTL \u002F Unicode support\n\n### Fast bootstrap\n\nThe browser version can load faster than the desktop app. Instead of Obsidian reading dozens of config files one by one from disk, everything is served in a single HTTP request (`\u002Fapi\u002Fbootstrap`) — all files, directories, and metadata arrive at once, before Obsidian even starts running. When it calls `statSync` or `readFileSync`, the answer is already waiting in memory.\n\n### Two deployment modes\n\n| | **Node.js server** | **Cloudflare Workers** |\n|---|---|---|\n| Path | `src\u002Fserver\u002F` | `src\u002Fdeployments\u002Fcloudflare\u002F` |\n| Storage | Real filesystem | Durable Object (in-memory) |\n| Persistence | Full | R2 (optional) or reset every N hours |\n| Use case | Personal use, self-hosted | Public demo, zero-maintenance |\n| URL | `http:\u002F\u002Flocalhost:3000` | [obsidian-web.tzlev.ovh](https:\u002F\u002Fobsidian-web.tzlev.ovh) |\n\n## Repo layout\n\n```\nsrc\u002F                         our source code\n├── client\u002F                  desktop runtime (loaded at \u002F)\n├── client-mobile\u002F           mobile runtime (loaded at \u002Fmobile)\n├── server\u002F                  Node.js HTTP\u002FWS backend\n├── plugins\u002F                 system plugin overlay (e.g. obsidian-web-layout)\n└── deployments\u002F             provider-specific deployments\n    └── cloudflare\u002F          Cloudflare Workers + Durable Object\n\nvendor\u002F                      extracted Obsidian bundles (gitignored)\n├── obsidian\u002F                desktop renderer\n├── obsidian-mobile\u002F         mobile renderer (with build-time patches)\n└── Obsidian.AppImage        source binary\n\nuser-data\u002F                   user-facing data\n├── demo-vault\u002F              example vault (tracked)\n└── registry.json            recent-vaults registry (gitignored, runtime)\n\n.tmp\u002F                        intermediate \u002F build artifacts (folder tracked,\n                             contents gitignored via internal .gitignore)\nscripts\u002F                     build tooling (update-obsidian, patch-obsidian-mobile)\n```\n\n---\n\n## Setup (Node.js server)\n\nDownload and extract the latest Obsidian renderer files:\n\n```bash\nnode scripts\u002Fupdate-obsidian.js\n```\n\nInstall and run the backend:\n\n```bash\ncd src\u002Fserver\nnpm install\nnpm run dev   # auto-reloads on file changes (uses node --watch)\n```\n\nFor production (no reload overhead):\n```bash\nnpm start\n```\n\nOpen `http:\u002F\u002F127.0.0.1:3000`.\n\nOpen `http:\u002F\u002F127.0.0.1:3000\u002Fstarter` to manage recent vaults and add a\nserver folder path as a vault.\n\n## Obsidian Version\n\n`vendor\u002Fobsidian\u002F` is generated from the official `obsidianmd\u002Fobsidian-releases` GitHub releases and is intentionally ignored by Git.\n\nUseful commands:\n\n```bash\n# latest stable release\nnode scripts\u002Fupdate-obsidian.js\n\n# specific release\nnode scripts\u002Fupdate-obsidian.js --version 1.12.7\n\n# re-download even if cached\nnode scripts\u002Fupdate-obsidian.js --force\n\n# remove cached .asar.gz\u002F.asar after a successful extraction\nnode scripts\u002Fupdate-obsidian.js --no-cache\n```\n\nThe updater uses the official `obsidian-\u003Cversion>.asar.gz` release asset, verifies the SHA-256 digest when GitHub provides one, extracts it locally, validates required renderer files, then replaces `obsidian\u002F`.\n\n### Mobile bundle (`vendor\u002Fobsidian-mobile\u002F`)\n\nThe project ships **two runtimes** — a desktop one at `\u002F` and a mobile one at `\u002Fmobile`. The mobile runtime needs the Obsidian Android APK bundle, extracted into `vendor\u002Fobsidian-mobile\u002F`. Like `vendor\u002Fobsidian\u002F`, this directory is gitignored and downloaded on demand:\n\n```bash\n# extract vendor\u002Fobsidian-mobile\u002F from the latest Android APK release\nnode scripts\u002Fupdate-obsidian-mobile.js\n\n# specific version\nnode scripts\u002Fupdate-obsidian-mobile.js --version 1.12.7\n```\n\nThis script downloads the official APK, unpacks the `assets\u002Fpublic\u002F` tree to `vendor\u002Fobsidian-mobile\u002F`, and **applies four build-time patches** to `vendor\u002Fobsidian-mobile\u002Fapp.js` (via `scripts\u002Fpatch-obsidian-mobile.js`) that expose `window.__owPlatform`, merge `window.__owPlatformOverrides`, and surface the desktop-layout vault profile panel. If a patch fails to match, the script aborts loudly — that's our signal that the Obsidian minifier changed.\n\nBoth runtimes share the same server. Run **both updater scripts** if you want `\u002F` and `\u002Fmobile` to work. If you only want one of them, you can run just the corresponding script.\n\n| Runtime URL | Updater | Notes |\n|---|---|---|\n| `\u002F` (desktop) | `node scripts\u002Fupdate-obsidian.js` | Required for legacy fallback |\n| `\u002Fmobile` | `node scripts\u002Fupdate-obsidian-mobile.js` | **Preferred runtime.** Applies patches automatically. |\n\n## Configuration\n\nServer environment variables:\n\n- `PORT`: HTTP port, default `3000`.\n- `HOST`: bind address, default `127.0.0.1`.\n- `VAULT_PATH`: vault path relative to the project root or absolute, default `user-data\u002Fdemo-vault`.\n- `VAULT_REGISTRY`: recent-vault registry JSON path, default `user-data\u002Fregistry.json`.\n\n## Deployment\n\n## Cloudflare Workers demo (`src\u002Fdeployments\u002Fcloudflare\u002F`)\n\nA standalone deployment that runs entirely on Cloudflare's edge — no server to maintain.\n\n```bash\ncd src\u002Fdeployments\u002Fcloudflare\nnpm install\nnpm run deploy\n```\n\n### Architecture\n\n```\nBrowser → CF Worker → Durable Object (VaultDO)\n             ↓\n       \u002Fapi\u002F* → DO (vault in memory)\n       other  → static assets (CF CDN)\n```\n\nThe Durable Object holds the entire vault in a `Map\u003Cpath, {content, mtime, size}>`. A single `\u002Fapi\u002Fbootstrap` call preloads all files and directory listings so Obsidian can boot with minimal latency.\n\n### Demo mode (`DEMO_MODE=true`)\n\n- Vault is initialized from a template on cold start\n- Resets automatically every N hours via DO alarm\n- Core template files (Welcome, How It Works, etc.) are protected from deletion\n- No auth required — anyone can visit and try it\n\n### Personal mode (`DEMO_MODE=false`)\n\n- Writes persist to R2\n- Requires `API_KEY` secret for access\n- No automatic reset\n\n### Configuration\n\nEnvironment variables in `wrangler.toml`:\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `DEMO_MODE` | `\"true\"` | Enable demo mode (in-memory, auto-reset) |\n| `RESET_INTERVAL_HOURS` | `\"4\"` | Hours between automatic vault resets |\n| `API_KEY` | — | Required when `DEMO_MODE=false` (set via `wrangler secret put API_KEY`) |\n\n### Key files\n\n| File | Purpose |\n|------|---------|\n| `src\u002Fdeployments\u002Fcloudflare\u002Findex.js` | Worker entry: routes `\u002Fapi\u002F*` to DO, else to CDN |\n| `src\u002Fdeployments\u002Fcloudflare\u002Fvault-do.js` | Durable Object: vault state, WebSocket, alarm reset |\n| `src\u002Fdeployments\u002Fcloudflare\u002Ftemplate.js` | Demo vault content (loaded on cold start \u002F reset) |\n| `src\u002Fdeployments\u002Fcloudflare\u002Fapi\u002Fbootstrap.js` | Single-shot preload: electron IPC + fs + dirs |\n| `src\u002Fdeployments\u002Fcloudflare\u002Fapi\u002Ffs.js` | REST file system (stat, read, write, readdir, etc.) |\n| `src\u002Fdeployments\u002Fcloudflare\u002Fapi\u002Felectron.js` | IPC channel stubs |\n| `.tmp\u002Fdeployments\u002Fcloudflare\u002Fpublic\u002F...` | Built static assets (generated by `npm run build`) |\n\n---\n\n## Node.js deployment\n\nThe Node.js server (`src\u002Fserver\u002F`) can be deployed to any Linux box. A typical setup:\n\n1. Clone the repo and run `node scripts\u002Fupdate-obsidian.js` to get Obsidian's renderer files\n2. `cd src\u002Fserver && npm install && npm start`\n3. Put it behind a reverse proxy (nginx, Caddy, Cloudflare Tunnel) with HTTPS\n4. Do not expose the server directly to the internet without auth — there is no application-level authentication\n\n## Notes\n\n- Obsidian's extracted files are treated as third-party artifacts. Do not edit files under `vendor\u002Fobsidian\u002F` or `vendor\u002Fobsidian-mobile\u002F`; update wrappers\u002Fshims instead.\n- The default vault is `user-data\u002Fdemo-vault\u002F`.\n- The current starter folder picker is prompt-based: enter an absolute server path.\n- Do not bind the server to a public IP without a tunnel or auth layer in front.\n- Current architecture and roadmap are in `PLAN.md`.\n\n## Disclaimer\n\nThis is an **educational proof-of-concept** exploring how Electron-based apps can run in a standard browser. It is not affiliated with, endorsed by, or associated with [Obsidian](https:\u002F\u002Fobsidian.md) or Dynalist Inc.\n\nThis repository does **not** include Obsidian's source code. The `vendor\u002Fobsidian\u002F` and `vendor\u002Fobsidian-mobile\u002F` directories are gitignored — users must download Obsidian's renderer themselves using the provided setup scripts. Obsidian's code remains the property of Dynalist Inc. under their [Terms of Service](https:\u002F\u002Fobsidian.md\u002Fterms).\n\nIf the Obsidian team has any concerns about this project, please [open an issue](https:\u002F\u002Fgithub.com\u002FMusiCode1\u002Fobsidian-web\u002Fissues) and we will address them promptly.\n\n## Credits\n\nBuilt by [MusiCode1](https:\u002F\u002Fgithub.com\u002FMusiCode1) and [Claude Code](https:\u002F\u002Fclaude.ai\u002Fcode).\n","obsidian-web 项目允许用户在标准浏览器中运行 Obsidian 桌面应用，无需依赖 Electron。它通过加载原始的 Obsidian 渲染器，并使用轻量级 HTTP 替换所有 Node.js\u002FElectron 依赖项，从而实现在现代浏览器中运行完整的 Obsidian 应用。核心功能包括全面的 Markdown 编辑与预览、文件树管理、双向链接和反向链接支持、搜索及命令面板等，并且支持实时同步。此外，该项目提供了两种部署模式：Node.js 服务器适合个人或自托管场景，而 Cloudflare Workers 则适用于公共演示或零维护需求。这种架构不仅保留了 Obsidian 的主要特性，还提高了启动速度，使得整个应用能够更快地加载。","2026-06-11 03:59:32","CREATED_QUERY"]