reorg documentation
This commit is contained in:
@@ -13,7 +13,7 @@ Anyone can publish their data as BAS JSON and others can include it.
|
||||
|
||||
## Key design decisions
|
||||
|
||||
- **No database, no server** — everything is static files
|
||||
- **No database, no server** — everything is static files in single-user mode; multi-user VPS mode adds SQLite auth only
|
||||
- **Python with uv** for the extract stage
|
||||
- **Astro + Svelte + Tailwind + MapLibre GL + Observable Plot** for the site
|
||||
- **Haversine** (not geopy) for distance calculations (10x faster)
|
||||
@@ -23,6 +23,11 @@ Anyone can publish their data as BAS JSON and others can include it.
|
||||
- **BAS activity IDs** always use UTC with Z suffix for URL safety
|
||||
- **TCX files** from Garmin use both `http://` and `https://` namespace URIs —
|
||||
parser handles both
|
||||
- **Shard manifest for multi-user** — no activity data duplication; root `index.json`
|
||||
lists user shard URLs; browser resolves all shards concurrently; same mechanism
|
||||
handles yearly pagination and remote federation
|
||||
- **Iterative RDP** implemented inline in `simplify.py` — no `rdp` PyPI package
|
||||
(not available as a pure-Python wheel for Pyodide)
|
||||
|
||||
## Your data
|
||||
|
||||
@@ -44,7 +49,7 @@ bincio/ Python package
|
||||
sport.py sport name normalisation
|
||||
metrics.py haversine-based stats computation (single pass)
|
||||
timeseries.py downsample to 1Hz, build BAS timeseries object
|
||||
simplify.py RDP track simplification → GeoJSON
|
||||
simplify.py RDP track simplification → GeoJSON (iterative, no rdp dep)
|
||||
dedup.py exact (hash) + near-duplicate detection
|
||||
strava_csv.py Strava activities.csv importer
|
||||
writer.py BAS JSON + GeoJSON writer
|
||||
@@ -54,18 +59,29 @@ bincio/ Python package
|
||||
cli.py `bincio render` CLI (symlinks data, runs astro build/dev)
|
||||
merge.py sidecar edit overlay (produces _merged/)
|
||||
edit/
|
||||
cli.py `bincio edit` CLI
|
||||
cli.py `bincio edit` CLI (single-user local only)
|
||||
server.py FastAPI write API for the edit drawer
|
||||
serve/
|
||||
cli.py `bincio serve` CLI (multi-user VPS)
|
||||
server.py FastAPI: auth, user mgmt, write API (auth-gated)
|
||||
db.py SQLite data layer (users, sessions, invites)
|
||||
init_cmd.py `bincio init` CLI: bootstrap instance.db + admin user
|
||||
schema/
|
||||
bas-v1.schema.json JSON Schema for BAS
|
||||
SCHEMA.md Human-readable BAS spec
|
||||
site/ Astro project
|
||||
src/
|
||||
layouts/Base.astro
|
||||
layouts/Base.astro Reads instancePrivate from index.json; injects auth wall
|
||||
pages/
|
||||
index.astro Activity feed (loads index.json client-side)
|
||||
activity/[id].astro Single activity (SSG, loads detail JSON client-side)
|
||||
activity/local/ IDB-only activities (converted locally via Pyodide)
|
||||
stats/index.astro Heatmap + year totals
|
||||
u/[handle].astro Per-user profile pages (multi-user)
|
||||
login/index.astro Login form (public page)
|
||||
register/index.astro Registration with invite code (public page)
|
||||
invites/index.astro Invite management
|
||||
convert/index.astro Local file conversion via Pyodide (browser-only)
|
||||
components/
|
||||
ActivityFeed.svelte Card grid, sport filter, pagination
|
||||
ActivityDetail.svelte Map + stats + charts + photo gallery
|
||||
@@ -73,9 +89,12 @@ site/ Astro project
|
||||
ActivityCharts.svelte Observable Plot (elevation/speed/HR/cadence tabs)
|
||||
StatsView.svelte Yearly heatmap + totals
|
||||
EditDrawer.svelte Slide-in edit panel (visible when PUBLIC_EDIT_URL set)
|
||||
LocalActivityDetail.svelte Detail view for IDB-only (locally converted) activities
|
||||
lib/
|
||||
types.ts BAS TypeScript types
|
||||
format.ts formatDistance, formatDuration, sportIcon, etc.
|
||||
localstore.ts IndexedDB store for locally converted activities
|
||||
dataloader.ts Fetches index.json, resolves shards recursively
|
||||
```
|
||||
|
||||
## How to run
|
||||
@@ -85,16 +104,21 @@ site/ Astro project
|
||||
cd ~/src/bincio_activity
|
||||
uv run bincio extract --input ~/your-activity-data/activities --output /tmp/bincio_test
|
||||
|
||||
# Site dev server
|
||||
cd site
|
||||
ln -sf /tmp/bincio_test/_merged public/data # point at merged output
|
||||
cp .env.example .env && $EDITOR .env # set BINCIO_DATA_DIR
|
||||
npm run dev
|
||||
# Site dev server (single-user)
|
||||
uv run bincio render --data-dir /tmp/bincio_test --serve
|
||||
# → http://localhost:4321
|
||||
|
||||
# Edit server (optional — enables edit drawer in the site)
|
||||
uv run bincio edit --data-dir /tmp/bincio_test
|
||||
# set PUBLIC_EDIT_URL=http://localhost:4041 in site/.env
|
||||
|
||||
# Multi-user local test
|
||||
uv run bincio init --data-dir /tmp/bincio_test --handle dave --password test
|
||||
uv run bincio render --data-dir /tmp/bincio_test --site-dir site --serve # terminal 1
|
||||
uv run bincio serve --data-dir /tmp/bincio_test # terminal 2
|
||||
# site/.env: BINCIO_DATA_DIR=/tmp/bincio_test, PUBLIC_EDIT_URL= (empty)
|
||||
# astro.config.mjs Vite proxy forwards /api/* → localhost:4041
|
||||
|
||||
# Tests
|
||||
uv run pytest
|
||||
```
|
||||
@@ -196,28 +220,48 @@ Rode with friends. Legs felt great after the rest week...
|
||||
- **Unset** → no Edit button, normal static site
|
||||
- **Set** → edit drawer enabled; lives in `site/.env` (gitignored)
|
||||
|
||||
## Multi-user VPS architecture
|
||||
|
||||
`bincio serve` is a FastAPI app that owns auth and write ops. nginx proxies `/api/*` to it; static files are served by nginx directly. The Vite dev server replicates this proxy for local testing.
|
||||
|
||||
Key facts:
|
||||
- Session cookie: `bincio_session`, httpOnly, SameSite=Lax, 30-day max-age
|
||||
- Rate limiting: 10 login attempts / 15 min / IP (in-memory, resets on restart)
|
||||
- Invite limits: admins unlimited, regular users 3 each (`_MAX_USER_INVITES` in `db.py`)
|
||||
- Instance privacy: `instance.private=true` in root `index.json` → `Base.astro` injects a
|
||||
`fetch('/api/me')` auth wall; `/login/` and `/register/` have `public={true}` to skip it
|
||||
- Incremental rebuild: `POST /api/activity/{id}` triggers `bincio render --handle {user}`
|
||||
as a fire-and-forget subprocess (only if `--site-dir` was passed to `bincio serve`)
|
||||
- Write API in `bincio serve` delegates to `bincio.edit.server._apply_sidecar_edit`; the
|
||||
Strava sync delegates to `bincio.edit.server.strava_sync` with a temporary data_dir swap
|
||||
|
||||
## Known issues / next steps
|
||||
|
||||
- `bincio render` Python CLI is functional but `--watch` mode not yet implemented
|
||||
- `bincio render --watch` mode not yet implemented
|
||||
- Activity IDs in older test data may use `+0000` format (pre-fix); re-run extract to get `Z` format
|
||||
- Some activities appear with both untitled and titled IDs (near-dedup timing race)
|
||||
- Federation (remote data sources) not yet implemented in site
|
||||
- Friends pages (`/friends/{handle}/`) not yet implemented
|
||||
- Remote federation (remote shard URLs in root manifest) is parsed but not yet displayed with attribution in the UI
|
||||
- The `site/.env` file is gitignored — copy from `site/.env.example`
|
||||
|
||||
## What "good" looks like (not yet done)
|
||||
|
||||
- [ ] `bincio render` Python CLI wraps `astro build` properly
|
||||
- [ ] Friends/federation pages in site
|
||||
- [ ] Friends/federation pages in site (remote shard attribution)
|
||||
- [ ] Personal records page
|
||||
- [ ] Activity search / full-text filter in feed
|
||||
- [ ] GitHub Actions template for auto-publish
|
||||
- [ ] Karoo/Garmin Connect importers beyond Strava
|
||||
- [ ] `bincio render --watch` incremental rebuild on sidecar/data changes
|
||||
- [ ] Highlight badge in activity feed cards
|
||||
- [x] `bincio.render.merge` — sidecar parser, `_merged/` output, private filter, highlight sort
|
||||
- [x] `bincio edit` FastAPI write API (GET/POST activity, image upload/delete, triggers merge)
|
||||
- [x] `EditDrawer.svelte` — slide-in edit UI in the Astro site
|
||||
- [x] `PUBLIC_EDIT_URL` feature flag
|
||||
- [x] Markdown rendering in activity description with image path rewriting
|
||||
- [x] Photo gallery with lightbox on activity detail page
|
||||
- [ ] `bincio render --watch` incremental rebuild on sidecar/data changes
|
||||
- [ ] Highlight badge in activity feed cards
|
||||
- [x] `bincio serve` — multi-user VPS server (auth, invites, write API)
|
||||
- [x] `bincio init` — instance bootstrap (SQLite, admin user, root manifest)
|
||||
- [x] Login, register, invites pages
|
||||
- [x] Per-user profile pages (`/u/{handle}/`)
|
||||
- [x] Instance privacy (auth wall, private-by-default)
|
||||
- [x] Shard-based combined feed (no duplication, concurrent resolution)
|
||||
- [x] Local file conversion via Pyodide (`/convert/` page, IDB storage)
|
||||
|
||||
Reference in New Issue
Block a user