# Yard Map Agent Notes

This file is a fast handoff for future coding agents working in this repo.

## What this project is

Static client-side yard mapping app.

- Rendering: MapLibre GL JS.
- Basemap: committed Mandan-area Protomaps vector tiles in `tiles/mandan.pmtiles`.
- Yard data: authored in JavaScript modules, converted to GeoJSON in the browser.
- Runtime: plain ES modules, no bundler.

## Current architecture

Core files:

- `src/lib/geometry.js`: absolute points, local offsets, feet conversion, per-anchor rotation support.
- `src/lib/feature-types.js`: feature-kind labels, geometry constraints, detail field schemas, and style defaults.
- `src/lib/yard-features.js`: typed feature classes, stable ids, groups, parent-child relationships, schema metadata, GeoJSON export.
- `src/data/*.js`: yard content split by domain.
- `src/main.js`: MapLibre map, yard layers, legend, popup rendering.

Top-level exported data shape from `src/data/yard.js`:

- `type: "FeatureCollection"`
- `schemaVersion: 2`
- `lifecycleFields: { plantedDate: "date", removedDate: "date" }`
- `featureTypes: [...]`
- `features: [...]`
- `groups: [...]`

Each feature currently exports:

- `properties.id`
- `properties.kind`
- `properties.label`
- `properties.name`
- `properties.plantedDate`
- `properties.removedDate`
- `properties.parentId`
- `properties.groupIds`
- `properties.details`

## Important decisions already made

1. Data is JS-authored on purpose.
   This allows mixing exact imported geometry with expressions like `offset(anchor, east(ft(10)))`.

2. Styling belongs to feature types, not individual features by default.
   If you need a new semantic type, prefer adding a new typed feature or feature-type definition rather than hand-styling scattered instances.

3. Local rotation is per anchor.
   `offset(...)` reads `assumedNorthClockwiseDegrees` from the anchor point used as the origin. Do not reintroduce a global lot rotation unless there is a strong reason.

4. Grouping and parent-child metadata are already part of the data model.
   Future visibility controls should consume `groupIds` and `parentId` rather than inventing a second relationship system.

5. The GPKG was only a seed source.
   The app does not depend on GIS tooling at runtime.

## Known data caveat

`buildings.gpkg` has a CRS issue in `lot_boundary`.

- The usable lot polygon was `fid = 2`.
- It had to be treated as `EPSG:26914` during extraction.
- Do not trust that layer's metadata blindly if you re-import from the GPKG.

## What is already modeled

- Porch and deck are children of the main house and also part of the `House Parts` group.
- Medora junipers are part of the `Juniper Trees` group.
- A test tree exists that is offset from the top-left lot corner using per-anchor rotation.

## Likely next steps

1. Add show/hide controls driven by `yardGeoJSON.groups` and possibly `parentId`.
2. Decide whether toggles should be by feature kind, by group, by parent object, or a combination.
3. The basemap uses local vector tiles and is overzoomed from source zoom 15
   through the yard map's maximum zoom of 24. Symbol layers are deliberately
   omitted so the map has no remote font or sprite dependency.

## Useful validation commands

Validate data export:

```bash
node -e "import('./src/data/yard.js').then(({ yardGeoJSON }) => console.log(yardGeoJSON.features.length))"
```

Run local server:

```bash
python3 -m http.server 4173
```

## Editing guidance

- Preserve the typed-feature pattern.
- Prefer adding semantic types or groups over ad hoc properties when possible.
- Keep authored geometry readable; avoid generated noise unless the user explicitly wants bulk-import output.
- If adding new anchors, attach rotation metadata to the anchor itself.
