The document history page, with summary cards and a table of five demo contracts with red, amber and green risk badges

The problem

A contract is long and hard to read closely. The tool gives a first reading: a short summary and the clauses that matter most for the person who signs, each with a risk level and a plain explanation.

The approach

A web app and an API. The person uploads a contract, the server reads its text and asks an AI service for the clauses that matter, and the result comes back with a risk level for each clause. It can be saved, found again, questioned and deleted.

The upload, the Delete buttons and the question box call the NestJS server straight from the browser, while the history and report pages ask the server from the Next.js server. Analyses are written as JSON files in a data folder. There is no database: nothing to install, and a file can be read or deleted by hand.

What it does

  • Upload a PDF or Word (.docx) file of up to 10 MB
  • A summary and a list of clauses, each with a quote, a risk level (low, medium or high) and an explanation
  • Only clauses whose quote is found in the document are kept
  • Works with any AI service that has an OpenAI-compatible chat API, such as Ollama on your own computer
  • A button that stops a running analysis, and a server that then cancels its call to the AI service
  • A history page with a search box and a risk filter
  • A report page for each saved analysis, which can be printed or downloaded as a text file
  • Questions about a saved analysis, answered by the AI service
  • Delete one saved analysis, after a confirmation question
  • Saving can be turned off for one upload or for the whole server
  • Each analysis is saved as one JSON file, with no database
  • The report and the question box say that the result is a first reading and not legal advice

Where the engineering is

Clauses that must be quoted from the contract

The server asks the AI service for the clauses that matter most, each with a quote, a risk level and an explanation. A small model can answer in the wrong shape or invent a quote, so the server checks the answer and keeps only the clauses whose quote it can find in the document.

The result is labelled as what it is. The report and the question box both say that it is a first reading by a language model, which can miss a clause or get one wrong, and that it is not legal advice.

The analysis report for a demo NDA, with an executive summary and clause cards marked Low, High and Medium risk, Open the full-size image (opens in a new tab)
A saved analysis, with the summary and the clauses.

Stop means stop

A model on your own computer can be slow, so the server waits up to 120 seconds by default and cuts long documents at 30,000 characters. Meanwhile the page shows a loading screen with a Stop button.

A click on Stop does more than hide the spinner: when the browser stops waiting, the server cancels its call to the AI service. 23 test cases cover the cancel on the server, and in the run that took these pictures, the server logged that it had cancelled the analysis.

The loading screen with a spinner, the text Analyzing Document and a Stop the analysis button, Open the full-size image (opens in a new tab)
The wait, with a way out.

A contract that stays on your computer

The AI service can be any service with an OpenAI-compatible chat API, such as Ollama with qwen2.5:7b on your own computer, so the text of a contract does not have to leave it. The server listens on 127.0.0.1 by default, and only the client page may call it from a browser.

Saving can be turned off for one upload with a checkbox, or for the whole server. Saved analyses can be read only by their owner, and only ids made by the server are used in file names, so an address cannot reach other files.

The start page with the chosen file demo-contract.pdf, the Do not keep this analysis checkbox and the Analyze Document button, Open the full-size image (opens in a new tab)
A file chosen, with the choice not to keep the result.

Every upload checked twice

The browser refuses anything that is not a PDF or a Word file of up to 10 MB, with a plain message, before anything is sent. The server does not rely on that: it checks the file name, the size and the first bytes of the upload again.

The known limits are written down instead of hidden: there is no login, files are not scanned for viruses, a document can still steer the model, and reading a PDF or Word file blocks the server while it works.

The start page with a red message saying a text file is not a PDF or Word document, Open the full-size image (opens in a new tab)
A text file refused before anything is sent.

Questions about a saved analysis

Each saved report has a question box with suggested questions, such as which clauses to read most carefully before signing. Answers come only from the saved summary, clauses and notes, not from the whole contract, and the box says they can be wrong.

Questions are not saved: reloading the page clears them. The README also says plainly that these answers are not checked the way the clauses are.

The question box with suggested questions as buttons and a text field to ask about the contract, Open the full-size image (opens in a new tab)
Suggested questions about one analysis.

Screens

How it's built

LayerTechnology
ClientNext.js 16, React 19, TypeScript and Tailwind CSS 4: 3 pages, plus 404, error and loading screens
ServerNestJS 11 with 7 endpoints, and pdf.js to read the text of PDF files
AIAny OpenAI-compatible chat API, for example Ollama with qwen2.5:7b on your own computer
StorageOne JSON file per analysis in a data folder, with no database
TestsJest on the server, and the Node test runner on the client
Diagram of a browser, a Next.js client, a NestJS server, a local AI service and a JSON data folder, joined by arrows, Open the full-size image (opens in a new tab)
How the browser, the client, the server, the AI service and the data folder talk to each other.

Testing

1,533 automated tests ran and passed: 823 in the client, 629 unit tests and 81 end-to-end tests in the server.

The pictures on this page come from a script that runs the app on made-up demo data, checks that no file of the client or the server changed, and writes down anything it could not confirm.

Results

  • 1,533 automated tests, all passing.
  • 26 source files in the client and 26 in the server, 6,569 lines together.
  • 7 endpoints and 3 pages.
  • Two READMEs of 396 lines together, with the known limits written down.

What I would build next

  • Add a login.
  • Add interactive API documentation.
  • Add browser tests.
  • Add a Dockerfile.

Built with

  • Next.js
  • React
  • TypeScript
  • Tailwind CSS
  • NestJS
  • pdf.js
  • Ollama
  • Jest

56 results