Product & UX Design · iteration 5 · 2026-07-02

ollwrite — the editor & the architecture.

Your writing, all right. Any model, pay once. The mission is explicit now: beat Grammarly and every AI text editor. Iteration 5 is the "it's a functional product now" update: the assemble-three-assets reframe is fully built — a shared 13-endpoint text-ops engine (now with streaming + brainstorm), humaniz + specview both migrated onto it, and ollwrite is a coherent, deployable product: Core magic-link auth, a rebranded landing → editor flow, the complete v1 op menu, a Groq/Claude model toggle, and its own standalone Dockerfile. Runs & builds locally; not yet deployed. See §00.

✅ 13-endpoint engine · two products migrated ollwrite = functional product · full op menu not deployed · needs write.oll.am + real-Core auth e2e
This is the design page. The spec is separate. The build-ready spec — one-liner, scope, resist-list, milestones, franc-first sequencing — lives at ollwrite — one writing engine (the spec) →. This page answers three different questions: what is the editor experience, what tech powers it, and what is the right repo/architecture — plus, new in iteration 3, what exactly do we assemble and which five features must be great. Read the spec for what and when; read this for how it feels and how it's shaped. Order of record stays The Backlog.

ollwrite = "Grammarly × autocomplete × inline editing of an idea" — honest, pay-once, any-model — and it's already 70% built across three repos.

✦ Iteration 5 — the reframe is now a FUNCTIONAL PRODUCT

