huischeck
v1.0.3
Published
Paste a Dutch house listing, get a scored due-diligence report: commute gates, erfpacht, neighbourhood safety, amenities, mortgage affordability and a condition read from the photos. Self-hosted, web dashboard included.
Downloads
460
Maintainers
Readme
Paste a Dutch house listing. Get a report telling you whether it is actually right for you.
Not "is this a nice house". Whether the commute works, whether the erfpacht is a trap, whether the neighbourhood is what the photos suggest, whether you can afford it, and roughly what it will cost to fix up.
npx huischeck init # writes .env.local
# add a Gemini key and a Google Maps key
npx huischeck add-user me
npx huischeck # → http://localhost:3000Plak een Funda-link en krijg een onderbouwd rapport: reistijden, erfpacht, buurtveiligheid, voorzieningen, maximale hypotheek en een inschatting van de staat van de woning.

Every property you scan gets one score and a plain verdict, so five houses compare side by side instead of living in five browser tabs.
The report. Six tiles across the top: affordability, commute, erfpacht, energy and renovation, neighbourhood, red flags. Any hard gate failing means "has dealbreakers" no matter how high the score.

Money. Max mortgage from the official lending tables, including the energy-label bonus. What it costs per month gross, what comes back through hypotheekrenteaftrek, and what it really costs net. NHG and the startersvrijstelling checked against this specific price. Every figure is computed in code, not by a model.

Commute. Every reference location, by car, off-peak and at rush hour, with the routes drawn. The gate uses the rush-hour number, because that is the one you actually live with.

