The 30-second incident report: the safety record that actually gets filled in
A voice note from where it happened becomes a dated, checked entry in a register you own - because the paper form in the van has never once been filled in, and the list you must be able to produce is built from what people will actually send
Built for small businesses in general — not a sector list.
Version history
v1.0 · 2026-08-14 — First release. Intake is a voice note on whatever channel the crew already uses, transcribed locally by whisper.cpp and turned into fields by a local model. The model is fenced hard: it fills what happened, where and with what, and is never allowed near severity, fault or reportability. Nothing counts as a record until a named person ticks it. Includes the honest read on Heinrich's 300:29:1 near-miss ratio, which is from 1931 and should not be used as a target.
Every incident system that starts with a form has already lost. Nobody fills in a form on a ladder. Start instead from the one thing people reliably do send — a voice note, thirty seconds, while it is still fresh — and build the record from that.
The architecture
the same flow as text
[ A phone, on site, within the minute ] voice note · photo of the place · nothing typed
▼ email to incident@yourdomain, or a bot in the chat they already use
[ n8n — the intake ]
├─ stamps received-at the second it lands
└─ pulls the file onto your box, then deletes the chat copy
▼
[ whisper.cpp ] audio → text, on your own machine, offline
▼ the transcript is kept verbatim, forever, next to the entry
[ Ollama — fills the form, never the judgement ]
├─ what happened · where · when · who was involved · equipment
├─ what stopped it being worse ← the field that does the work
└─ anything it could not hear → left blank, flagged unclear
▼
[ Grist — the register ] status: draft
▼ a human reads it, fixes the machine name, and ticks. only then is it a record.
├─ injury → routed to whoever handles notification, clock started
├─ near miss → filed, counted, no further action required
└─ a fix agreed → a date and a name, or it is not a fix
▼ monthly
[ Grist — the same-place list ] grouped by location and equipment, oldest open fix at the top
The model transcribes and sorts. Severity, blame and reportability are human fields, always.
Four pieces on one machine, and the split matters. n8n owns the timing and the intake. whisper.cpp turns speech into text and never leaves the building with it. Ollama fills in fields. Grist holds the register and, more usefully, holds it in a table you can hand to somebody and they can read without being trained. Nothing here needs a server rack. An office PC or a Mac mini with 16 GB of RAM runs all four, and if you already built the meeting-notes machine from this library, whisper.cpp and Ollama are already installed.
The problem
A ladder slid and caught on the gutter. Nobody fell. The pan flared and the extractor filter went black, and someone opened a window. A pallet came off the truck at an angle and stopped against a wall instead of a leg. In every one of those, the same thing happened next: nothing. The job was not finished, the form is in a folder in the office, and by the time anyone is back at a desk the moment has passed and there is a delivery to unload.
Then one of them does not stop against the wall. Now you need to say what happened, when, who was there, and whether anything like it had happened before. You reconstruct it from three memories and a WhatsApp thread that has scrolled past. The answer to "had this happened before" is almost always yes, and you cannot show it.
There is a floor under this and it is not optional. The European framework directive on safety at work (89/391/EEC, Article 9(1)(c) and (d)) obliges an employer to keep a list of occupational accidents that leave a worker unfit for work for more than three working days, and to draw up reports on occupational accidents for the responsible authorities, in accordance with national law. That is the EU floor, transposed differently in every member state. What counts as reportable, who you notify, and inside how many days is a national question and this blueprint does not answer it. Ask your prevention advisor once, in writing, and put their answer in the register as a note. What this blueprint does is make sure that when you need the list, it exists.
The software sold for this is priced per person per month. Published SMB pricing runs from roughly $23 to $188 per user per month, with entry tiers around $25 and mid-tier around $70, before implementation. On an eight-person crew the entry tier alone is about $200 a month for a list of things that went wrong. That price is why most small businesses have no register at all, and no register is a worse outcome than a cheap one.
Tool choices — and why
whisper.cpp
(MIT, 52.9k stars, commit 07/08/2026) does the transcription, and the reason it is this one rather than an API is not cost, it is category. A voice note saying "Marc came off the second rung and his wrist swelled up" is health information about a named person. Sending that to a transcription service means a processor agreement, a location question and a retention question, for a thirty-second clip. Local means those questions do not exist. It runs on CPU, handles a noisy site badly enough that you will need the verbatim transcript alongside the entry, and does the job in seconds on a small model.
Ollama
(MIT, 178.5k stars, commit 13/08/2026) turns the transcript into fields. Give a 7–8B model the transcript and a fixed schema and it will pull out place, equipment, people, sequence and consequence perfectly well. What it is not allowed to touch: how serious this was, whose fault it was, and whether it is reportable. Those three are the entire liability surface of the record, and a confident wrong answer in any of them is worse than an empty field. So the prompt has a hard instruction to leave anything it did not clearly hear blank and mark it unclear, and the register refuses to accept an entry with a blank in a required field until a person fills it. A model that guesses gives you a tidy register full of quiet errors, which is exactly the failure you will not notice until the one time it matters.
Grist
(Apache-2.0, 11.5k stars, commit 13/08/2026) is the register. Two reasons over a spreadsheet. First, the formula columns are Python, so "days this fix has been open" and "third event at this location in twelve months" are readable lines rather than a query nobody can check. Second, and this is the one that decides it: access rules per row. The person who reports does not need to see everybody else's entries, and the register that holds injury detail should not be the file that gets copied to a laptop.
n8n
(Sustainable Use License, free for internal business use, 200.5k stars, commit 13/08/2026) runs the intake and the calendar. Mailbox trigger or chat-bot trigger, pull the attachment, stamp it, call whisper.cpp, call Ollama, write the draft row, nudge the reviewer if a draft sits untouched for a day, and fire the monthly grouping. If you already run other blueprints from this library, this is the same instance doing another job.
Monthly cost
Software is €0 for all four. If it runs on a machine you already own, the running cost is electricity. If you want it off-premises, a small VPS with 8 GB of RAM is roughly €10–20/month, and be honest that whisper plus a language model wants that RAM. Storage is trivial: a voice note is a few hundred kilobytes and a site photo a couple of megabytes, so five years of a busy crew fits on any disk. There is no per-person fee, which is the whole point, because per-person pricing is what stops a ten-person business from having a register at all.
Setup outline
1. Decide the intake channel by watching, not by asking. Whatever your crew already uses to send you a photo of a delivery note is the channel. If that is a group chat, put a bot in it; if it is email, use a dedicated address. Adding a new app is how this dies in week two.
2. Write the schema before you write any automation. Eight fields is enough: date and time of the event, location, what happened, equipment involved, people involved, injury yes/no, what stopped it being worse, and status. Add nothing else until you have fifty entries and can point at a field you wished you had.
3. Build the intake in n8n and stamp received-at separately from event time. They are different numbers and the gap between them is itself information.
4. Wire whisper.cpp and keep the transcript. Store it verbatim in its own column and never overwrite it. The structured fields are a convenience; the transcript is the evidence, and when a field turns out to be wrong in eighteen months the transcript is what settles it.
5. Write the extraction prompt with the fence in it, explicitly: fill these fields from the transcript, do not infer severity, do not assign cause or fault, leave unclear items blank and mark them unclear. Then test it on ten real voice notes recorded in the actual noise of your workplace, not in a quiet room. You are measuring how often it gets a machine name or a person's name wrong, and the answer on a site with a compressor running will surprise you.
6. Set every new entry to draft. Nothing is a record until a named person has read it and ticked it. Put the reviewer's name on the workflow, not "the office".
7. Minimise on the way in. Use initials or a payroll number in the body of the register and keep the full name in one restricted column that only the reviewer sees. Photograph the place, not the injury. Nobody needs a picture of a wound in a table that gets exported.
8. Add the routing. Injury yes, and it goes to whoever handles notification with a due date attached, because the deadline is national and short. Near miss, and it needs nothing further than being counted.
9. Add the fix loop. Any entry that produces an agreed action gets an owner and a date. Any action still open after its date shows up at the top of the monthly list. An action list nobody closes is worse than useless, and the next section explains why.
10. Build the same-place view. Group by location and equipment over a rolling twelve months, sorted by count. This is the only output of the whole system that changes a decision. Read it once a month, out loud, in the same meeting where you talk about the schedule.
11. Run a fire drill before you rely on it. Pick a closed entry, ask someone else to produce the full record from the register in five minutes, and see if what comes out is something you would hand to an inspector or an insurer. If it is not, fix the register, not the drill.
Pitfalls — the real ones
The first report that gets someone told off is the last report you receive
This is the failure, and it is not technical. A near-miss register runs entirely on people volunteering that they nearly did something stupid. One conversation that starts with "why were you standing on that" and the channel goes silent, permanently, and you will not notice because silence looks exactly like safety. If you cannot commit to the rule that reporting a near miss never produces a consequence for the reporter, do not build this. You will get a system that reports zero near misses and one accident a year, which is what you have now, but with a server.
Every number you will read about near misses comes from 1931
The 300:29:1 triangle — 300 near misses to 29 minor injuries to one serious one — is H. W. Heinrich, Industrial Accident Prevention, 1931, derived from insurance claim files. Fred Manuele's Heinrich Revisited (2002) points out that Heinrich changed the ratio in later editions without explaining why, and that the original files no longer exist, so nobody can check the work. Later research finds the ratios vary enormously by industry, and that serious and fatal events often have different causes from slips and small cuts, which means driving down minor incidents does not reliably drive down the serious ones. So do not set a target of N near misses per month, and do not promise yourself an injury reduction. The defensible claim is smaller and still worth a weekend: the same corner appearing three times in your own register is information you did not have before.
An open entry that says "the step is loose" is a written record that you knew
That is a reason to close them, not a reason not to write them, and it is the single most common argument for staying with paper. Answer it directly and up front with whoever is nervous about it: the register only becomes a liability if it fills with hazards nobody acted on, so the fix loop with an owner and a date is not administrative decoration, it is the part that makes the whole thing defensible. If you are not going to run the fix loop, the register is not worth building.
The model will get names wrong, confidently
On a noisy site, a person's name and a machine name are the two things transcription fails on, and they are the two fields most likely to matter later. This is why the verbatim transcript sits next to the entry and why the tick is a human tick. Read the draft against the audio the first thirty times; after that you will know which fields to check and which to trust.
Event time is not upload time
Somebody records a voice note at 14:10 and sends it at 18:40 when they get signal. If the register stamps 18:40 as the event, your entire timeline is wrong in a way that is very hard to explain afterwards. Ask for the time in the voice note, extract it as its own field, and keep received-at separately.
The chat app is a doorbell, not an archive
If the record lives in a group chat, it lives on a dozen personal phones, it is readable by anyone who has ever been added, and it leaves with whoever quits. Pull the message onto your own box within the minute and delete the copy in the channel. Say this out loud to the crew when you launch, because "the boss is deleting the messages" is a bad thing to discover on your own.
Health detail is the one category to be strict about
"Cut to the left hand, went to the GP" is what the register needs. Diagnoses, treatment and sick-note contents are not, they belong wherever your occupational health arrangements already put them, and copying them into an operational table is a decision to hold a category of data you have no reason to hold. Keep the register operational and let the medical file be the medical file.
A weekly digest nobody reads is not a system
The monthly same-place list only works if it is read in a meeting that already exists, by someone who can authorise a fix. Emailing it to everybody is how it becomes wallpaper in six weeks.
National rules decide what is reportable and by when, and they are short
Some deadlines are counted in days from the accident, not from when the paperwork was assembled. This blueprint keeps the list and starts a clock; it does not tell you what the clock is set to. Get that number from your prevention advisor once and hard-code it into the workflow with the date you asked.
Sources for the claims above: Directive 89/391/EEC Article 9(1)(c)–(d), via EU-OSHA. Heinrich's ratio and its critique: H. W. Heinrich, Industrial Accident Prevention (1931); F. A. Manuele, Heinrich Revisited: Truisms or Myths (2002); see also Yorio & Moore (2018) on how the ratios vary by establishment. Per-user EHS pricing ranges from published 2026 vendor comparisons. National reporting duties are not covered here and are not the same in any two member states.
Get the next blueprint as it publishes — free, practical, verified tooling only.