Darryl Schaefer
← All projects

Case study

AI text editor

Inline AI assists while keeping the author in control.

2024Frontend + integrations
ReactTypeScriptLexical JSOpenAI API

I built a local-first editor for project-aware, reviewable AI assistance in long-form writing. Writers can select text, invoke reusable macros that retrieve relevant project context and chain specialized model calls, then inspect the proposed replacement as a diff before deciding whether it enters the document. The editor also provides document management, semantic search, and tools for navigating nearby prose, character profiles, and other project material.

A macro running end to end

Shorthand selected, the workflow fires, nine davinci-002 candidates stream past, and the renderer's draft arrives as a reviewable diff. Trimmed from 74 seconds of real runtime.

The Problem

Long-form writing distributes context across chapters, notes, character profiles, scenes, and accumulated continuity decisions. General chat interfaces can rewrite an isolated passage, but they do not naturally provide durable project context, repeatable editorial procedures, or precise control over what enters the manuscript.

I designed the editor so models operate as bounded tools inside the writing process rather than autonomous authors. A macro can retrieve facts, perform editorial checks, generate alternatives, or transform selected text, while the application keeps every proposed change local, visible, and reviewable.

Release Experiment

To test the editor as a standalone product, I packaged it for a Product Hunt launch and integrated Lemon Squeezy checkout with key-based access.

The launch produced no sales or meaningful feedback. I removed the commercial gate and released the editor publicly rather than treating the launch as evidence of demand.

The experiment did not validate the market, but it took the application through packaging, access control, and public distribution beyond local development.

Case Study: Preserving Continuity Without Flattening the Scene

The selected shorthand asks Mercer to build a fire, eat, and sleep. The existing next paragraph says a gust kills the flame before the fire catches.

A direct chat-model rewrite can avoid the contradiction by turning the requested events into outcomes Mercer anticipates rather than events that happen. The macro instead keeps the action physical and incomplete, preserving the existing next paragraph.

Direct model vs. macro

Both receive the same shorthand and surrounding document context. One goes directly through the chat model; the other runs through the macro.

Author's shorthand

He made a strong fire, warmed his hands, ate the last of the meat, and slept until morning.

Direct model

gpt-5.6-sol

He bent close, cupping the little flame, and saw in it a fire high enough to warm his hands, the last strip of meat softening over the coals, and sleep that would carry him safely into morning.

Avoids the contradiction, but replaces physical progression with a single sentence of anticipated outcomes and retains the four requested beats as a list.

Through the macro

davinci-002 → gpt-5.6-sol

He bent low over the match, making a wall of his shoulders and cupped hands. The heat was too slight to feel, but the sulphur bit his nostrils. He pressed the flame beneath the finest curl. His stiff fingers would not hold steady; match and bark touched, parted, and touched again. The bark's brown edge curled and smoked, and he bent closer, nursing the little flame against it.

Keeps the action physical and unresolved. It removes the incompatible outcomes and leaves the following paragraph free to extinguish the flame.

How a macro runs

Macros can be layered: one macro can call others, creating a workflow in which each stage has one constrained job. This example separates planning, candidate generation, drafting, and validation.

That separation keeps later judgment calls from flattening the prose. Completion models generate stylistic options, chat models plan and validate, and application checks prevent the validator from changing the chosen draft.

A four-stage macro

Each stage has one job: set constraints, generate options, compose a draft, or validate the result.

  1. 01

    Plan the bridge

    plannerchat model

    Reads the text around the selection and defines what may and may not happen in the replacement.

  2. 02

    Generate candidates

    generatorcompletion model

    Produces parallel style-matched options from demonstrated London prose without seeing the surrounding document.

    • Candidate Atemp 0.72
    • Candidate Btemp 0.72
    • Candidate Ctemp 0.72
    • Candidate Dtemp 0.78
    • Candidate Etemp 0.78
    • Candidate Ftemp 0.78
    • Candidate Gtemp 0.83
    • Candidate Htemp 0.83
    • Candidate Itemp 0.83
  3. 03

    Compose the draft

    rendererchat model

    Combines candidate material into one draft while staying inside the planner's continuity constraints.

  4. 04

    Validate the seam

    validatorchat model

    Checks the draft against the surrounding text and either approves or rejects it. It cannot rewrite the prose.