Grundstücksfinder is a self-hosted search tool for German real-estate parcels. It imports official open data ("Grundsteuer") published by German states, stores it in Postgres, and lets you search parcels by postal code, municipality, and area (m²) through a Blazor Server web UI — with geocoded map markers via OpenStreetMap/Nominatim.
Currently ships with an importer for North Rhine-Westphalia (NRW). The import pipeline is
built around a pluggable IPropertyImporter interface, so adding another Bundesland (or
country) is a matter of writing one importer class — no changes to the shared import,
storage, or search code required.
- Search parcels by PLZ, Gemeinde, and min/max area
- Map view with geocoded markers (Nominatim, cached to respect its usage policy)
- Automatic daily import of new open-data releases, deduplicated per dataset/file/version
- Multiple data sources can coexist without one import wiping another's rows
- Import history (
ImportLog) shown per source
Requires Docker and a web external network for Traefik (or drop the Traefik labels/network
in docker-compose.yml if you don't use it).
-
Copy the env template and fill in real values:
cp .env.example .env
Variable Meaning DB_PASSWORDPassword for the homelocatorPostgres user, shared byappanddbDOMAINPublic hostname Traefik should route to this app GITHUB_REPOSITORY_OWNERGitHub user/org owning the ghcr.io/<owner>/grundstuecksfinderimage -
Start it:
docker compose up -d
The app listens on port
8080behind Traefik and connects to the bundledpostgres:17-alpineservice. On first startup it downloads and imports the current NRW dataset (this can take a few minutes); the daily import check then runs at 03:00 UTC.
docker-compose.dev.yml only starts a local Postgres instance (hardcoded dev password, no
.env needed):
docker compose -f docker-compose.dev.yml up -d
cd Grundstuecksfinder
dotnet run --project GrundstuecksfinderConfig for local dev lives in Grundstuecksfinder/appsettings.Development.json
(ConnectionStrings:DefaultConnection, Import:Nrw:*). To skip waiting on the real NRW
download while developing, set EnableDevSeeding to true (in launchSettings.json or as an
environment variable) — this seeds a handful of fake parcels from part.csv (or a single
hardcoded fallback row) instead of hitting the network.
Implement IPropertyImporter (see Services/Importers/Nrw/NrwPropertyImporter.cs for a
CSV-based example) and register it in Program.cs:
builder.Services.AddScoped<IPropertyImporter, YourRegionPropertyImporter>();The shared ImportOrchestrator/PropertyBulkWriter handle dataset dedup, per-source deletes,
and the Postgres bulk write — your importer only needs to know how to discover and fetch its
region's data.
Integration tests spin up Postgres via Testcontainers, so Docker must be running:
dotnet test --project Grundstuecksfinder.TestsLicensed under the GNU Affero General Public License v3.0 (AGPL-3.0-or-later).
