Build HyperWrite

YESback to the verdict

0%0 of 16 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

A local drafting workspace whose hard problems are chunking sources so a retrieved passage is actually a unit of support, verifying every generated sentence against the passage it cites instead of trusting the model's own citation, and keeping that verification correct as drafts are rewritten and sources removed.

estimated effort weekendthe files for this build are in the project pack

RuntimeNext.js 15 and TypeScript, local, with the model key server sideStorageSQLite through Drizzle, with source text kept as files beside itRetrievalParagraph-aligned chunks with character offsets into the originalGenerationOne provider behind one adapter, structured output, passages numbered in the promptVerificationA separate pass checking each sentence against the passage it cited

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. installfree

    Why Runs the application and its test suite.

    Get it nodejs.org, or your version manager. open ↗

    Verify node --version prints v22 or higher

  2. API keypay per token; measure a real section before choosing the ceiling

    Why Generation and the separate verification pass both go through it, and the verification pass roughly doubles the call count per draft.

    Get it Create a key with your chosen provider and set a spend limit in their console as well as the ceiling in this app.

    Verify A section drafts and every sentence receives a support state

  3. have readyfree

    Why Chunking and verification both behave differently on a research paper, a transcript and a marketing page, and testing on one of them teaches you nothing about the others.

    Get it Assemble the documents for something you actually need to write, including at least one long and one badly formatted file.

    Verify All of them import, chunk and show passages in context

  4. decidefree

    Why A flagging rule written after the draft exists is written around the draft, which is the opposite of useful.

    Get it Write down the claims this document must never make, in the wording the flagger will match on.

    Verify The list is stored on the project and appears in every generation prompt

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- projects(id, title, audience, objective, tone, prohibited_claims_json, created_at)
- sources(id, project_id, kind, title, origin, added_at, sha256, text_path) · kind is pasted, uploaded or fetched once
- passages(id, source_id, ordinal, text, char_start, char_end) · the only unit anything is ever allowed to cite
- outlines(id, project_id, version, approved_at) and sections(id, outline_id, ordinal, heading, brief)
- drafts(id, section_id, version, created_at, model_id, prompt_version, cost_minor) · a rewrite is a new version, never an edit
- sentences(id, draft_id, ordinal, text, support_state) · support_state is supported, weak or unsupported
- citations(sentence_id, passage_id, verifier_score, verified_at) · a row exists only after the id resolved and the check ran
- The model's own numbering never becomes a citation row without passing through resolution and verification first.

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
MODEL_API_KEYsecretrequiredsk-...redactedGeneration and verification. Give it a provider-side spend limit too.
MODEL_IDrequireda text model identifierStored with every draft, because a different model cites differently.
VERIFIER_MODEL_IDrequireda smaller text model identifierThe support check. A cheaper model is usually enough for this one job.
DATABASE_PATHrequired./data/workspace.dbProjects, passages, drafts, sentences and citations.
SOURCE_TEXT_DIRrequired./data/sourcesFull original text per source, so a passage can be shown in context.
CHUNK_OVERLAP_CHARSrequired200Overlap between paragraph-aligned chunks. Changing it re-chunks new sources only.
SUPPORT_THRESHOLDrequired0.7Verifier score below which a sentence is weak, and lower still is unsupported.
MONTHLY_COST_CEILINGrequired10.00Generation stops here; reading, hand editing and export continue.

The build, in order

  1. Sources in, passages out

    Everything the app will ever cite is a passage with a stable id and an offset into the original text.

    1. A passage should be a unit of support, not a unit of tokens.

      Files src/lib/chunk.tstests/chunk.test.ts

    2. Context is what lets a human judge a citation in two seconds.

      Files src/lib/sources.ts

    3. A reused id turns a stale citation into a wrong one.

      Files src/db/schema.ts

    done when · tick each as it passes
    watch out
    • Chunking purely by token count splits a claim from the qualifier that follows it, so the retrieved passage supports half a sentence and your verifier cheerfully passes it. Chunk on paragraph boundaries, overlap by a configured amount, keep the offsets, and show the surrounding text whenever somebody opens a citation.
  2. Retrieval you can see and correct

    The passages that will be used are on screen, editable, before anything is generated.

    1. Otherwise you are debugging the prompt for a retrieval bug.

      Files src/app/project/[id]/retrieve/page.tsx

    2. So a strange draft can be explained instead of argued about.

      Files src/lib/drafts.ts

    3. An ungrounded draft is the thing this app exists to avoid.

      Files src/lib/generate.tstests/generate.test.ts

    done when · tick each as it passes
    watch out
    • Hiding retrieval behind a generate button makes a bad draft indistinguishable from a bad model, and you end up rewriting prompts to fix a problem that was three irrelevant passages. Put the retrieved set on screen first, let it be corrected, and store the exact set used with the draft.
  3. Outline first, approval before prose

    Nothing is drafted until a section structure with a brief per section has been approved.

    1. Structure is cheaper to change than prose.

      Files src/lib/outline.ts

    2. A restructure should not delete yesterday's work.

      Files src/db/schema.ts

    3. The rule is useless if it only lives in the settings page.

      Files src/lib/prompt.tstests/prompt.test.ts

    done when · tick each as it passes
    watch out
    • Generating three thousand words and then deciding the structure is wrong wastes the generation and, worse, anchors the rewrite to the shape of the thing you were about to throw away. Approve a structure first, and make the approval a stored fact rather than a click that leaves no trace.
  4. Draft, then check every sentence yourself

    Each sentence is resolved against the passage it cited and rendered as supported, weak or unsupported.

    1. The model's numbering is a claim until you check it.

      Files src/lib/resolve.tstests/resolve.test.ts

    2. A second pass with one job beats a longer first prompt.

      Files src/lib/verify.ts

    3. It is the first thing the writer needs to know.

      Files src/components/SupportSummary.tsx

    done when · tick each as it passes
    watch out
    • Rendering the model's citations as the app's citations gives you a document that looks sourced and is not: the published audit of four generative search engines found only about half of generated sentences fully supported by their citations, and about a quarter of citations not supporting the sentence they were attached to. Resolve every number against your own passage store, verify the sentence against the passage text in a separate call, and let the failures show.
    • Dropping the citation from a sentence that failed verification leaves a plain, confident sentence sitting in the draft and removes the only signal that it was doubtful. Keep the sentence, mark it unsupported, and make the unsupported count visible before the writer reads a word of the prose.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more ai writing.