@allenwu06/vault-bridge
v0.1.0
Published
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.
Downloads
93
Maintainers
Readme
vault-bridge
Read and quick-edit your folder of markdown notes on your phone — in any browser, including Firefox and mobile Safari.
You have a folder of .md notes (an Obsidian vault, a
Files.md vault, or just plain
markdown files) and you want to read and tweak them from your phone or in
Firefox — not only in Chrome, and without standing up a server and a chat-bot
login just to do it. vault-bridge does exactly that: it runs a tiny local
program over your own folder and opens a clean, touch-friendly
reader/editor. Your phone, your laptop, Firefox, Safari, Chrome — anything
that can open a web address works, because the browser is just a thin window;
the actual reading and writing of files is done by the local program, not the
browser.
npx @allenwu06/vault-bridge ./my-vaultNo install. No setup. No account. No cloud. No usage tracking. Zero outside code dependencies.
Screenshots: placeholder. This is a faceless utility; a short screen capture (phone: list → note → edit → save) belongs here and is the only thing this README is missing on purpose — there are deliberately no invented benchmarks or numbers anywhere in it.
Why this exists
Files.md — an open-source Obsidian alternative — hit the Show HN front page (526 points, thread). It's nice. But the top comments named three concrete gaps, and the author confirmed each one. vault-bridge exists to fill exactly those three gaps — nothing more:
| The gap (verbatim from the HN thread) | Author's reply | What vault-bridge does |
|---|---|---|
| "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. |
| "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. |
| "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.) |
This is not a general "better Obsidian". It is a small bridge that covers the specific, acknowledged, currently-unowned Files.md gaps.
What you get
- List & search every note in the vault (filename + full-text, instant for a personal vault).
- Good markdown rendering — headings, lists, task checkboxes,
code blocks, quotes, images, links — output is HTML-escaped, so a note
containing
<script>renders as inert text, never executes. - Obsidian-compatible
[[wikilinks]]with aliases ([[Note|alias]]), headings ([[Note#Section]]), folder paths, and a backlinks ("linked from") panel. - Quick-edit + save straight back to the
.mdfile. - New note creation (won't ever overwrite an existing file).
--read-onlymode for safe browsing.
Data safety (this is the part that matters)
Your notes are the whole point. The write path is deliberately paranoid and is the most heavily tested part of the codebase:
- Atomic writes. A save is written to a temp file in the same
directory,
fsync'd, thenrename'd over the target (an atomic operation on one filesystem), then the directory isfsync'd. A crash or power loss at any instant leaves either the complete old file or the complete new file — never a truncated, empty, or half-written note. The temp file is always cleaned up, even on failure. - No lost update. When you open a note the server hands you its modified-time. On save, that timestamp must still match. If the file changed underneath you (another device, another tab, an external editor), the save is refused with a clear message instead of silently clobbering the other change. You are told; you are not overwritten.
- No silent reinterpretation / no path escape. Every path is
contained to the vault root.
.., absolute paths, NUL bytes, and symlinks that point outside the vault are all refused loudly. - Never deletes. vault-bridge has no delete endpoint. Saving an empty note writes an empty file; it does not remove it.
These are not aspirations — see
test/safe-write.test.js: byte-exact unicode
roundtrip, a simulated power-loss-during-fsync that asserts the original
note is intact and no temp file leaked, the no-lost-update guard under
concurrent writers, and the path-containment refusals.
Security model — read this before --host
By default, only this computer can reach it. npx @allenwu06/vault-bridge ./my-vault
listens on 127.0.0.1 (localhost — your own machine only). Nothing else on
your network, and nothing on the internet, can connect. No access password is
needed because no one else can reach it in the first place.
To read it on your phone you have to open it up to your local network (your home/office Wi-Fi — your "LAN"), and the moment you do, vault-bridge requires an access token (a long random password it prints for you):
npx @allenwu06/vault-bridge ./my-vault --host 0.0.0.0 # phone access
npx @allenwu06/vault-bridge ./my-vault --host 0.0.0.0 --read-only # saferWhen the bind is not loopback:
- A random token is generated (
crypto.randomBytes) and printed once in your terminal, inside a copy-paste URL you open on your phone. - Every request must present that token (
?token=…in the URL, or anAuthorization: Bearerheader) or it gets a401. The comparison is constant-time. - There is no code path that serves a non-loopback bind without a
token. Your notes are never silently world-open. This invariant is
asserted by
test/lan-security.test.js("there is NO way to construct a non-loopback server without a token").
Honest caveats about LAN mode (stated loudly on purpose):
- That token rides in a plain web address over plain, unencrypted HTTP
(there is no TLS — the encryption that puts the padlock on
https://). Anyone who can watch that network traffic, or anyone you forward the URL to, gets in. Treat it like a password. It changes every time you start the process. - This is designed for your own device on your own trusted Wi-Fi, for
the length of a session. It is not an authentication system, not
hardened for a hostile network, and must not be port-forwarded to
the public internet. If you need that, you want the (future, separate)
hosted relay — not
--host 0.0.0.0. - Prefer
--read-onlywhen you only need to read on the phone. - vault-bridge makes no outbound connections of any kind. No telemetry, no phone-home, no update check. The only socket it opens is the listener you asked for.
Install / run
Zero-install via npx:
npx @allenwu06/vault-bridge /path/to/your/vaultOr clone and run:
git clone <this repo> && cd files-md-mobile-bridge
npm ci
node bin/vault-bridge.js ./examples/sample-vaultOptions
vault-bridge <vault-folder> [options]
--host <addr> Bind interface. Default 127.0.0.1 (localhost only, no
token). Use 0.0.0.0 (or a LAN IP) for phone access —
this REQUIRES the token printed at startup.
--port <n> Port (default 4321). 0 = random free port.
--read-only Serve notes but refuse every write.
-h, --help Help (includes the security model).
-v, --version Version.Honest scope / limitations
vault-bridge is intentionally small and is blunt about what it is not:
- Not a sync service. The free package serves a local folder. It does not sync between devices, resolve merge conflicts across machines, or store anything in a cloud. (A hosted sync-relay may exist later as a separate, optional, paid thing. It is not here and nothing here needs it.)
- Not a full Obsidian. No graph view, no plugins, no canvas, no live
preview while typing, no embeds rendering (an
![[embed]]is shown as a reference, not inlined). The markdown renderer covers the common note subset well; it is not a full CommonMark/GFM engine (no tables, no footnotes, no nested-list edge cases). It is a reader + quick-edit, not an authoring environment. - Not built for a 100k-note vault. Search and the backlink index read files on demand. Instant for a personal vault; not an indexed search engine.
- LAN mode is session-grade, not internet-grade. See the security model above. Do not expose it publicly.
- No tests claim a number this README repeats. There are no benchmarks here. "Fast" means "no build step, no framework, files read on demand"; measure it on your own vault.
If a limitation above is a dealbreaker for you, that is useful signal — please tell us (below). If it is intended behaviour you are filing as a bug (e.g. "it doesn't sync between my devices"), it is documented here on purpose; reports about the data-safety and the Firefox/mobile experience are the ones that move the needle.
Feedback — read exactly as written
This product lives or dies on one question: does it actually fill the Files.md gaps for real vault users, safely? Your words are the signal.
The zero-friction way: open an issue and add the vault-bridge-feedback
label. Maintainers watch that label. Or use the
structured template.
Whatever you write is captured and read exactly as written — never
summarized or paraphrased. See FEEDBACK.md and the
verbatim/append-only/corrupt-resilient contract in
src/feedback.js (tested in
test/feedback.test.js).
Tests
npm ci && npm testNo network beyond an ephemeral 127.0.0.1 server the tests start
themselves, no API key, no cloud. 62 tests: safe-write (byte-exact
roundtrip, simulated-crash atomicity, no-lost-update, path containment),
LAN token gate, list/search, markdown render + XSS safety,
wikilink/backlink, CLI, verbatim feedback. See SPEC.md.
License
MIT.
