---
title: "The complaint register: three people complained about the same thing, and nobody put it together"
subtitle: "Every complaint in one list whoever takes it, sorted into your own categories by a model on your own box, and one honest page a month showing what keeps going wrong"
url: "https://rxed.ai/blueprints/complaint-register.html"
id: "complaint-register"
version: "1.0"
published: "2026-09-07"
kind: "workflow"
setup_effort: "An afternoon"
setup_hours: "3-6"
running_cost_usd_per_month: "0-12"
paid_software_usd_per_month: "0"
time_saved: "not a weekly time saving - it is the month you stop paying for the same fault six times"
time_saved_basis: "the return is a repeat cause found and fixed, not minutes saved; the published entry prices for software sold to do this are USD 14/user/month (Zoho Desk Standard) rising to USD 40 for its top tier, and USD 115/user/month for Zendesk Support Enterprise, both on Zoho's own comparison page, checked 07/09/2026"
runs_by: "owner"
data_location: "your-server"
data_location_note: "A complaints log holds named customers describing a bad experience, alongside your own written admissions of what went wrong. Classifying it with a local model keeps both inside the building, and the register never gains a credential that could mail a customer."
first_to_break: "the complaints staff fix on the spot and never log, which are exactly the ones that form the pattern"
failure_signal: "silent"
problem: "Complaints arrive in five different places - an email, a phone call, a review, a remark at the counter - and each one is handled by whoever caught it and then forgotten. Nobody ever sees that three of them last month were about the same thing."
fix: "Every complaint lands in one list, whoever takes it, with the date, what was promised and which of your own categories it belongs to. Once a month you get a short page showing what people actually complained about, so you can fix the cause instead of the case."
tools: ["Grist", "n8n", "Ollama", "Docker", "Zammad"]
tech: ["Grist", "n8n", "Ollama", "Docker"]
repos:
  - name: "Grist"
    url: "https://github.com/gristlabs/grist-core"
  - name: "n8n"
    url: "https://github.com/n8n-io/n8n"
  - name: "Ollama"
    url: "https://github.com/ollama/ollama"
  - name: "Zammad"
    url: "https://github.com/zammad/zammad"
categories: ["Customer service", "Reporting", "Self-hosted", "n8n", "Local AI"]
source: "RXed AI News — https://rxed.ai"
---
# The complaint register: three people complained about the same thing, and nobody put it together

> Every complaint in one list whoever takes it, sorted into your own categories by a model on your own box, and one honest page a month showing what keeps going wrong

## Before you start

- Your own list of eight to twelve complaint categories, written before any software is installed - if you cannot name them, the model will not name them for you
- One mailbox everything can be forwarded to, and agreement that a complaint solved on the spot still gets logged
- An always-on machine with roughly 8-16 GB of RAM for the local model, or a mini-VPS at EUR 5-12/month
- Ten minutes a month, by the owner, to read the theme page and pick one cause to fix

## What breaks first

the complaints staff fix on the spot and never log, which are exactly the ones that form the pattern. The register looks healthy, the monthly page looks calm, and the recurring fault is invisible because it was always solved in two minutes at the counter. Count logged complaints per person per month; a member of staff at zero is a reporting problem, not a quality result.

Three complaints in a month about the same thing are not three complaints. They are one problem you paid for three times, and nobody put them together, because each one was solved by a different person on a different day and the record died with the phone call.

 

