A writing desk where the manuscript never leaves the machine
A desktop notebook built on Electron, where documents live on disk, the editor is a real rich-text surface, and the AI assistant reads only what the writer hands it.
What the engagement involved
- Industry
- Book Publishing
- Duration
- 14 weeks
- Cooperation model
- Fixed price, phased
- Services
- Desktop engineeringEditor experienceLocal-first data
- Integrations
- Auto-update channelCode signing & notarizationSentryAnthropic API
- Technologies
- ElectronNext.jsTypeScriptTiptapelectron-storeTailwind CSS
- Team
- 1 Project lead2 Desktop engineers1 Product designer
Client name withheld under NDA. Engagement details are shown to the extent our agreement permits.
The hard problem
Writers won't put an unfinished manuscript into a web app owned by someone else, and the tools that respect that are usually plain-text editors with no structure. The brief asked for both: real formatting, and a file that stays on disk.
The trust problem was specific. Writers weren't worried about encryption; they were worried that a tool with a sync feature will eventually sync, through a default, an update or a setting they didn't find. That's a question of architecture, and no privacy page answers it. The app has to have no path at all.
An Electron application with a Tiptap editing surface, documents persisted locally through electron-store, and an assistant scoped to the passage the writer selects, never the whole library.
The system we were asked to build
A publisher wanted a notebook their writers would trust with unpublished work. We built the desktop application, the editing surface and the assistant, all under one constraint: nothing leaves the machine unless the writer asks it to.
A publisher wanting a notebook its writers would actually put unpublished manuscripts into. Both available categories failed: web tools that hold the file on someone else's server, and plain-text editors that keep it local by giving up structure entirely. The brief was to have both, which is what made it a desktop build.
Desktop & Product Engineering
How the pieces fit
- 01
Made local disk the primary store, with no implicit sync anywhere in the app
No implicit sync was the requirement writers stated, and it's architectural: there's no setting to find and switch off.
- 02
Built the editor on Tiptap so structure survives a round trip intact
Tiptap models the document as structured content, so headings, lists and emphasis survive a save and reopen intact.
- 03
Split the window into navigation and notes so a long manuscript stays navigable
The window splits into a navigation rail and the notes surface, so a manuscript of dozens of documents stays reachable without a modal or a file dialog.
- 04
Scoped the assistant to the current selection, so what's sent is exactly what was chosen
The assistant receives the highlighted passage and nothing else, for the length of the request, which makes the scope claim something a writer can check.
- 05
Kept auth entirely optional: the app is useful before anyone signs in
Signed-out writers get a full layout of their own. An account only adds to it.
Local by default
Documents persist to disk through electron-store. There's no background sync to switch off.
Documents persist to disk through electron-store as the writer types, so the work exists on their machine and nowhere else by default. There's no background sync to discover and switch off, and no account required to start. The file is the source of truth: the arrangement writers actually asked for, and the one most writing tools have quietly stopped offering.
- Persisted to disk as you type; the file is the source of truth
- No background sync to discover and disable
- No account needed to start writing
Nine versions of chapter 14 kept on disk, with the words added and removed between the last two shown inline. Beside them, the path of the chapter's file on this machine, saved as you type, and no background sync.
Real rich text
A notes document with headings, a bulleted list, a quote and emphasis, beside the document model it's saved as: nodes and marks, no styling, with the same structure counted when it's reopened from disk.
Tiptap models headings, lists and emphasis, so structure survives being saved and reopened.
Tiptap models the document as structured content (headings, lists, emphasis, quotes), so the structure survives being saved, closed and reopened, and exports without a reconstruction step. Editing state is normalized on save, which keeps a document written across fifty sessions from accumulating the invisible markup that eventually breaks an export.
- Structured document model, not styled text
- Structure survives save, close and reopen intact
- Normalized on save, so markup can't accumulate
Selection-scoped assistant
The assistant sees the passage the writer highlighted. Never the document, never the library.
The assistant is scoped to the passage the writer highlighted: the selection only, and only for as long as the request takes. That boundary is the product decision. A writer will accept help with a paragraph they chose to share and won't accept a tool that reads the manuscript, and the two look identical unless the scope is enforced in code.
- Scope is the selection, never the document or the library
- Nothing retained past the request
- Enforced in the call, not promised in a policy
The assistant scoped to a selection: one highlighted sentence, forty-one words sent, and an explicit list of everything that stayed on the machine, from the rest of the chapter to the notes and file paths.
The app before anyone signs in: a new manuscript saving to disk, no account, and a table of what signing in would add, which is sync across machines and a longer assistant context. It removes nothing.
Usable signed out
Guest and authenticated layouts are separate; an account adds capability and gates nothing.
Guest and authenticated states are separate layouts, so a signed-out writer gets a complete tool and not a demonstration of what they're missing. An account adds capability (sync across machines, longer assistant context) and removes nothing. Signing out later leaves every local document exactly where it was.
- Separate layouts, no grayed-out features
- An account adds capability and removes nothing
- Signing out leaves every local document in place
A navigable manuscript
A navigation rail beside the notes surface keeps dozens of documents reachable without losing the current one.
A navigation rail sits beside the writing surface holding the manuscript's documents, so dozens stay reachable without a modal or a file dialog. Switching preserves cursor position and scroll in the document being left, which makes moving between a chapter and its notes feel like turning a page.
- Persistent rail: dozens of documents reachable without a dialog
- Cursor and scroll preserved in the document you leave
- Moving between chapter and notes costs nothing
The whole manuscript as a table: twenty-four chapters across three parts, with word counts, draft status, progress toward each chapter's length and how much is still to write.
Phase by phase
Phase 1: The Shell
A Desktop App, Not A Wrapped Website
Built the Electron main and renderer processes properly: a real window with real menus, local file access, and a renderer that doesn't assume a network.
- Electron Shell
- Local Storage Layer
- Window & Menu Behaviour
Phase 2: The Editing Surface
Structure That Survives A Round Trip
Built the editor on Tiptap so headings, lists and emphasis are modeled as structure, and a document reopened a month later is the document that was saved.
- Tiptap Editor
- Document Schema
- Autosave
Phase 3: Navigation
Finding A Passage In A Long Manuscript
Split the main view into a navigation rail and the notes surface, so a writer working across dozens of documents moves between them without losing their place.
- Navigation Rail
- Notes List
- Document Switching
Phase 4: The Assistant
Scoped To The Selection
Wired the assistant to operate on the selected passage only. What gets sent is what the writer highlighted, which is a promise the interface can actually keep.
- Selection-Scoped Assistant
- Prompt Surface
- Explicit Send
Phase 5: Optional Accounts
Useful Before Sign-In
Separated the guest and authenticated layouts so the application is fully usable without an account; signing in adds capability instead of unlocking the product.
- Guest Layout
- Auth Layout
- Optional Account Flow
Search across manuscript, notes and research at once: ninety-four hits in nine documents, resolved on the device in 0.04s, with chapter 12 open at the third of its twenty-two hits.
What it carries now
0
Documents leaving the machine
100%
Usable without an account
None
Structure lost on reopen
2
Platforms shipped
Documents leaving the machine is structural: the app has no network path for a document to leave by, so the count is zero by construction. Usable without an account and structure lost on reopen are both capability claims. Two platforms is a count of signed, shipping builds.
Client name withheld under NDA. Figures are approximate, drawn from the engagement’s own reporting.
What the architecture settled
Local-first is a promise the interface has to keep visibly. A line in a privacy policy won't do it.
Local-first has to be visible in the interface: writers weren't reassured by a policy, they were reassured by there being no sync setting to find.
Owning your files shouldn't cost you formatting. A modeled document survives the round trip.
Owning your files doesn't have to cost you structure. A modeled document survives the round trip, and the plain-text tools had been an unnecessary trade.
Scoping an assistant to the selection is what makes 'we only send what you choose' a checkable claim.
Scoping to the selection turns a promise into something a writer can verify by looking at what they highlighted. That's why the boundary is the selection and not the document.
An app that is useless until you sign in has made the account the product.
The publisher's writers had specifically rejected two competing tools on this point, so a sign-in wall would have lost the audience before the editor was seen.
How the work was run
We shipped the shell and the editor before the assistant existed at all, because the local-first claim had to be demonstrably true before anything was allowed to send text anywhere. The assistant arrived in week ten, scoped to the selection from its first commit.
Phased so local persistence and the editor landed before the assistant, because the assistant's boundary only means something if the surrounding app has no network path of its own. The selection-scoped assistant was the contentious decision, and it was settled by asking what writers would accept over what would be most useful. The answers weren't the same.
One sentence, three scopes
What gets sent is what was highlighted. There is no wider setting.
One assistant request from chapter 14, scoped to the selection, the document and the library. Only the first exists in the app; the other two show what would have left the machine if it did. Switch tabs, or use the arrow keys once one is focused.
The writer highlights one sentence in chapter 14 and asks for a plainer version. The request holds that sentence and the instruction. Nothing around it goes.
Chapter 14 · The Ferry at Low Water
The letter had said Thursday, and so Maren came on Thursday, though the bus from Carrow let her off an hour after the last boat and the woman at the ticket window only shrugged and pointed down the hill toward the water.
She had expected the harbor to smell of diesel, but at low water it smelled of something older: weed and iron and the cold breath of the mud, as if the town had been lifted and the sea floor left behind. Gulls worked the shallows in pairs, unhurried, like clerks.
Tobias was already on the slipway, his hands in his coat, watching the ferry lean in its mooring as though it were listening for the tide. He did not turn when she called. He had never turned when she called; it was the one thing about him the years had left alone.
- Scope: the highlighted sentence
- Assemble the request
- Ready to send on your click
The request, in full
Send 41 words
Stays on this machine
- The rest of chapter 143,427 words
- The other 23 chapters47,071 words
- 7 notes, 5 research documentsall 12
- 9 versions of this chapteron disk
- Titles, file names and pathsnot sent
Why the boundary is the selection: writers accept help with a paragraph they chose to share. They won't accept a tool that reads the manuscript.
From a keystroke to the only request that leaves
Four of the five stages happen on the writer's machine and have no network path to leave by. The fifth is the assistant, and it can only carry what the writer highlighted and chose to send.
- 01 · InputKeystroke in the Tiptap editorHeadings, lists, quotes and emphasis are modeled as structure, not styled text.
- 02 · ModelStructured document, normalized on saveEditing state is normalized on every save, so invisible markup can't accumulate across sessions.
- 03 · Storageelectron-store on local diskPersisted as the writer types. The file is the source of truth, with no background sync behind it.
- 04 · On deviceLocal versions and searchVersions are kept on disk and search resolves on the device, in a renderer that doesn't assume a network.
- 05 · The one exitSelection-only assistant requestCarries the highlighted passage and nothing else, on an explicit send. Nothing is retained past the request.
What stays on the machine, and why
Unpublished work, protected by architecture instead of policy
No path for a document to leave by
The app has no network path for a document to leave through, so the count of documents leaving the machine is zero by construction. It isn't a setting, and there's no background sync to find and switch off.
The assistant gets the highlight, briefly
The assistant receives only the passage the writer highlighted, and only for the length of the request. The document and the library stay put, and nothing is retained afterward.
Signing out moves nothing
Guest and signed-in states are separate layouts, and an account adds capability without gating the app. Signing out leaves every local document exactly where it was.
Building a tool people will only trust if their work never leaves the machine? Scope your build in three minutes.
Scope your buildNearby engagements
AI & AutomationLong text becomes narrated audio, and the job tells you the truth while it runs
A production tool that pulls text out of a source, narrates it, and reports honestly on a job that takes minutes, without pretending to be instant.
Media & Publishing · 12 weeks
Web PlatformsTwo billing models in one product, and neither one pretending the other doesn't exist
A content platform sold both by subscription and as a lifetime deal, where a redeemed code and a monthly plan resolve to the same entitlement, with no parallel systems.
Media & Publishing · 18 weeks
Web PlatformsThree kinds of publication, two comment streams, and one queue that keeps them civil
A market-news publication with announcements, reporting and commentary as separate content types, member profiles, and a moderation queue that can hold a comment while a person decides.
Media & Publishing · 14 weeks
Let's talk
Running a large platform, shaping a first MVP, or getting a product ready for a funding round? Tell us where you are. We'll shape the process around it, and stay with you after launch.