Iteration 3 landed the reframe: ollwrite assembles three assets Sam already owns — the live humaniz React shell, two in-repo React + Plate.js editor prototypes (specdocv2, the "other specview frontend" Sam half-remembered), and the shared write-service — on one shared text-ops engine; iteration 4 proved it in code. Iteration 5 (this update) makes ollwrite a coherent product: the shared engine is now a 13-endpoint write-service (streaming + brainstorm added — specview's last local op is gone, so both products are fully migrated), ollwrite carries the complete v1 op menu (one calm ✨ dropdown), and it is deployable — Core magic-link auth (login → oll_token cookie → middleware-gated editor, the real JWT forwarded to write-service), a rebranded landing → editor flow, a Groq/Claude model toggle, and a standalone Next.js Dockerfile + Coolify README. npm run build succeeds, boots, Playwright-verified. NOT deployed. The whole design series stands — this is the "it's a functional product now" checkpoint. Start at §00 · Built; the reframe rationale is still §02.

00Built — ollwrite is a functional product (2026-07-02)

Updated in iteration 5. Everything below iterations 1–3 designed on paper; iteration 4 proved the shared-engine PoC; tonight (waves 4–5) ollwrite crossed from PoC to a coherent, deployable product, dev-tested against real Groq. The "one text-ops engine every product calls" story in §01 is now fully true — 13 endpoints, both products migrated, no local ops left.

✅ FULLY MIGRATED — both products run on ONE 13-endpoint engine, no backend per product

write-service is now a 13-endpoint text-ops engine on stage — the original verbs (PR #65 + PR #66, merged): improve · clarify · spec · draft · rewrite · expand · compress · simplify · tldr · bullets (+ health), plus tonight's two closers (PR #67 → stage): POST /rewrite/stream (SSE — chunked today because the oll-model gateway is non-streaming, forward-compatible to real token streaming) and POST /brainstorm (specview's last local op). Core-JWT gated, calls the frozen oll-model gateway (Groq default), honest provider/model attribution, 119 tests with real Groq SSE frames verified. humaniz.me runs on it (PR #17, needs-review): its own prompt/model code deleted, rewrite route a thin passthrough — proven e2e, ZERO direct model calls. specview runs on it too (PR #129, needs-review): now that brainstorm exists, its last local op is gone — specview can fully retire its backend. ⇒ the strangler-fig convergence of §04 is complete — two products, one shared engine, no auth/model/prompt code per product.

Real now — dev-tested tonight

write-service — 13-endpoint engine — the ten verbs + health, plus rewrite/stream (SSE) and brainstorm. Core-JWT gated → frozen oll-model (Groq), honest attribution, 119 tests, real Groq SSE frames verified. PR #65 + #66 + #67 → stage

humaniz on write-service — its prompt/model code deleted; rewrite route a thin passthrough. Proven e2e; ZERO direct model calls. PR #17 · needs-review · NOT deployed

specview fully on write-service — all verbs migrated (brainstorm was the last); local skill files deleted; specview's own backend can retire. 889 tests. PR #129 · needs-review · NOT deployed

ollwrite is a coherent, deployable PRODUCT — Core magic-link auth (login → verify → oll_token cookie → middleware-gated /editor, the real user JWT forwarded to write-service so ops are Core-gated), a rebranded landing (/) → editor flow ("Your writing, all right. Any model, pay once."), the complete v1 op menu (§05), a Groq(fast)/Claude(quality) model toggle, and a standalone Next.js Dockerfile + Coolify self-host README. npm run build (standalone) succeeds, boots, Playwright-verified (landing hero, CTA→editor, model toggle, login form, middleware 307 gate). standalone at ~/Projects/ollwrite

Still design / not yet real

Nothing is deployed. write-service isn't on write.oll.am; the humaniz + specview PRs are needs-review (Sam's call); ollwrite builds & boots locally but is not on a domain.

Real Core magic-link e2e not yet exercised. ollwrite's auth is fully wired but the live round-trip (Core sends the email → user clicks → verify) needs a live Core + inbox to prove.

ollwrite has no remote repo yet. It's a standalone local project; giving it its own repo (+ CI) precedes its first deploy.

The model toggle isn't plan-gated. Groq/Claude switches freely — billing/plan-gating the premium (Claude) tier is still to wire once ollwrite is chargeable.

Streaming is chunked, not token-level. /rewrite/stream emits SSE but in chunks (the oll-model gateway is non-streaming); real token streaming is forward-compatible, not yet live.

The flagship, real — per-paragraph "Edit this idea"

Hover a paragraph → ✨ → type an instruction → an inline word-level diff (red deletions / green insertions) → Accept (⌘↵) / Reject / Retry. Browser-verified against real Groq: "the servise was quick and the team they was very helpfull""The service was quick, and the team was very helpful…" (groq · llama-3.3-70b). This is feature 1 of §05 and interaction 3 of §06 — the one that was "already prototyped in specdocv2" — now running end-to-end on the shared engine.

The v1 text-operations set — now a wired menu, not a plan

The complete v1 menu is built into ollwrite — one calm ✨ dropdown, grouped Edit / Length / Transform, each op returning a preview or an inline word-diff → Accept / Reject / Retry, verified e2e against real Groq. The always-on diagnostics and ghost-text remain the honest v1.1 deferrals.

GroupOperations (in the ✨ menu)Status
EditImprove · Rewrite… (instruction) · Fix grammar · Change tone ▸✓ wired in ollwrite
LengthShorten (compress) · Expand✓ wired
TransformBullets · Simplify · TL;DR✓ wired
The killer flowPer-paragraph instruction + inline word-level diff (Accept/Reject/Retry)✓ BUILT — flagship
Model routingGroq (fast) default · Claude (quality) toggle (via the frozen oll-model gateway)✓ toggle wired · plan-gate to come
Generative (braindump)Draft-from-braindump · Spec-from-braindump · Brainstorm✓ backed by write-service
Always-on checksHemingway / Lex-style diagnostics (readability, passive, adverbs) · Continue-writing ghost-textdeferred → v1.1

Every menu op resolves to a write-service verb (Improve→improve, Shorten→compress, TL;DR→tldr, …); the killer flow composes rewrite with an inline diff on the client; the model toggle picks the oll-model tier. The engine is one; the menu is now the shipped product surface.

01Ground truth — the honest state today

Design work is only useful on top of an accurate picture. Here is exactly what is and isn't real right now — updated after the repo scan.

What exists — more than we thought

The shared text-ops backend — write-service (services/write) — exists with clarify / spec / draft prompt-modes, calls Core (auth · billing · quota) + Model over HTTP, stateless, 54 pytest green on a feat branch.

humaniz.me is live in production — Next.js 16 + React 19 + shadcn/ui + Tailwind, Core magic-link auth (oll_token cookie + middleware), Stripe billing, a two-pane streaming editor, refine chips, model picker. Docker + nginx on Coolify (not Vercel-locked).

Two React + Plate.js editor prototypes already sit in the repo at /Users/sam/Projects/2026/specdocv2 and specdocv2-plate-demo — Next 16 + React 19 + Plate.js 52 + @platejs/ai 52 + ai-sdk 6, with an AI toolbar, AI-preview popover, slash commands, floating/fixed toolbars, custom spec-block plugins, a use-claude-text Claude wiring, markdown import/export, and a /api/ai/text route. This is an ollwrite editor prototype.

What is NOT real yet — updated in iteration 5; the engine story is now true, see §00

Now true (was the #1 gap here): the "one text-ops engine all products call" story — write-service is a 13-endpoint engine and both humaniz and specview are fully migrated onto it (dev-tested, PR'd). See §00. What remains ↓

Not deployed. write-service isn't on write.oll.am yet; the humaniz + specview migration PRs are needs-review, not merged/deployed.

ollwrite is a functional product but not yet shipped — the standalone ~/Projects/ollwrite now has Core auth + landing + the full op menu + model toggle + a Dockerfile (builds & boots locally), but it has no remote repo, no deploy, and its real-Core magic-link e2e is unexercised — not the live hero product yet.

⚠️ Ship-vs-build — this is design, not a build order

humaniz.me's live money path is still P0 — the first stranger franc isn't closed. ollwrite is the post-first-franc god-product. Everything here is design: cheap, reversible, on paper — so it's ready when the franc lands. It is explicitly not a green-light to build before that dollar. The Backlog stays the order of record.

02The reframe — ollwrite assembles three assets you already have

The headline of iteration 3, and the thing that de-risks the whole build. The goal is to beat Grammarly — but the path there is reuse-not-rebuild, not a greenfield editor. Everything ollwrite needs already exists, in three places, in the same React lineage.

Asset 1 · the shell

humaniz.me — live frontend

Next.js 16 · React 19 · shadcn/ui · Tailwind. Core magic-link auth (oll_token cookie + middleware), Stripe billing, two-pane streaming editor, refine chips, model picker. Production-proven.

→ the app shell, auth, billing, deploy

Asset 2 · the editor

specdocv2 — Plate prototype

Two React + Plate.js 52 + @platejs/ai 52 + ai-sdk 6 prototypes: AI toolbar, AI-preview popover, slash commands, floating/fixed toolbars, custom spec-block plugins, a use-claude-text wiring, md import/export, /api/ai/text.

→ the rich AI editor surface

Asset 3 · the backend

write-service — shared engine

The platform's text-ops service — clarify / spec / draft prompt-modes, calls Core + Model, stateless, tested. humaniz + specview converge onto it (see the Backlog migration).

→ prompts, model routing, quota

The build, in one line

Graft the specdocv2 Plate editor into the humaniz app shell, point it at write-service, add the five winning features.

That's it. No greenfield editor, no new auth/billing, no new backend. Each of the three interactions ollwrite needs is already prototyped in specdocv2; the shell that wraps them is already live in humaniz; the prompts and model routing are already in write-service. Iteration 2 correctly called React — iteration 3 shows the reason is far stronger than "the ecosystem is React-first": Sam's own three repos already are ollwrite, unassembled.

Why this matters against the ship-vs-build pattern

The recurring failure is a net-new build that stalls at 85%. "Assemble three finished things" is the opposite of a greenfield: the risky parts (a working Plate+AI editor, live auth+billing, a tested prompt backend) are already past 85%. The remaining work is integration + the five features — bounded and additive — not invention.

03specview frontend evolution — how we got two editor lines

Sam asked to be clear about the iterations, because the specdocv2 prototype was "the other specview frontend I half-remember." Here is the real lineage — two parallel lines, and why the React+Plate one is where the editor future already lives.

IterationWhat it wasLesson it banked
vanilla JS web/
deleted May 2026
The first frontend — plain JS, no framework. Too bare to carry a rich editor. Needs real structure — a framework, typed state, a component model.
Angular 19 web-ng
the LIVE specview app
Signals (RxJS → signals for cleaner state), ng-openapi-gen typed client, magic-link auth, LCS paragraph diff, read-only marked + DOMPurify render, whole-file replace. Passwordless magic-link won · API-first (spec→code) prevents drift · LCS paragraph diff is the right granularity to visualize AI output.
React + Plate line
specdocv2 · specdocv2-plate-demo
In parallel, explored the rich-editor future: Plate.js 52 + @platejs/ai, AI toolbar/popover, slash commands, custom spec-block plugins, Claude wiring, md import/export. The React + Plate prototype is where the editor future already lives — WYSIWYG, block-level, AI-native.

The arc: vanilla → needs structure · RxJS → signals for cleaner state · passwordless magic-link won · API-first prevents drift · LCS paragraph diff is the right diff granularity · and the React+Plate prototype is the editor future. ollwrite doesn't discard this — it keeps the philosophy (meaning-preserving edits, diff-before-accept) and graduates the surface from read-only markdown into the live Plate editor.

04Feature convergence map — three products → three modes

ollwrite isn't net-new surface area. It's a convergence: each existing product's core loop becomes a mode of one calm editor.

Product todayWhat it does nowBecomes
humaniz.me
Next.js · LIVE Stripe (prod)
Two-pane editor · streaming rewrite · Light/Medium/Heavy strength · refine chips (Shorter · Formal · Warmer · Casual · Impactful) · 3-pass heavy mode · free cap · 5/day Clarify mode
specview
Angular 19 · signals
Braindump → AI-generated structured spec · 8 text-ops (expand · compress · clarify · simplify · tl;dr · bullets · brainstorm · rewrite) · markdown render (read-only) · paragraph LCS diff · git-backed history · share links · async job polling Spec mode + the text-ops menu
write-service
services/write · exists
The draft prompt-mode (braindump → polished prose) Draft mode

Clarify

Rewrite messy text for clarity & flow, with strength + refine chips.

← humaniz.me

Spec

Braindump → structured spec, plus the 8-op text menu.

← specview

Draft

Braindump → polished prose in a chosen tone.

← write-service

End state: ollwrite modes = Clarify · Spec · Draft (+ tone toggles). humaniz.me and specview gradually retire → redirect to write.oll.am. Two brands / split SEO → one.

05The five must-be-great features — the beat-Grammarly thesis

Every incumbent is a loud, cloud-only, subscription tool that only polishes. ollwrite is the honest inverse. Five features must be genuinely great — ranked by differentiation × buildability (buildability is high across the board because §02: it's already prototyped).

1

Cursor-style per-paragraph edit with a real diff

diff HIGH · build HIGH

Select a block → give an instruction → a red/green inline diff appears → accept/reject per hunk or per word, keyboard-first, the original visible until you accept. This is the wedge no prose tool owns: Cursor nails it for code only, and writers already hack Cursor to write prose. Plate ships the suggestion + comment diff utilities and rejectAISuggestions to build exactly this — and specdocv2 already prototypes the AI-preview popover.

Evolution of specview: specview does a whole-file replace + LCS diff after. ollwrite tightens the granularity to per-paragraph, in-place, propose-not-apply with inline word-level decorations.

2

Quiet-by-default suggestions (anti-nag)

diff HIGH · build MED

Only surface a suggestion when estimated accept-probability is ≥ ~25%. This is Cursor's Tab-RL principle: a wrong suggestion is worse than none — their model cut suggestions ~21% while lifting acceptance ~28%. Add category toggles; never re-surface a dismissed suggestion; and — the honesty line — NEVER paywall a suggestion you've already shown.

This is Grammarly's #1 complaint — nagging plus weak, paywalled suggestions. Winning here is a UX + trust move, not a model move.

3

Any-model / BYO-key / local (Ollama) routing

diff HIGH · build MED

Route through the oll-model gateway: a premium hosted model, the user's own API key, or local Ollama. This uniquely defuses the pay-once cost bomb — if the user brings their key or runs local, there's no per-token bleed, so "pay once" is honest and financially safe. Simultaneously it's the privacy story (text can stay on the user's machine).

No incumbent can copy this — their business model IS the per-seat subscription and the cloud. This is structurally ours.

4

Minimal-edit, voice-preserving prompt engine

diff HIGH · build MED

The engine returns structured edits{span, replacement, reason} via constrained decoding — not a rewritten blob. Edits keep ~74–98% of tokens verbatim (copy-biased); the expensive error is a false correction. This is what makes quality beat Grammarly even on a cheap, fast model, and it's what powers the diff UI in F1.

Evidence: LLMs already outperform Grammarly on grammar (2026 Springer GEC study); Grammarly's own CoEdIT proved instruction-tuned minimal-edit discipline beats raw model size. We copy the discipline, not the subscription.

5

Spec ⟷ clarity two-mode engine

diff MED · build HIGH

Generate structure (specview's Spec mode) ⟷ refine prose (humaniz's Clarify mode) in one calm editor. No incumbent unifies both — Grammarly is polish-only, spec tools don't refine. This is the specview + humaniz convergence made into the product's core, and it's the most buildable of the five because both halves already run in production.

The thesis in one sentence

Grammarly polishes, loudly, in the cloud, for a subscription. ollwrite edits with a real diff you control, quietly, on any model (including local), for pay-once — and it keeps your voice because the engine is minimal-edit by construction. Same job, honest inverse of every incumbent constraint.

06The editor experience — three interactions, the feel

The five features above are the strategy; these three interactions are the feel — a living surface, not a text box with a "rewrite" button. Each is grounded in a market precedent and its known failure mode, and each is already prototyped in specdocv2.

1

Clarify suggestions

precedent · Grammarly · feature 2

Color-coded underlines rendered as editor decorations layered over the text — never mutating the document. Hover or click → a floating card shows the fix inline (strike old → new), with Accept · Dismiss and a one-line why.

clarify · draft.md
The report was written by the team in order to summarize findings that are of an important nature for the launch.
Conciseness · high confidence
in order to  →  to
Cut filler — "in order to" almost always shortens to "to".

Quiet-by-default is make-or-break (feature 2). Category toggles, a high-confidence-only density setting, never re-surface a dismissed suggestion, and — the honest-tool line — never show a suggestion you then paywall.

2

Ghost-text autocomplete

precedent · Copilot · Lex

A dimmed inline continuation at the cursor; Tab to accept. Copilot's pattern, tuned for prose — the timing rules are everything (see the AI bar, §10).

draft · intro.md
We built ollwrite because writing tools each solve one slice of the job, and switching between them breaks the train of thought.Tab

Critical for prose: trigger on a typing pause at sentence / word boundaries — never per-keystroke, never mid-word. Tab accepts, Esc dismisses, Cmd/Ctrl+→ accepts word-by-word. Offer Snooze + per-document off. Plate's CopilotPlugin is this, already debounced and word-by-word.

3

Inline edit-an-idea

precedent · Cursor Cmd-K · feature 1

Per-paragraph AI editing. Hover a paragraph's gutter handle or select text → Cmd-K opens an instruction box → the rewrite appears as an inline word-level diff. The original stays visible until you Accept.

edit · paragraph
⋮⋮Selected paragraph
Cmd-K
We think this approach could maybe help reduce some of the approach removes the confusion users have been running intohit.
ShorterMore formalTry again

Never auto-apply. Cursor's silent-apply is its single most-hated regression — the AI must propose, never overwrite. Per-hunk / per-word accept; refine chips follow. Add a "show AI-authored spans" toggle — the honest-tool transparency move. Plate's suggestion + rejectAISuggestions utilities give this off-the-shelf.

These three interactions are the product's soul. The modes are the menu; this is the feel — and all three already run in the specdocv2 prototype.

07Editor tech & the document model — Plate.js on Slate, JSON-canonical

Iteration 3 corrects an error carried since iteration 1 and settles the storage question that iteration 2 left open.

⚠️ Correction — Plate is Slate-based, NOT ProseMirror

Iterations 1–2 called the engine "ProseMirror, consumed through Plate." That is wrong. Plate.js is built on Slate (a React-native document framework with a JSON node tree). Tiptap and BlockNote are the ProseMirror family. The recommendation is unchanged — Plate.js — but for the right reason: Slate gives a plain-JSON, block-addressable node tree that maps cleanly onto per-paragraph AI ops, and Plate ships the AI plugins (ghost-text, AI menu, suggestion/comment diffs) MIT-licensed on top of it. We just stop mis-describing the lineage.

Document model — decided

Plate's Slate JSON node tree is CANONICAL. Markdown and HTML are EXPORT-only projections.

Each block carries a stable ID, so every paragraph is independently selectable · AI-rewritable · regenerable · reorderable · commentable. Plate preserves block IDs through markdown as <block id="…">, so "rewrite the 3rd paragraph" maps to a real node, not a fuzzy text offset.

The critical rule — persist the JSON, never round-trip through markdown

Markdown round-trips are lossy: they silently drop callouts, comments, and suggestions, and they reformat whole documents — which breaks trust (the user sees edits they never asked for). So: persist the Slate JSON; emit markdown only on "Export / Copy as Markdown"; emit HTML only on "Copy to Google Docs / email". DOMPurify guards ONLY those two export seams + paste-in — not every render (specview's read-only marked+DOMPurify pattern moves to the export boundary, not the editing loop).

Evolution of specview — keep the philosophy, change the mechanism

Dimensionspecview today (keep the intent)ollwrite (change the mechanism)
PhilosophyKEEP → meaning-preserving edits · diff-before-accept · the writer stays in control.
StorageRead-only markdown, rendered with marked + DOMPurify.Slate JSON persisted; md/HTML export-only.
Edit unitWhole-file replace.Per-block ops keyed on stable IDs.
Diff renderingParagraph-level LCS diff shown after.Inline word-level suggestion decorations, propose-not-apply.
SurfaceRead-only rendered view.Live WYSIWYG Plate editor.

Why Plate over the alternatives

OptionFamilyVerdict
Plate.jsSlateRecommended — JSON node tree + block IDs + MIT AI plugins (ghost-text, AI menu, suggestion/comment diffs). Already prototyped in specdocv2. shadcn-native.
TiptapProseMirrorFine engine, but its Content AI / AI Toolkit is a paid Cloud add-on → avoid for a proprietary pay-once product.
BlockNoteProseMirrorNice block UX, but its xl-ai package is GPL-3.0 → avoid (copyleft).
LexicalownFast, but no first-class suggestion/decoration + AI plugin layer → you rebuild the hard parts.
CodeMirror / MonacosourceCode editors — wrong surface for rich prose.

Model streaming to our OWN backend

The editor streams via the Vercel AI SDK (provider-agnostic) pointed at our self-hosted oll-model — via @ai-sdk/openai-compatible or an SSE data-stream against write-service. No vendor cloud, ever, keeping the promise intact: any model, pay once. (Honest caveat: the React AI ecosystem churns — AI-SDK made a 4→5 bump, Plate renamed @udecode/plateplatejs; specdocv2 already runs Plate 52 / ai-sdk 6, so we pin those exact versions.)

08Framework & architecture — React, standalone, assembled

Iteration 2 reversed the framework call to React; iteration 3 makes it inevitable — you don't reverse into React, you assemble into it, because all three assets already are React. The topology is otherwise unchanged.

Recommendation (settled)

ollwrite = a standalone, frontend-only React repo — grown from the live humaniz Next.js shell with the specdocv2 Plate editor grafted in. It owns no backend.

A pure HTTP client of the platform: shared write-service → frozen oll-core → frozen oll-model. Standalone because it's the hero brand with its own domain (write.oll.am), its own deploy cadence, and a desktop-class writing editor distinct from bubls's mobile shell — buying clean brand + SEO and independent sellability (the modular exit). Next.js is settled (humaniz already is Next.js, and its thin server layer proxies oll-model + keeps the Core JWT off the client) — the iteration-2 "Vite vs Next" question is closed by continuity. Self-hosted on Coolify (Docker + nginx, no Vercel lock-in).

The backend is the EXISTING shared write-service — not in ollwrite's repo

services/write stays in the platform monorepo as shared, frozen infra — all product prompts as versioned, named module-level constants, in one place. ollwrite is its primary consumer; humaniz + specview migrate to call it during the transition, then retire. The frontend never holds a prompt; it names a mode.

The topology

the client — standalone React, assembled from three assets
ollwrite
standalone React (Next.js) · humaniz shell + specdocv2 Plate editor + Vercel AI SDK · one editor, Clarify · Spec · Draft + the three interactions · self-hosted on Coolify · write.oll.am
humaniz.me
asset 1 · the shell
Next.js 16 · React 19 · LIVE · auth + billing + streaming UX carry forward verbatim, then redirects
specdocv2
asset 2 · the editor
Plate.js 52 + @platejs/ai · AI toolbar/popover, slash, spec-block plugins — grafted in
specview
UX reference only
Angular 19 · patterns to reimplement (diff-viz · history · share) · then redirects
▼   over HTTP   ▼
the platform — shared, in the monorepo
write-service
asset 3 · text-ops & prompts · all product prompts as named constants · stateless · services/write
Core
frozen · live
auth · billing · email · magic-link JWT · Stripe
oll-model
frozen
any model · Groq default · BYO-key · local Ollama · no SDK in products
write.oll.am — ollwrite (React, assembled) oll.am — platform core.oll.am — frozen model.oll.am — frozen

Why not a bubls module

bubls is the mobile super-app shell (Angular / Ionic / Capacitor) and has been ~4 months stale. ollwrite's core is a web-first rich-text editor — a different device story, interaction model, deploy cadence, and framework. Keep it standalone and focused; it can appear inside bubls later via an embed or a link if that ever earns its keep.

09The UX + AI bar — the numbers we must hit

Great feel is measurable. These are the thresholds ollwrite's editor is held to, drawn from published latency research and shipping AI editors.

ConcernTargetReference
Ghost-text latency≤ 200 ms target · ~400 ms ceiling (Doherty threshold) · < 100 ms feels instantCopilot 110–140 ms · Cursor Tab 150–260 ms · Gmail Smart Compose p90 60 ms
Anything non-instantStream it — perceived ~40% faster; TTFT < 0.5 s reads as "instant"Nielsen response-time limits · streaming UX studies
Ghost-text triggerOn a typing PAUSE at sentence/word boundaries — never per-keystroke, never mid-wordCopilot / Lex prose tuning
KeysTab accept · Esc dismiss · Cmd/Ctrl+→ accept word-by-wordPlate CopilotPlugin

3-tier model routing on oll-model

Fast inline

Groq Llama-3.3-70B — ~276 t/s, sub-300 ms TTFT, cheap. Drives ghost-text + quick suggestions.

tier 1 · default

Premium rewrite

Claude — full-doc, voice-preserving rewrite. The slower "deep edit" multi-pass.

tier 2 · quality

Private / offline

Ollama — on-device, text never leaves the machine. The privacy + longevity tier.

tier 3 · local

Keep inline single-pass (fast tier) for the always-on feel; offer an explicit, slower "deep edit" multi-pass (premium tier) for a full-document voice-preserving rewrite. The tier is a routing decision in oll-model, invisible to the editor code.

10Niche & go-to-market — win a wedge, not the market

Honest framing: you cannot out-distribute a 30M-user, ~$700M-ARR Grammarly. You beat it on a niche where its constraints (cloud-only, subscription, polish-only) hurt most.

Primary wedge

The non-native English professional in privacy-constrained EU / DACH.

Four pressures stack on the same person: English writing is their weakest skill (and carries a 12–29% DACH wage premium); 61% of Western-EU CIOs are deprioritizing US cloud; GDPR; and subscription fatigue. ollwrite's pay-once + any-model/local + private-by-default answers all four at once — and DACH is Sam's home turf.

Secondary wedges

Honest students — "improve YOUR writing, not write it for you," which matches institutional integrity lines. · Spec-writing devs — oll.am's own build-in-public audience, native to Spec mode.

⚠️ Ethics & positioning — locked

Honest writing tool ONLY — never a detector / Turnitin-bypass. Never claim "Swiss-hosted" (the VPS is Frankfurt) or name a location. The true pillars are: pay-once · any-model / open-weight · private-by-default. Message longevity — BYO-key / local means "works even if we vanish" — to counter the lifetime-deal-abandonment fear that dogs pay-once tools.

11Build path — assemble, franc-gated

The order, reconciled with the Backlog and the spec's milestones (not duplicated). Everything from step 1 on is gated behind the first stranger franc — humaniz's live money path stays P0.

  1. NOW — research & design this page — iterations 1–3 land here: the editor feel, the five features, the doc model, and the assemble-three-assets reframe. Pure paper. No code.
  2. Converge the backend onto write-service after franc + go — Phase A: write-service gains /rewrite + SSE streaming + the 3-pass prompts; point humaniz at it; dev-test e2e; retire humaniz's own text-ops. Then specview follows.
  3. Assemble the ollwrite frontend after franc — take the humaniz shell, graft the specdocv2 Plate editor, point it at write-service. Clarify mode first, chargeable via the existing Core Stripe.
  4. Ship the five features after franc — per-paragraph diff edit · quiet suggestions · any-model/BYO/local routing · minimal-edit engine · Spec⟷Clarify.
  5. Deploy write.oll.am + redirect explicit go only — deploy write-service, run the local frontend against the remote, develop ollwrite against the stage dependency; then point humaniz.me / specview.devwrite.oll.am and retire. Outward & irreversible → only on Sam's explicit go.

⚠️ The gate is real

Steps 1+ do not start until the first stranger franc lands (close humaniz's live money path) and Sam gives the go. Until then this page — plus the spec — is the whole deliverable.

Status: design iteration 5, captured 2026-07-02 — ollwrite is a functional product (§00): a shared 13-endpoint write-service engine (streaming + brainstorm), humaniz + specview both fully migrated onto it (dev-tested, PR'd, needs-review), and ollwrite is now coherent & deployable — Core magic-link auth, a rebranded landing → editor flow, the complete v1 op menu, a Groq/Claude model toggle, and a standalone Dockerfile (npm run build green, Playwright-verified). The design still stands — the reframe (assemble three assets), the Slate/Plate correction, the JSON-canonical doc model, the beat-Grammarly-on-DACH thesis and the five features. What's left is deployment (write.oll.am + ollwrite's own repo/deploy), real-Core magic-link e2e, and plan-gating the model toggle. The spec is here; the order of record stays The Backlog.