### The problem

 The EU switched off the central complaints button. The Online Dispute Resolution platform, the one every online seller was required to link to, stopped accepting new complaints on 20 March 2025 and was shut down on 20 July 2025, with the stored data deleted; Regulation (EU) 2024/3228 repealed the regulation that created it, and the obligation to link to it went with it. The reason it was killed is the number: 2 to 3 million visitors a year, of which about 2 percent of complaints ever got a positive reply from the trader, which came to roughly 200 resolved cases a year across the whole Union. Nine years of a button almost nobody answered.

 What replaces it is aimed squarely at the trader. Directive (EU) 2025/2647 was published in the Official Journal on 30 December 2025 and entered into force on 19 January 2026, and member states have to have it in national law by 20 March 2028. Three things in it matter for a small business. When a dispute-resolution body contacts you about a case, you answer within 20 working days whether you will take part, 30 if the case is genuinely complex. The scope now also covers pre-contractual behaviour, so what you advertised and what you failed to disclose are in range, along with digital content and services. And traders are pushed to tell customers how their own in-house complaint handling works, which presumes you have one.

 There is also a small job on your website today. If your legal notice, terms or email footer still links to the ODR platform, it points at something that has not existed since July 2025. German practitioners flag that a stale reference is not neutral: it can be read as a misleading commercial practice and drag in a cease-and-desist letter. Delete it.

 None of that is the real reason to build this. The real reason is that complaints arrive in five places — the shared inbox, a phone call, a remark at the counter, a review, a message to a personal number — each one gets handled by whoever caught it, and none of them meet. So the same faulty batch, the same technician, the same misleading line on the quote generates six separate apologies over a quarter and no decision. The software sold for this starts at $14 per user per month for Zoho Desk Standard and runs to $40 for its top tier, with Zendesk Support Enterprise at $115 per user per month, all on Zoho's own published comparison page, checked 07/09/2026. For a business with five people and forty complaints a year, that is not the answer. A list, a fixed set of categories, and one honest page a month is the answer.

 

### The architecture

 
 [ complaints@yourbusiness ]  [ web form ]  [ counter / phone, typed in ] 
         │                  │                  │ 
         └────────────────┴────────────────┘ 
         ▼ 
 [ n8n ] one pass every 15 minutes — makes the row, never the answer 
         ▼ 
 [ Local model via Ollama ] picks from your fixed list: 
         │  theme (8-12 options, or "other"), product/job reference, 
         │  what the customer is asking for — as a draft 
         ▼ 
 [ Grist — the register, one row per complaint ] ◄── the only record 
         │  acknowledge_by = received + 2 working days 
         │  promised_by     = what you told the customer 
         │  adr_reply_by    = body's letter + 20 working days 
         ▼ 
 ├─ severity high (injury, food, data, money) → a person, now 
 ├─ any clock passed → the owner, by name 
 └─ first Monday of the month → one page: themes, repeats, what it cost 
 
 Nothing is sent to a customer by a machine. The register classifies; people reply.
 

 The whole design decision is that the model only ever fills the boxes. It reads a paragraph of angry text and picks a theme from a list you wrote, pulls out the order or job number, and says what is being asked for. That is copying, not judgement, and a 7-8B model does it well. The reply, the goodwill, the refund and the apology stay human, because a complaint answered by a machine is how one unhappy customer becomes a screenshot with 400 shares.

 

### Tool choices — and why

 Grist (Apache-2.0, 11.7k stars, pushed 07/09/2026) is the register, and it is doing two jobs. Its built-in forms give you the public complaint page and the 30-second internal form staff use after a phone call, without a second piece of software. Its cells hold real Python formulas, so the working-day arithmetic on the three clocks sits in the table where you can read it and correct it, not inside a script nobody opens.

 n8n (Sustainable Use License — free for internal business use, 203.6k stars, pushed 07/09/2026) does the fetching: read the complaints mailbox, create the row, call the model, check the clocks, send the internal alerts, build the monthly page. Every action it takes is internal. It has no credential that can mail a customer, and that is deliberate.

 Ollama (MIT, 180.3k stars, pushed 05/09/2026) runs the classification on your own machine. Complaints contain the two things you least want in someone's API logs: named customers who are angry, and your own admissions about what went wrong. Keep both in the building. Give the model the category list in the prompt and force it to answer with one of them or with "other".

 The alternative, honestly. If you already run a help desk — Zammad (AGPL-3.0, 5.9k stars, pushed 07/09/2026), or the self-hosted help desk from this library — do not build a second inbox. You already have the tickets. What you are missing is the classification and the monthly read, so point n8n at the ticket database instead of a mailbox and skip straight to the register. And if you handle fewer than about one complaint a month, build nothing: a shared spreadsheet with six columns will beat this, and you will actually fill it in.

 Cost. Software €0. Hosting €0 if a box from another blueprint is already running, otherwise €5-12/month for a small VPS. The local model runs on 8-16 GB of RAM. There is no per-user fee, which is the point: complaints should be logged by everybody who takes one, and per-seat pricing quietly teaches a small team to log fewer.

 

