thinking about edits...
This commit is contained in:
@@ -144,6 +144,123 @@ vite: {
|
|||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Activity sidecar edits — design spec
|
||||||
|
|
||||||
|
Users edit activities via **sidecar markdown files** that live alongside BAS JSON in the data dir.
|
||||||
|
No database, no server — consistent with the project's static-files-only philosophy.
|
||||||
|
|
||||||
|
### File naming
|
||||||
|
|
||||||
|
```
|
||||||
|
~/bincio_data/
|
||||||
|
2024-05-15T10:30:00Z_cycling.json ← immutable extract output (never touched)
|
||||||
|
2024-05-15T10:30:00Z_cycling.md ← user edits (sidecar)
|
||||||
|
```
|
||||||
|
|
||||||
|
Same stem as the JSON, `.md` extension. `bincio extract` never writes `.md` files,
|
||||||
|
so re-running extract is always safe and will never clobber user edits.
|
||||||
|
|
||||||
|
### Sidecar format
|
||||||
|
|
||||||
|
YAML frontmatter + optional Markdown body:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
title: "Epic climb up Monte Grappa"
|
||||||
|
sport: cycling # override detected sport
|
||||||
|
hide_stats: [cadence] # suppress specific stat panels in detail view
|
||||||
|
highlight: true # pin/feature in feed (shown first, maybe badged)
|
||||||
|
private: false # exclude from public feed
|
||||||
|
gear: "Trek Domane" # freeform gear note
|
||||||
|
---
|
||||||
|
|
||||||
|
Rode with Marco and Giulia. Legs felt great after the rest week...
|
||||||
|
```
|
||||||
|
|
||||||
|
- All frontmatter keys are optional; omit means "keep extracted value"
|
||||||
|
- The Markdown body becomes the activity's `description`, rendered as HTML in the detail page
|
||||||
|
- `hide_stats` takes stat panel names: `elevation`, `speed`, `heart_rate`, `cadence`, `power`
|
||||||
|
|
||||||
|
### Where overrides are applied: the render stage
|
||||||
|
|
||||||
|
The **render stage** (`bincio render`) is the right place — not extract, not the browser.
|
||||||
|
|
||||||
|
- Extract → clean BAS JSON (immutable)
|
||||||
|
- Render → merges sidecars → Astro build consumes enriched data
|
||||||
|
|
||||||
|
A `bincio.render.merge` module walks the data dir, finds `*.md` sidecars,
|
||||||
|
and produces either enriched JSON files or a separate `overrides/index.json`
|
||||||
|
that Astro reads at build time. The site never needs to fetch a `.md` file
|
||||||
|
at runtime — all merging is build-time, keeping the static-first guarantee.
|
||||||
|
|
||||||
|
### Federation angle
|
||||||
|
|
||||||
|
Sidecars work for *remote* activities too: if you include someone else's BAS feed,
|
||||||
|
you can write local `.md` sidecars for their activity IDs. Your render stage applies
|
||||||
|
your overrides on top of their data. This is a natural extension of the local case.
|
||||||
|
|
||||||
|
### Editing UX: `bincio edit --serve`
|
||||||
|
|
||||||
|
A separate FastAPI server (`bincio edit --serve`, default port 4041) handles all writes.
|
||||||
|
The static site and Astro are untouched — no hybrid mode, no dead-code API routes in prod.
|
||||||
|
|
||||||
|
**How it works:**
|
||||||
|
|
||||||
|
```
|
||||||
|
bincio edit --serve --data ~/bincio_data # starts on :4041
|
||||||
|
```
|
||||||
|
|
||||||
|
- Serves a bundled Svelte UI (single compiled HTML, reuses existing Svelte investment)
|
||||||
|
- `GET /api/activity/{id}` — returns merged BAS JSON + existing sidecar fields
|
||||||
|
- `POST /api/activity/{id}` — writes `edits/{id}.md` to the data dir
|
||||||
|
- `POST /api/activity/{id}/images` — multipart upload → `edits/images/{id}/{filename}`
|
||||||
|
- The Astro dev server's file watcher picks up `.md` writes → incremental rebuild
|
||||||
|
|
||||||
|
**Edit UI features:**
|
||||||
|
- Title text input (pre-filled from BAS JSON)
|
||||||
|
- Sport dropdown (pre-filled, shows all known sport types)
|
||||||
|
- Markdown textarea for description, with minimal toolbar (bold, italic, link, image insert)
|
||||||
|
- Live markdown preview panel
|
||||||
|
- `hide_stats` checkbox group: elevation, speed, heart_rate, cadence, power
|
||||||
|
- `highlight` toggle (feature in feed)
|
||||||
|
- `private` toggle (suppress from feed at render time)
|
||||||
|
- Image drag-and-drop zone → uploads to `edits/images/{id}/`, inserts `![]()` into textarea
|
||||||
|
- Save button → POST to API → success toast
|
||||||
|
|
||||||
|
**Workflow (typical):**
|
||||||
|
1. User browses the Astro dev server on :4040
|
||||||
|
2. Activity detail page has an "Edit" button (rendered only when `PUBLIC_EDIT_URL` env var is set)
|
||||||
|
3. Button links to `:4041/edit/{id}` — opens the FastAPI-served edit UI
|
||||||
|
4. User fills in form, saves → sidecar written → Astro rebuilds → refreshing :4040 shows changes
|
||||||
|
|
||||||
|
The `PUBLIC_EDIT_URL` env var in `.env` controls whether the Edit button appears;
|
||||||
|
leave it unset for production builds, set to `http://localhost:4041` for local dev.
|
||||||
|
|
||||||
|
### Image storage
|
||||||
|
|
||||||
|
```
|
||||||
|
~/bincio_data/
|
||||||
|
edits/
|
||||||
|
2024-05-15T10:30:00Z_cycling.md
|
||||||
|
images/
|
||||||
|
2024-05-15T10:30:00Z_cycling/
|
||||||
|
col-summit.jpg
|
||||||
|
group-photo.jpg
|
||||||
|
```
|
||||||
|
|
||||||
|
Images are referenced in the markdown body with relative paths: ``.
|
||||||
|
The render stage resolves relative image paths against `edits/images/{id}/` and copies them
|
||||||
|
to `site/public/images/activities/{id}/` so they're served from the static site.
|
||||||
|
|
||||||
|
### Decided
|
||||||
|
|
||||||
|
- **Sidecar location**: `edits/` subdirectory (not co-located with JSON) — cleaner, easier to
|
||||||
|
backup/sync just your customisations independently of the extracted data
|
||||||
|
- **`private: true`**: suppresses from `index.json` at render time (not client-side hide) —
|
||||||
|
safer for public hosting
|
||||||
|
- **`highlight`**: visual badge in feed + sorted before non-highlighted activities
|
||||||
|
- **Edit UI**: `bincio edit --serve` FastAPI server (Option B) — not integrated into Astro
|
||||||
|
|
||||||
## Known issues / next steps
|
## Known issues / next steps
|
||||||
|
|
||||||
- `bincio render` Python CLI is a stub — site is built via `npm run build` directly
|
- `bincio render` Python CLI is a stub — site is built via `npm run build` directly
|
||||||
@@ -165,3 +282,9 @@ vite: {
|
|||||||
- [ ] Map thumbnail in activity cards (SVG path from GeoJSON)
|
- [ ] Map thumbnail in activity cards (SVG path from GeoJSON)
|
||||||
- [ ] GitHub Actions template for auto-publish
|
- [ ] GitHub Actions template for auto-publish
|
||||||
- [ ] Karoo/Garmin Connect importers beyond Strava
|
- [ ] Karoo/Garmin Connect importers beyond Strava
|
||||||
|
- [ ] `bincio.render.merge` module: walk `edits/`, parse sidecars, produce enriched data for Astro
|
||||||
|
- [ ] `bincio render --watch` incremental rebuild on sidecar changes
|
||||||
|
- [ ] Sidecar `.md` format: title, sport, description, hide_stats, highlight, private, images
|
||||||
|
- [ ] `bincio edit --serve` FastAPI server with Svelte edit UI (port 4041)
|
||||||
|
- [ ] Edit button on activity detail pages (visible when `PUBLIC_EDIT_URL` env var set)
|
||||||
|
- [ ] Image upload → `edits/images/{id}/`, render stage copies to `public/images/activities/{id}/`
|
||||||
|
|||||||
Reference in New Issue
Block a user