Skip to content

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.

Leafhold
The Salt YearPart 2 · The Crossing14 · The Ferry at Low Water
Saved to this disk · 3:21 PMNot signed in
Body text 3,468 words

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.

The ferryman said they would sail when there was water enough, and not a minute sooner. He said it kindly, the way one explains weather to a child, and went back to coiling rope that did not need coiling.

So they waited. Maren sat on an upturned crate with her suitcase between her knees and tried to remember the last time she and her brother had been silent together without it meaning something. Across the channel the lighthouse stood unlit, and the island behind it was only a darker gray against the gray.

“You came,” Tobias said at last, still not looking at her.

“You wrote.”

Session+662 wordsChapter3,468 / 3,500Manuscript50,539 words Saved as you typeNot signed in

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 problem

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.

Introduction

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

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

01

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.

What shipped
  • 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
Leafhold
The Salt Year14 · The Ferry at Low WaterVersions
Saved to this disk · 3:21 PMNot signed in
Comparev8 · 1:37 PMtov9 · 3:21 PM · current+72 words−9 wordsRestore v8

Chapter 14

The Ferry at Low Water
2 unchanged paragraphs

She had expected the harbor to smell of fueldiesel, but at low tidewater it smelled of something older: weed and iron and the cold breath of the mud, like a cellar opened after winter., 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.

The ferryman said they would sail when there was water enough, and not beforea minute sooner. He said it kindly, the way one explains weather to a child, and went back to coiling rope that did not need coiling.

9 unchanged paragraphs
Session+662 wordsChapter3,468 / 3,500Manuscript50,539 words Saved as you typeNot signed in
On screen

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.

Leafhold
The Salt YearNotesLighthouse keepers
Saved to this disk · 3:22 PMNot signed in
Heading 2
Lighthouse keepers

Everything I know about who kept the Carrow light, for chapters 3, 12 and 16. Check against the harbor records before the copyedit.

The Carrow light

  • •A keeper and one assistant, relieved by boat every second week
  • •Lamp lit at dusk and logged to the minute
  • •The stair: one hundred and nine steps (Tobias counts, ch. 12)

Lamp lit 7.42. Wind SW, moderate. Relief boat did not come; stores for four days.

Harbor records, 1911

For Maren

  1. 1.She does not climb the stair until chapter 22.
  2. 2.Her father’s lunch tin: keep it, it pays off.
Session+662 wordsChapter3,468 / 3,500Manuscript50,539 words Saved as you typeNot signed in
02

Real rich text

On screen

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.

What shipped
  • Structured document model, not styled text
  • Structure survives save, close and reopen intact
  • Normalized on save, so markup can't accumulate
03

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.

What shipped
  • Scope is the selection, never the document or the library
  • Nothing retained past the request
  • Enforced in the call, not promised in a policy
Leafhold
The Salt YearPart 2 · The Crossing14 · The Ferry at Low Water
Saved to this disk · 3:24 PMNot signed in
Body text 41 words selected

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.

The ferryman said they would sail when there was water enough, and not a minute sooner. He said it kindly, the way one explains weather to a child, and went back to coiling rope that did not need coiling.

Session+662 wordsChapter3,468 / 3,500Manuscript50,539 words Saved as you typeNot signed in
On screen

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.

Leafhold
Untitled manuscript
Saved to this disk · just nowNot signed inSign in
Heading 1

Chapter 1

Title

Start writing. Everything here is saved to this computer as you type, and nothing needs an account.

Session0 wordsManuscript1 chapter Saved as you typeNo account
On screen

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.

04

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.

What shipped
  • Separate layouts, no grayed-out features
  • An account adds capability and removes nothing
  • Signing out leaves every local document in place
05

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.

What shipped
  • 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
Leafhold
The Salt YearManuscript overview
Saved to this disk · 3:21 PMNot signed in
The Salt Year

24 chapters · 50,539 of 84,000 words · 36,161 still to write

Final 4Revising 4Drafted 5Writing 2Outline 9
#ChapterPartStatusWordsToward 3,500To writeEdited
1The Letter1 · The MainlandFinal4,112—Jul 02
2Carrow in RainFinal3,870—Jul 06
3What the Lamp Keeper KeptFinal4,305—Jul 11
4A House with No ClocksFinal3,642—Jul 15
5Tobias, Aged NineRevising2,988512Aug 04
6The Dry SummerRevising3,511—Aug 07
7Signal HillRevising4,027—Aug 12
8Leaving by the Early BusRevising3,206294Aug 14
9The Harbor Office2 · The CrossingDrafted3,354146Aug 18
10Rope and TarDrafted2,871629Aug 20
11A Map Drawn from MemoryDrafted3,190310Aug 22
12The Lamp RoomDrafted3,733—Aug 25
13Mother's LedgerDrafted3,058442Aug 27
14The Ferry at Low WaterWriting3,46832Today
15CrossingWriting1,2042,296Sep 11
16The Keeper's WifeOutline—3,500Aug 01
17Salt in Everything3 · The IslandOutline—3,500Aug 01
18The Relief BoatOutline—3,500Aug 01
19Fog SignalOutline—3,500Aug 01
20Two LampsOutline—3,500Aug 01
21The Census ManOutline—3,500Aug 01
22What the Tide ReturnedOutline—3,500Aug 01
23Low Water AgainOutline—3,500Aug 01
24The Last LightingOutline—3,500Aug 01
Manuscript50,53936,161
Session+662 wordsChapter3,468 / 3,500Manuscript50,539 words Saved as you typeNot signed in
On screen

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.

Process

Phase by phase

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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
Leafhold
The Salt YearSearch
Saved to this disk · 3:21 PMNot signed in
12 · The Lamp RoomHit 3 of 22Copy passageOpen chapter

Chapter 12

The Lamp Room

Their father had kept the lighthouse for eleven winters before Maren was old enough to be taken up, and by then she had built it so often in her head that the real one seemed a poor copy: narrower, colder, smelling of paraffin and wet wool.

The stair inside the lighthouse had one hundred and nine steps. Tobias counted them aloud on the way up and again on the way down, and when the numbers did not agree he sat on the landing and would not move until they did.

From the lamp room you could see the whole of Carrow laid out like something spilled: the harbor, the chapel, the long gray tongue of the slipway, and beyond it, faint as a thumbprint, the mainland lighthouse answering theirs.

“Every lighthouse has a temper,” their father said, wiping the brass. “This one is patient. It waits for the dark the way a dog waits at a door.”

Session+662 wordsChapter3,468 / 3,500Manuscript50,539 words Searched on this device
On screen

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.

36 documents on this disk24 chapters · 7 notes · 5 research
  1. Scope: the highlighted sentence
  2. Assemble the request
  3. Ready to send on your click

The request, in full

scopeselection
words41
characters203
text“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.”

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.

Architecture

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.

  1. 01 · Input
    Keystroke in the Tiptap editorHeadings, lists, quotes and emphasis are modeled as structure, not styled text.
  2. 02 · Model
    Structured document, normalized on saveEditing state is normalized on every save, so invisible markup can't accumulate across sessions.
  3. 03 · Storage
    electron-store on local diskPersisted as the writer types. The file is the source of truth, with no background sync behind it.
  4. 04 · On device
    Local versions and searchVersions are kept on disk and search resolves on the device, in a renderer that doesn't assume a network.
  5. 05 · The one exit
    Selection-only assistant requestCarries the highlighted passage and nothing else, on an explicit send. Nothing is retained past the request.
Stays on the machine Leaves only on an explicit send

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 build
Have a project?

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.