### Setup outline

 1. Write the theme list before you install anything. Eight to twelve categories, in your own words, from the last twenty complaints you can remember — "late", "wrong item", "damaged on arrival", "quality of the work", "billed wrong", "staff attitude", "could not reach us". If you cannot name your categories, the software will not name them for you. 
 2. Deploy Grist and n8n on one box behind HTTPS. Build the register: received date, channel, customer, order or job reference, what happened in their words, theme, severity, what they are asking for, who owns it, what you promised, promised date, what it cost you, closed date, cause. 
 3. Add the three formula columns — acknowledge_by, promised_by, adr_reply_by — and count them in working days, not calendar days. 
 4. Publish two Grist forms: one public page linked from your site as "make a complaint", one internal page a member of staff fills in after a call or a counter conversation. The internal one must be answerable in 30 seconds on a phone. 
 5. Create complaints@ and forward to it anything that arrives elsewhere. Build the n8n flow: read the mailbox, create the row, attach the original message. 
 6. Install Ollama, pull a 7-8B instruct model, and write one prompt that returns JSON with theme, reference and requested remedy — with the category list pasted in and an instruction to answer "other" rather than invent. Run it over the last fifty complaints you can find and check it by hand before you trust a single row. 
 7. Add the alerting pass: high severity goes to a person immediately; a passed clock goes to the owner by name, not to a channel where it becomes wallpaper. 
 8. Build the monthly page: complaints by theme, the three that repeated, average days to close, and the total of what you paid out. Set it to arrive on the first Monday. Read it for ten minutes and pick one cause to fix. That ten minutes is the whole return on this build.

 

### Pitfalls — the real ones

 The complaints that never get logged are the ones you needed. Staff log the formal, written, scary complaints and fix the small ones on the spot out of pride. The small ones are the pattern. This is why the internal form is 30 seconds and why logging has to be praised in front of people, not just permitted. 
 Let the model choose categories and they will drift. Free-form labels give you "delivery issue", "late delivery" and "shipping delay" as three separate themes, and your monthly page shows nothing. Fix the list, force a choice, and review the "other" pile once a month. That review is how the list earns a thirteenth category, once a year, on evidence. 
 Severity is a human call. Injury, food safety, personal data, and anything with a lawyer in it route to a person the minute the row exists, regardless of what the model wrote. Do not let a classifier stand between a hurt customer and you. 
 Working days, and the clock starts with the letter. The 20 working days under Directive (EU) 2025/2647 begin when the dispute body contacts you, not when the customer first complained, and the national rules that decide what happens if you miss it will differ by country when they land by 20 March 2028. Count in working days and hold your own holidays in the table. 
 The register is a record, so treat it like one. It holds named customers describing a bad experience, which is personal data with a purpose and a retention period. Decide how long you keep a closed complaint, write it down, and delete on schedule. Do not quietly turn a complaints log into a permanent file on people. 
 Do not connect it to your customer mail. Every failure mode of this build that ends badly involves a generated apology going out without a human reading it. The machine classifies and reminds. People answer.

 

### Verified repos

 
 [Grist](https://github.com/gristlabs/grist-core) — Apache-2.0, 11.7k stars, active (07/09/2026) 
 [n8n](https://github.com/n8n-io/n8n) — Sustainable Use License (free self-hosted internal use), 203.6k stars, active (07/09/2026) 
 [Ollama](https://github.com/ollama/ollama) — MIT, 180.3k stars, active (05/09/2026) 
 [Zammad](https://github.com/zammad/zammad) — AGPL-3.0, 5.9k stars, active (07/09/2026) — the alternative if you want full ticketing
 

 
 Get the next blueprint as it publishes — free, practical, verified tooling only.

 [Subscribe](https://subscribe.rxed.ai) · Want this audited or extended for your business? DM [@RXed_EU](https://x.com/RXed_EU)