Why this exists
Every listing looks good. The photos are wide-angle, the text is written by an agent, and the things that actually decide whether you should buy are the things nobody puts in the ad: how long the drive to work really takes at 08:30, whether the erfpacht runs out in eleven years, what the neighbourhood is like after dark, and whether the price leaves you anything for the kitchen.
So: give it one URL, let it go and find all of that out, and get a single scored report you can compare against the last five houses you looked at.
What it works out
Commute, twice. Every reference location you set, by car, at off-peak and at rush hour, through the Google Routes API with live traffic. The pass/fail gate uses the rush-hour number, because that is the one you will actually live with.
Erfpacht. First-class, not a footnote. Freehold scores 100. Bought off in perpetuity scores about 95. Bought off until a date is scored on the years remaining, and a short remaining term or a running annual canon is flagged as the real problem it is.
Neighbourhood. Three parallel grounded research passes, merged before extraction, because a single search pass will miss a recent incident entirely. Weighted by severity, recency and proximity. A serious dated incident in or next to the buurt caps the safety score in code, not by asking the model nicely.
Affordability. A deterministic engine over the 2026 lending norms: maximum
mortgage from the official financieringslast tables, the energy-label borrowing
bonus, NHG, the under-35 startersvrijstelling, itemised kosten koper, how much
cash you actually need, and the net monthly cost after hypotheekrenteaftrek.
Every constant is cited to its source in finance-norms.ts. No model touches
these numbers.
Condition. A multimodal read over the listing text and the full harvested photo gallery: renovation level, what stays and what the seller takes, and red flags that must quote the phrase that triggered them. The euro range is computed in code, not guessed by the model.
Amenities. Nearest supermarket drives the score, a nearby station is a small bonus. Schools and daycare are shown on the map but never scored.
One number. A weighted 0-100 blend of six components, weights adjustable in Settings. Any hard gate failing means "has dealbreakers" regardless of score.
Install
Node 20 or newer. You need two API keys, both with a free tier that covers personal use.
Try it:
npx huischeck init
# fill in .env.local
npx huischeck add-user me
npx huischeckThe first start compiles the app and takes a minute or two. Later starts are immediate.
Run it properly:
git clone https://github.com/OmarNassar1127/huischeck-nl.git
cd huischeck-nl
npm install
cp .env.example .env.local # then fill it in
npm run add-user -- me
npm run build && npm startKeys you need
| Key | Where | What for |
|---|---|---|
| GEMINI_API_KEY | AI Studio | Reading the listing, neighbourhood research, condition read, writing the report |
| GOOGLE_MAPS_API_KEY | Google Cloud | Routes API for commute times, Places API (New) for geocoding and amenities |
Both APIs must be enabled on the same Maps key. Set a budget alert on the Google Cloud project.
First run
npx huischeck add-user <name>— there is no open sign-up.- Sign in, go to Settings, and fill in the four reference locations. These ship as "My current home", "My work", "Partner's work" and "Family". Rename them to whatever fits and set an address and a maximum commute for each. A scan cannot complete until they resolve to coordinates.
- Optionally add the finance profile: gross incomes, birthdates, how much of your own money you are willing to put in, and the interest rate to assume. Leave it blank and affordability is simply skipped.
- Optionally write a household profile in free text. It personalises the neighbourhood research.
Nothing is preconfigured. No addresses, no incomes, no weights beyond neutral defaults.
How a scan runs
paste a listing URL
├── parse grounded fetch, then a separate structured extraction
├── geocode address → coordinates
├── research commute ∥ erfpacht ∥ neighbourhood ∥ amenities
│ ∥ finance ∥ condition (all in parallel)
├── score deterministic gates + weighted 0-100
└── report the model writes the narrative; a code fallback covers
a model failure so the property still completesIt keeps running server-side if you close the tab. The property page polls for progress. A run stalled for about five minutes offers a re-run button.
Design rules this follows
Worth knowing, because they are why the output can be trusted:
- Deterministic logic lives in code. Gates, score maths, commute parsing and every euro figure. The model supplies judgement and prose, never numbers.
- "Could not determine" beats a guess. A number or URL that was not verified is never presented as fact.
- A model-provided URL is never trusted. Image URLs are validated with a ranged GET before use, because the model happily invents plausible ones.
- Grounding and structured output are never combined. On Gemini 3 that truncates JSON mid-object. Two calls: grounded plain text, then a separate structured parse.
Security
- Every page and API route requires a login. The only open surfaces are
/login, the login endpoint, and/api/health, which exposes no data. - Passwords are scrypt-hashed. Sessions are opaque random ids validated server-side on every request, so deleting a row revokes a session.
- API keys are read from the environment and never stored in the database. The Settings page only shows whether a key is set.
- There is no TLS here. If you expose this beyond localhost, put it behind a reverse proxy or a tunnel with authentication.
- Your data is a SQLite file plus uploaded photos in
./data. Back it up. It contains your income and your addresses, so do not commit it.
A note on dependencies
npm audit reports three high-severity advisories from inside Next.js
(postcss and sharp). The advisory range covers every current Next release
and npm's suggested "fix" is to downgrade to Next 9.3.3, from 2020, which is
not a fix. This project tracks the latest Next release. The advisories will
clear when upstream ships a patched version.
Layout
src/app/ App Router pages and API routes
(app)/ authenticated pages: dashboard, add, compare, property, settings
login/ sign-in, outside the auth group
src/components/ dashboard, property report, map, forms
report/ scorecard, panels, the report body
src/lib/
research/ pipeline, scoring, erfpacht, finance, renovation + year-stamped norms
gemini/ client, listing parse, neighbourhood, condition, report
maps/ geocode, routes, places, autocomplete
funda/ preview image, gallery harvest, listing metadata
src/db/ SQLite open + migrate, repositories, mappers
migrations/ plain .sql, applied at startup, tracked in _migrations
scripts/ add-user + engine assertion harnessesDocs
- ARCHITECTURE.md — the scan pipeline, the scoring model, and where each number comes from
- CONTRIBUTING.md — adding a research task, updating the lending norms
- AGENTS.md — for coding agents: the invariants that break quietly, including the two Gemini rules that cost the most to relearn
- SECURITY.md
Related
huurradar— the renting-side counterpart: watches six platforms and tells you the moment something matches
License
MIT
