Geobeet
Garden planning on official Swiss geodata, from the aerial image to a to-scale printed plan.
- Role
- Sole developer, own project
- Period
- July to September 2026
- Python 3.13
- FastAPI
- Pydantic
- uvicorn
- SQLite
- Shapely
- pyproj
- Leaflet
- swisstopo
- WMTS
- rough.js
What it does
Beyond the first paragraph this page is still in German. A full translation is on its way.
A real plot in Däniken, planned on paper and in the head until then. What was needed was not a garden diary but a tool that works with the actual measurements: areas are drawn on the swisstopo aerial image or measured with a tape, crops are planned over the season, the rotation is checked, and out of it comes a to-scale A4 plan to print. The core in one sentence: stored in WGS84, computed only in LV95, because that is the only way square metres and edge lengths come out right in Switzerland. Geobeet is the one project without React and TypeScript, chosen deliberately: Python, a typed API with FastAPI and Pydantic, and interfaces whose behaviour has to be measured rather than read.
Ein reales Grundstück in Däniken SO, bis dahin auf Papier und im Kopf geplant. Gesucht war kein Gartentagebuch, sondern ein Werkzeug, das mit den tatsächlichen Massen rechnet: Flächen werden auf dem swisstopo-Luftbild gezeichnet oder mit dem Bandmass ausgemessen, Kulturen über die Saison geplant, die Fruchtfolge geprüft, und daraus entsteht ein massstäblicher A4-Plan zum Ausdrucken.
Der Kern in einem Satz: gespeichert wird in WGS84, gerechnet ausschliesslich in LV95. Nur so stimmen Quadratmeter und Kantenlängen in der Schweiz. Die Transformation ist an einer einzigen Stelle gekapselt, weil eine Konvention, an die man sich bei jedem Aufruf erinnern muss, keine Konvention ist, sondern eine Fehlerquelle mit Verzögerung. Erschwerend: ein Projektionsfehler stürzt nicht ab, er liefert eine plausibel aussehende Zahl.
Geobeet ist das einzige der sechs Projekte ohne React und TypeScript, bewusst so gewählt: Python, eine typisierte API mit FastAPI und Pydantic, und die Arbeit mit fremden Schnittstellen, deren Verhalten nicht in der Dokumentation steht, sondern gemessen werden muss.
Numbers
- typed API endpoints
- 22 typed API endpoints
- resolution limit, measured rather than estimated
- 10 cm resolution limit, measured rather than estimated
- maximum edge error across seven test cases
- 0.00003 mm maximum edge error across seven test cases
Screenshots



Die Auflösungsgrenze gemessen, statt am Bild zu optimieren
Der Ausgangswunsch war ein schärferes Luftbild, um Beetkanten genauer abzeichnen zu können. Statt zu optimieren wurde zuerst gemessen: Die WMTS-Kacheln enden bei rund 10 cm pro Pixel, darüber antwortet der Server mit HTTP 400, und eine Spektralanalyse des Orthofotos bestätigt dieselbe Grenze. Schärfer existiert nicht. Damit war die Frage falsch gestellt: nicht das Bild musste besser werden, sondern die Eingabe. Ein Bandmass ist an einem 3-Meter-Hochbeet rund zehnmal genauer als das beste verfügbare Luftbild, und daraus entstand die Funktion «Ausmessen statt Abmalen». Was am Bild machbar war, wurde trotzdem gemacht: eine Unsharp-Mask, deren Radius mit der Vergrösserung mitwächst, gemessen von 1.76 auf 4.45 Kantenschärfe.
Stack
- Language
- Python 3.13
- kein Build-Schritt
- Web
- FastAPI 0.141
- uvicorn 0.52
- Pydantic 2.13
- OpenAPI automatisch aus den Schemata
- Geometry
- Shapely 2.1
- pyproj 3.7
- Transformation zwischen WGS84 und LV95
- Storage
- SQLite 3.51 aus der Standardbibliothek
- Schema als SQL-Datei
- GeoJSON als Text
- Map and plan
- Leaflet 1.9
- Leaflet.draw
- swisstopo-Luftbild als WMTS-Dienst
- generiertes SVG
- rough.js
Status and reading
Map, measuring, woody plants, plantings and the plan view are done; calendar, test suite and deployment open, continuation planned. Runs locally with one command. Repository private, access and a demo on request.