Build Jenni AI
YESreplaces $12/mosaves $144/yrback to the verdict
Upload your sources, and the assistant drafts sections that quote and cite only those documents, showing which passage supports each sentence, rejecting any output that cites something you did not supply, and exporting to a document with a bibliography built from the sources you actually used.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the build and the extraction pipeline.
Get it nodejs.org, or nvm install 22. open ↗
Verify
node --version prints v22 or higher - decidefree, and it is the first task
Why Whether assistance of this kind is permitted differs by institution, publisher and assignment, and it is changing. The tool cannot know your rules and the consequence of getting it wrong is yours.
Get it Read your institution's or publisher's current position on writing assistance, and record what it says and when you read it.
Verify
A policy note is recorded for the project with a date - have readyfree
Why Extraction, page positions and retrieval are all only meaningful against real papers, which have columns, footnotes and figures that break naive extraction.
Get it Use the sources for something you are actually writing. Include at least one two column paper and one scanned document.
Verify
At least ten sources import, including a two column paper - API keypay per token; a section is typically a few cents
Why Phase 3 onward. Import and retrieval work without one, which is deliberate.
Get it A provider key with a spend limit, or Ollama for a local model where nothing leaves the machine.
Verify
A draft generates and passes validation - decidefree
Why Styles differ in what fields they require, and discovering a missing field at export is worse than requiring it at import.
Get it Confirm the required style for your work and which fields it needs.
Verify
The style is configured and its required fields are enforced at source import
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- projects(id, title, style, created_at, policy_note) · policy_note records what you checked about permitted assistance - sources(id, project_id, path, title, authors, year, doi, added_at, extraction_state) - passages(id, source_id, page, ordinal, text) · page-level position is what makes a citation checkable - sections(id, project_id, ordinal, heading, brief) - drafts(id, section_id, at, model, text, claims_json, validated) · claims_json maps each sentence to passage ids - revisions(id, draft_id, at, text, author) · your edits, kept separately from generated text - A sentence with no supporting passage is not written. That is the constraint the whole build enforces.
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.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
PROJECT_DIR | required | ~/Writing/Thesis | Sources, drafts and revisions. Your work, in your backup. |
MODEL_PROVIDER | required | local | Which adapter. Local means sources never leave the machine. |
MODEL_API_KEYsecret | optional | sk-... | Only for a hosted provider. Consider whether your sources may be sent to one. |
CONTEXT_TOKEN_BUDGET | required | 8000 | Maximum assembled passages per generation. |
CITATION_STYLE | required | apa | Drives required bibliographic fields and export formatting. |
MIN_PASSAGES_TO_GENERATE | required | 3 | Below this, generation refuses rather than drafting from thin context. |
The build, in order
Sources with checkable positions
An uploaded document becomes passages that each know their page.
Page number preserved per passage. A citation without a page cannot be checked.
Files
src/extract.tsPrefilled from metadata as a suggestion, confirmed by you, with unconfirmed fields marked.
Files
src/sources.tsNo text layer means no passages. Say so rather than importing an empty source.
Files
src/extract.ts
done when · tick each as it passeswatch out- Guessing bibliographic details from a PDF's metadata or its first page is wrong often enough to matter, and a reference list with a wrong year is a real problem in academic work. Ask for the details, prefill from metadata as a suggestion, and mark anything unconfirmed.
Retrieval over your sources only
The model sees passages from your documents and nothing else.
Search your passages, rank, take until the budget is reached.
Files
src/retrieve.tsThe actual passages. You are about to be responsible for whatever is written from them.
Files
src/ui/ContextPreview.tsxNo relevant passages means no draft. Generating anyway is where fabrication starts.
Files
src/retrieve.ts
done when · tick each as it passeswatch out- A model asked to write on a topic will draw on its training data whether or not you gave it sources, and the result reads identically. Supplying only your passages narrows what it can say, but the validation in the next phase is what actually enforces it, so build both.
Drafts where every sentence is attributable
Each generated sentence names the passage that supports it, and one that cannot is not shown.
Structured output with a passage identifier per sentence, so parsing is not a regular expression.
Files
src/generate.tsA pure function, unit tested with a crafted bad reference rather than waiting for a model to produce one.
Files
src/validate.tssrc/validate.test.tsOne bad sentence rejects the draft. Partial acceptance is how unsupported claims survive.
Files
src/generate.ts
done when · tick each as it passeswatch out- Stripping an unsupported sentence and showing the rest teaches you to trust the output, and the next unsupported sentence will be one the validator missed. Reject the draft, show why, and regenerate, so trust attaches to the process rather than to individual sentences.
Your writing and its writing, kept apart
You can always see what was generated and what you wrote.
Generated text is revision one. Your edits are later revisions. The chain answers the question.
Files
src/revisions.tsPer section. Visible, because hiding it is the same as not tracking it.
Files
src/attribution.tsTo any revision. Editing without a way back makes people cautious rather than productive.
Files
src/revisions.ts
done when · tick each as it passeswatch out- Once generated text is edited in place, the boundary disappears and you cannot answer what was written by whom, which is exactly the question an institution or a coauthor may ask. Keep the generated text as a revision and your edits as later revisions, so the history answers it.
Bibliography from what was actually cited
The reference list contains every source you used and nothing you did not.
Walk the citations, collect their sources. Not the upload list and not the model's output.
Files
src/bibliography.tsUnconfirmed details block the export rather than producing a plausible wrong reference.
Files
src/styles.tsUseful information rather than an error, and it belongs in the report rather than the bibliography.
Files
src/report.ts
done when · tick each as it passeswatch out- A reference list built from everything you uploaded includes sources you read and did not use, which is wrong in most styles, and one built from the model's output includes whatever it invented. Build it from the passages actually cited, which is the only list that is both complete and true.
Export, policy and privacyproduct builder
The document leaves cleanly, and you have settled what you are allowed to do with it.
Markdown and a document format. Citations and bibliography from the same source of truth.
Files
src/export.tsPer project, with the date. The tool cannot know your rules; recording that you checked is the honest step.
Files
src/projects.tsWhich model, and whether sources leave the machine. Shown in the interface, not only documented.
Files
src/ui/ModelBadge.tsx
done when · tick each as it passeswatch out- Uploading unpublished sources or a draft to a hosted model may itself breach a confidentiality or publication agreement, separately from any question about assistance. Say which provider receives what, and offer a local model path for work where nothing may leave the machine.
That is the whole plan for Jenni AI. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- Citation search across the literature.
- Any claim that output is publishable as written.
- A judgement about whether your use is permitted.
- Plagiarism detection against a corpus.
- citation search, document workflow, and polished editor integrations
- proprietary ranking data
- brand-trained models
- team workflows
- large template libraries
- Reference manager import, so sources arrive with confirmed details already
- A coverage view showing which sources support which sections
- Optical character recognition for scanned sources, which currently import empty
Need the files? The project pack on the verdict page hands your agent the whole brief · more ai writing.