DEV Community

Cover image for Building a notes + whiteboard + graph app where losing data is not an option
gordey_pro
gordey_pro

Posted on

Building a notes + whiteboard + graph app where losing data is not an option

I built OMNI — one web app for documents, whiteboards, databases and a link graph. The editors
were the easy part: I used ready-made ones, BlockNote for documents and tldraw for boards. The hard part was a promise
I made to myself: a user must never lose a note. Not after a crash, not after two open tabs, not after a bad sync.

OMNI: a board, a table, a kanban and the knowledge graph in one app

Here is what that promise turned into in code.

1. One door for every write

All user data lives in IndexedDB (via Dexie), and there is exactly one place that writes it: a VaultRepo module.
Features never touch the database directly. That sounds bureaucratic, but it means every guarantee below is
implemented once, not once per feature.

localStorage is used for one thing only — the UI theme.

2. Every save is atomic and versioned

Each write is a single transaction. Before an entity is overwritten, the previous version goes to its revision list —
up to 30 revisions per entity. Restoring is just another write through the same door.

3. Delete means "move to trash"

There is no hard delete in normal use. Deleted items go to a trash and can be restored; emptying the trash is a
separate, explicit action. Old work that's still useful goes to an archive instead — out of sight, still searchable.

4. Two tabs, no lost edits

Two open tabs editing the same note is the classic way to lose data in a local-first app. OMNI detects the conflict and
keeps both versions instead of letting the last writer win silently.

5. Backup is one JSON file

The whole vault exports to one JSON file and imports back. Boring, and exactly what you want on a bad day.

6. Schema changes only through migrations

The database schema changes only by a new Dexie version with a migration. No "just add a field" — that is how old
data quietly breaks.

7. Tests guard the promise

All of the above is covered by the test suite, and the rule is simple: if a change breaks a data-safety test, the
change is wrong.

Keeping it fast

Boards, documents and the graph are heavy, so each one is a lazy chunk: you only download tldraw when you open a board.
The core (src/core/) has no React and no editor code, and features don't import each other — which keeps the startup
bundle small and the architecture honest.

The OMNI knowledge graph: every note and its links

AI without giving it the keys

OMNI also exposes an MCP server, so an AI assistant can search the vault, read notes and propose changes. Changes the
owner didn't ask for come in as drafts that wait for approval, and every edit still goes through the same door — soft
delete and revision history included — so even an over-eager AI can't destroy anything for good.

Takeaways

  • Pick one write path and make it the only one.
  • Make deletion reversible by default.
  • Treat "two tabs" as a real user, not an edge case.
  • Use battle-tested editors; spend your effort on the data layer.

I'm Gordey Fisun, I build websites, online stores, Telegram bots and AI assistants for businesses —
gordey.pro.

Top comments (0)