{"_id":"@allenwu06/vault-bridge","name":"@allenwu06/vault-bridge","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@allenwu06/vault-bridge","version":"0.1.0","description":"Serves any local markdown vault (Obsidian / Files.md / a plain folder) over localhost so you can read and quick-edit notes on your phone in any browser — including Firefox and mobile Safari — with no Chrome File System API, no cloud sync, and no account. ","type":"module","license":"MIT","private":false,"bin":{"vault-bridge":"bin/vault-bridge.js"},"engines":{"node":">=20"},"scripts":{"test":"vitest run","test:watch":"vitest","start":"node bin/vault-bridge.js"},"keywords":["markdown","obsidian","files.md","notes","vault","firefox","mobile","wikilink","backlink","local-first","no-cloud","cli"],"devDependencies":{"vitest":"^2.1.9"},"_id":"@allenwu06/vault-bridge@0.1.0","_nodeVersion":"25.9.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-XiniJDzruBiihHsEm/7TSPKJMxcPHBYlxMWJqdXN0qdTC5SxOQ3hw8nbHSXEKmUjwJWUzC0vDBEP4nzs0wQuhA==","shasum":"5810ab8f47c0d5551043fe489696cd60e04b9da9","tarball":"https://registry.npmjs.org/@allenwu06/vault-bridge/-/vault-bridge-0.1.0.tgz","fileCount":13,"unpackedSize":78241,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDirMz1RfTTzJAyk1CZPVv3yZzKC63oP9Vqz4wl3V75aAiEA8gysSxXM3F5S6rGBmxIUwWDuapBVDKFMONshywltfIk="}]},"_npmUser":{"name":"allenwu06","email":"allenwu@umich.edu"},"directories":{},"maintainers":[{"name":"allenwu06","email":"allenwu@umich.edu"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/vault-bridge_0.1.0_1779208961682_0.9669582337436229"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-19T16:42:41.550Z","0.1.0":"2026-05-19T16:42:41.819Z","modified":"2026-05-19T16:42:42.032Z"},"maintainers":[{"name":"allenwu06","email":"allenwu@umich.edu"}],"description":"Serves any local markdown vault (Obsidian / Files.md / a plain folder) over localhost so you can read and quick-edit notes on your phone in any browser — including Firefox and mobile Safari — with no Chrome File System API, no cloud sync, and no account. ","keywords":["markdown","obsidian","files.md","notes","vault","firefox","mobile","wikilink","backlink","local-first","no-cloud","cli"],"license":"MIT","readme":"# vault-bridge\n\n**Read and quick-edit your folder of markdown notes on your phone — in any browser, including Firefox and mobile Safari.**\n\nYou have a folder of `.md` notes (an Obsidian vault, a\n[Files.md](https://github.com/zakirullin/files.md) vault, or just plain\nmarkdown files) and you want to read and tweak them from your phone or in\nFirefox — not only in Chrome, and without standing up a server and a chat-bot\nlogin just to do it. vault-bridge does exactly that: it runs a tiny local\nprogram over *your own folder* and opens a clean, touch-friendly\nreader/editor. Your phone, your laptop, Firefox, Safari, Chrome — anything\nthat can open a web address works, because the browser is just a thin window;\nthe actual reading and writing of files is done by the local program, not the\nbrowser.\n\n```bash\nnpx @allenwu06/vault-bridge ./my-vault\n```\n\nNo install. No setup. No account. No cloud. No usage tracking. Zero outside\ncode dependencies.\n\n> _Screenshots: placeholder._ This is a faceless utility; a short screen\n> capture (phone: list → note → edit → save) belongs here and is the only\n> thing this README is missing on purpose — there are deliberately **no\n> invented benchmarks or numbers** anywhere in it.\n\n---\n\n## Why this exists\n\n[Files.md](https://github.com/zakirullin/files.md) — an open-source\nObsidian alternative — hit the Show HN front page\n([526 points, thread](https://news.ycombinator.com/item?id=48179677)).\nIt's nice. But the top comments named three concrete gaps, and the author\nconfirmed each one. vault-bridge exists to fill exactly those three gaps —\nnothing more:\n\n| The gap (verbatim from the HN thread) | Author's reply | What vault-bridge does |\n|---|---|---|\n| _\"Post it again when it works in Firefox.\"_ — and _\"Only works in Chrome!\"_, _\"Let us know when this isn't a Chrome-specific tool.\"_ | _\"Once they'll support Local File System API!\"_ / _\"Local File System API has limited support in other browsers.\"_ | **Works in Firefox and every browser today.** It does **not** use the Chrome-only File System Access API. The local process owns the folder; the browser only does `fetch()`. Firefox support is not blocked on a browser API because we don't use that API. |\n| _\"Is there a way to follow inline links from a mobile device? Doesn't seem to work for me in mobile Safari.\"_ / _\"Doesn't work in Safari though, which is a non-starter for me.\"_ | _\"It is not very well tested on mobiles yet.\"_ | **Mobile-first, not mobile-afterthought.** Responsive layout, large touch targets, safe-area insets for the iPhone notch, no zoom-on-focus, tappable wikilinks. Built and tested as a phone surface first. |\n| _\"seems overkill to me to run a Go server to sync with a telegram bot to authenticate.\"_ | _\"You don't need to spin up the server… Optional sync is only working with chatbot auth for now.\"_ | **No sync service, no bot, no auth dance in the free tier.** It serves the folder you point it at. Reading/editing your own vault from your own phone on your own Wi-Fi needs none of that. (A hosted sync-relay may come later as a separate paid option — it is **not** in this package and not required for anything here.) |\n\nThis is **not** a general \"better Obsidian\". It is a small bridge that\ncovers the specific, acknowledged, currently-unowned Files.md gaps.\n\n## What you get\n\n- **List & search** every note in the vault (filename + full-text,\n  instant for a personal vault).\n- **Good markdown rendering** — headings, lists, task checkboxes,\n  code blocks, quotes, images, links — output is HTML-escaped, so a note\n  containing `<script>` renders as inert text, never executes.\n- **Obsidian-compatible `[[wikilinks]]`** with aliases (`[[Note|alias]]`),\n  headings (`[[Note#Section]]`), folder paths, and a **backlinks**\n  (\"linked from\") panel.\n- **Quick-edit + save** straight back to the `.md` file.\n- **New note** creation (won't ever overwrite an existing file).\n- **`--read-only`** mode for safe browsing.\n\n## Data safety (this is the part that matters)\n\nYour notes are the whole point. The write path is deliberately paranoid\nand is the most heavily tested part of the codebase:\n\n- **Atomic writes.** A save is written to a temp file *in the same\n  directory*, `fsync`'d, then `rename`'d over the target (an atomic\n  operation on one filesystem), then the directory is `fsync`'d. A crash\n  or power loss at any instant leaves **either the complete old file or\n  the complete new file** — never a truncated, empty, or half-written\n  note. The temp file is always cleaned up, even on failure.\n- **No lost update.** When you open a note the server hands you its\n  modified-time. On save, that timestamp must still match. If the file\n  changed underneath you (another device, another tab, an external\n  editor), the save is **refused with a clear message** instead of\n  silently clobbering the other change. You are told; you are not\n  overwritten.\n- **No silent reinterpretation / no path escape.** Every path is\n  contained to the vault root. `..`, absolute paths, NUL bytes, and\n  symlinks that point outside the vault are all refused loudly.\n- **Never deletes.** vault-bridge has no delete endpoint. Saving an\n  empty note writes an empty file; it does not remove it.\n\nThese are not aspirations — see\n[`test/safe-write.test.js`](test/safe-write.test.js): byte-exact unicode\nroundtrip, a simulated power-loss-during-fsync that asserts the original\nnote is intact and no temp file leaked, the no-lost-update guard under\nconcurrent writers, and the path-containment refusals.\n\n## Security model — read this before `--host`\n\n**By default, only this computer can reach it.** `npx @allenwu06/vault-bridge ./my-vault`\nlistens on `127.0.0.1` (localhost — your own machine only). Nothing else on\nyour network, and nothing on the internet, can connect. No access password is\nneeded because no one else can reach it in the first place.\n\n**To read it on your phone you have to open it up to your local network**\n(your home/office Wi-Fi — your \"LAN\"), and the moment you do, **vault-bridge\nrequires an access token** (a long random password it prints for you):\n\n```bash\nnpx @allenwu06/vault-bridge ./my-vault --host 0.0.0.0          # phone access\nnpx @allenwu06/vault-bridge ./my-vault --host 0.0.0.0 --read-only   # safer\n```\n\nWhen the bind is **not** loopback:\n\n- A random token is generated (`crypto.randomBytes`) and **printed once\n  in your terminal**, inside a copy-paste URL you open on your phone.\n- **Every request** must present that token (`?token=…` in the URL, or an\n  `Authorization: Bearer` header) or it gets a `401`. The comparison is\n  constant-time.\n- There is **no code path** that serves a non-loopback bind without a\n  token. Your notes are **never silently world-open**. This invariant is\n  asserted by [`test/lan-security.test.js`](test/lan-security.test.js)\n  (\"there is NO way to construct a non-loopback server without a token\").\n\n**Honest caveats about LAN mode** (stated loudly on purpose):\n\n- That token rides in a plain web address over **plain, unencrypted HTTP**\n  (there is no TLS — the encryption that puts the padlock on `https://`).\n  Anyone who can watch that network traffic, or anyone you forward the URL\n  to, gets in. Treat it like a password. It changes every time you start the\n  process.\n- This is designed for **your own device on your own trusted Wi-Fi**, for\n  the length of a session. It is **not** an authentication system, not\n  hardened for a hostile network, and **must not** be port-forwarded to\n  the public internet. If you need that, you want the (future, separate)\n  hosted relay — not `--host 0.0.0.0`.\n- Prefer `--read-only` when you only need to read on the phone.\n- vault-bridge makes **no outbound connections** of any kind. No\n  telemetry, no phone-home, no update check. The only socket it opens is\n  the listener you asked for.\n\n## Install / run\n\nZero-install via `npx`:\n\n```bash\nnpx @allenwu06/vault-bridge /path/to/your/vault\n```\n\nOr clone and run:\n\n```bash\ngit clone <this repo> && cd files-md-mobile-bridge\nnpm ci\nnode bin/vault-bridge.js ./examples/sample-vault\n```\n\n### Options\n\n```\nvault-bridge <vault-folder> [options]\n\n  --host <addr>   Bind interface. Default 127.0.0.1 (localhost only, no\n                  token). Use 0.0.0.0 (or a LAN IP) for phone access —\n                  this REQUIRES the token printed at startup.\n  --port <n>      Port (default 4321). 0 = random free port.\n  --read-only     Serve notes but refuse every write.\n  -h, --help      Help (includes the security model).\n  -v, --version   Version.\n```\n\n## Honest scope / limitations\n\nvault-bridge is intentionally small and is blunt about what it is not:\n\n- **Not a sync service.** The free package serves a local folder. It does\n  not sync between devices, resolve merge conflicts across machines, or\n  store anything in a cloud. (A hosted sync-relay may exist later as a\n  separate, optional, paid thing. It is not here and nothing here needs\n  it.)\n- **Not a full Obsidian.** No graph view, no plugins, no canvas, no live\n  preview while typing, no embeds rendering (an `![[embed]]` is shown as\n  a reference, not inlined). The markdown renderer covers the common note\n  subset well; it is **not** a full CommonMark/GFM engine (no tables, no\n  footnotes, no nested-list edge cases). It is a *reader + quick-edit*,\n  not an authoring environment.\n- **Not built for a 100k-note vault.** Search and the backlink index read\n  files on demand. Instant for a personal vault; not an indexed search\n  engine.\n- **LAN mode is session-grade, not internet-grade.** See the security\n  model above. Do not expose it publicly.\n- **No tests claim a number this README repeats.** There are no\n  benchmarks here. \"Fast\" means \"no build step, no framework, files read\n  on demand\"; measure it on your own vault.\n\nIf a limitation above is a dealbreaker for you, that is useful signal —\nplease tell us (below). If it is *intended behaviour* you are filing as a\nbug (e.g. \"it doesn't sync between my devices\"), it is documented here on\npurpose; reports about the **data-safety and the Firefox/mobile\nexperience** are the ones that move the needle.\n\n## Feedback — read exactly as written\n\nThis product lives or dies on one question: **does it actually fill the\nFiles.md gaps for real vault users, safely?** Your words are the signal.\n\nThe zero-friction way: open an issue and add the **`vault-bridge-feedback`**\nlabel. Maintainers watch that label. Or use the\n[structured template](.github/ISSUE_TEMPLATE/vault-bridge-feedback.yml).\n\nWhatever you write is **captured and read exactly as written** — never\nsummarized or paraphrased. See [`FEEDBACK.md`](FEEDBACK.md) and the\nverbatim/append-only/corrupt-resilient contract in\n[`src/feedback.js`](src/feedback.js) (tested in\n[`test/feedback.test.js`](test/feedback.test.js)).\n\n## Tests\n\n```bash\nnpm ci && npm test\n```\n\nNo network beyond an ephemeral `127.0.0.1` server the tests start\nthemselves, no API key, no cloud. 62 tests: safe-write (byte-exact\nroundtrip, simulated-crash atomicity, no-lost-update, path containment),\nLAN token gate, list/search, markdown render + XSS safety,\nwikilink/backlink, CLI, verbatim feedback. See [`SPEC.md`](SPEC.md).\n\n## License\n\n[MIT](LICENSE).\n","readmeFilename":"README.md","_rev":"1-42346cc5385975480ef074417282eeb0"}