Last month I was on a train. Tunnel. My notes app showed a spinner.
I just wanted to write down one idea, and my notes app was waiting on a server.
So I built Dovli: a calm place to write, plan and sketch. Notes, docs, to-dos and whiteboards in one app, and it keeps working when the internet doesn't.
What Dovli does
- ✍️ Block editor with
/commands, nested pages, tables and to-do lists - 🔎 ⌘K search across every page, plus #tags
- 🧠 Whiteboards and flowcharts that sit right next to your notes
- 🎨 Page styles (Linen, Cobalt Night, Sage Garden and more) and light/dark themes
- 📴 Offline-first: edits save on your device and sync when you're back online
- 🤖 MCP support: Claude Desktop, Claude Code or Codex can search, write and tidy your pages
- 📥 Imports from Notion, Evernote and Craft
- 💻 Runs on the web, Mac and Windows, and Android (APK now, Google Play on 7 November)
It's free.
How it's built
- Turborepo monorepo with a Next.js web app
- Expo / React Native for Android. The mobile app reuses the web editor as an Expo DOM component, so I didn't write the editor twice
- Electron for the desktop app, reusing the same web code
- BlockNote for the editor and Excalidraw for whiteboards
- Firebase for sign-in and sync
Where I'm stuck, and I'd love your take 👇
You edit the same note on your laptop and your phone, both offline. Then you reconnect.
Which version should win?
- Last write wins: simple, but you can lose work
- Merge both: smart, but sometimes messy
- Ask the user: safe, but annoying
Reply with 1, 2 or 3 and why. I'll build the most popular answer into Dovli and credit you in the changelog. 🙌
🔗 Try it: dovli.in
💻 Code: github.com/MayankJha0333/dovli
Top comments (7)
Good catch, thanks for pointing this out.
Content edits are merging fine per block ID, but block order depends on whichever device syncs last. Because of this, a move + edit can lose the move, and an indent + edit can even duplicate the block. I was able to reproduce both issues.
I'm fixing this now by handling block position separately from content so both changes can be merged correctly.
Good, and clearing both symptoms at once is the right instinct. Two mechanisms, because they fail differently.
Order. Stop storing an integer position. Store a string that sorts between its neighbours, so a move is just "assign a new key". The
fractional-indexingpackage (rocicorp) is about two functions and does exactly this; it is the same idea Figma wrote up for their multiplayer docs. Then sort by(key, id). Two devices that pick identical keys still land in the same order without ever talking, which is the part that kills last-writer-wins flapping.The duplicate on indent is not an ordering bug, it is an identity bug. If the split mints a fresh block id on device A while device B keeps the original id carrying the same content, a union-by-id merge legitimately produces two blocks, both of which look correct. So: ids are minted once at creation, never reused, never derived from content. On merge, union by id, and treat same id, different content as a collision (ask, or bump a per-block counter) rather than as something to reconcile silently.
After that, a move and an edit cannot destroy each other, because they no longer write the same field.
Would love your honest thoughts
Maybe connect the 2 devices with bluetooth for offline sync! 😀
I’d choose 3, with one distinction: merge independent edits automatically, but when both devices change the same block, show the two versions and let the person choose. Keep a small conflict history so a mistaken choice is recoverable. That avoids silently losing work without interrupting every offline edit.
Your update about separating block position from content makes sense, and I'd add a delete-versus-edit case before choosing a default. If I delete a block on my laptop while my offline phone adds a paragraph to it, silently picking either device loses something intentional. I'd preserve the edited version as recoverable content and make that collision visible after sync. What happens today if the deleted block is a parent containing children that the other device has moved or edited?
Some comments may only be visible to logged-in visitors. Sign in to view all comments.