diff --git a/docs/superpowers/specs/2026-06-20-pixelfed-import-design.md b/docs/superpowers/specs/2026-06-20-pixelfed-import-design.md new file mode 100644 index 0000000..7589ce6 --- /dev/null +++ b/docs/superpowers/specs/2026-06-20-pixelfed-import-design.md @@ -0,0 +1,168 @@ +# Pixelfed Import & Demo Reorganisation — Design Spec + +**Date:** 2026-06-20 +**Status:** Approved + +## Overview + +Import 36 Pixelfed posts from `gram.social/m038` (exported as `pixelfed-statuses.json`) into three new permanent trips. Simultaneously reorganise the demo system: move the Italy demo trip to a clearly-labelled 2026 demo slug and retire the Japan demo entries. + +--- + +## Scope + +### What this covers + +1. Demo system reorganisation (Italy 2025 demo → `italy-2026-demo`, Japan demo retired) +2. Three new real trip page trees +3. A one-time Python import script that routes posts to the correct trip, downloads photos, and writes Grav entry folders +4. Updated Makefile `demo-load` / `demo-reset` targets + +### What this does not cover + +- Generating proper titles (done interactively with Claude after import) +- Adding GPX routes to real trips +- Lat/lng geocoding (location data from the export has city/country only, no coordinates) + +--- + +## Part 1: Demo System Reorganisation + +### 1a. Italy demo moves to `italy-2026-demo` + +Copy `user/docs/demo/trips/italy-2025/` → `user/docs/demo/trips/italy-2026-demo/`. + +Update the trip page frontmatter inside the new demo source: +```yaml +title: 'Italy 2026 (Demo)' +slug: italy-2026-demo +``` + +Create the real page tree at `user/pages/01.trips/italy-2026-demo/` with the standard four subfolders. + +Update Makefile: +- `demo-load`: replace all `italy-2025` references with `italy-2026-demo` +- `demo-reset`: replace `rm -rf user/pages/01.trips/italy-2025` with `rm -rf user/pages/01.trips/italy-2026-demo` + +`italy-2025` is never touched by demo commands after this change. + +### 1b. Japan demo retired + +Remove all `japan-korea-2026` blocks from `demo-load` and `demo-reset`. + +The source files in `user/docs/demo/trips/japan-korea-2026/` stay on disk as a backup but are not loaded by any make target. The `japan-korea-2026` trip structure and any real content committed there remains untouched. + +### 1c. Italy 2025 demo stories removed + +The 3 Tuscany demo stories currently at `user/pages/01.trips/italy-2025/04.stories/` (if present on disk) are deleted — they are moving to the demo trip. The `04.stories/` folder itself is kept with its `stories.md` index page. + +--- + +## Part 2: Real Trip Page Trees + +Three trips get the standard structure: `trip.md`, `01.dailies/dailies.md`, `02.map/map.md`, `03.stats/stats.md`, `04.stories/stories.md`. + +| Slug | Title | Action | +|---|---|---| +| `central-asia-2023` | Central Asia 2023 | Create new | +| `us-canada-mex-2024` | Northern America 2024 | Create new | +| `italy-2025` | Cycling Tuscany 2025 | Exists — update title only | + +All three are committed to the `user/` git repo as permanent content. + +--- + +## Part 3: Pixelfed Import Script + +### Location + +`scripts/pixelfed-import.py` + +Invoked via: `make pixelfed-import` + +### Input + +`/home/mischa/Nextcloud/Downloads/pixelfed/pixelfed-statuses.json` (36 posts, Pixelfed v1 export format) + +### Trip routing by year + +| `created_at` year | Target trip | +|---|---| +| 2023 | `central-asia-2023` | +| 2024 | `us-canada-mex-2024` | +| 2025 | `italy-2025` | + +Posts are numbered per trip (1-indexed), reset for each trip. + +### Output folder structure + +For each post, one folder inside `user/pages/01.trips/{trip}/01.dailies/`: + +``` +{YYYY-MM-DD}-pixelfed-{N}.entry/ + entry.md + photo-1.jpg + photo-2.jpg + ... +``` + +Where `N` is the per-trip sequence number and `YYYY-MM-DD` comes from `created_at`. + +### Field mapping + +| Pixelfed field | Grav frontmatter field | Notes | +|---|---|---| +| `created_at` | `date` | ISO 8601 → `Y-m-d H:i` | +| *(generated)* | `title` | `"Pixelfed Import {N}"` | +| `place.name` | `location_city` | Empty string if `place` is null | +| `place.country` | `location_country` | Empty string if `place` is null | +| *(none)* | `lat`, `lng` | Always empty — no coordinate data in export | +| *(none)* | `weather_temp_c`, `weather_desc` | Always empty | +| first downloaded photo filename | `hero_image` | e.g. `photo-1.jpg` | +| `content_text` | body | Already HTML-stripped in export | + +Fixed frontmatter values: `template: entry`, `published: true`. + +### Photo download + +For each item in `media_attachments`: +- Download from `url` field +- Save as `photo-{index}.jpg` (1-indexed) regardless of original filename +- Use the extension from the `mime` field (`image/png` → `.png`, `image/jpeg` → `.jpg`) +- Set `hero_image` in frontmatter to the filename of the first downloaded photo + +### Error handling + +- If a photo download fails, log a warning and continue (do not abort the post) +- If the output folder already exists, skip that post (idempotent re-runs) + +### Make target + +```makefile +pixelfed-import: + python3 scripts/pixelfed-import.py +``` + +--- + +## File Map + +| File | Change | +|---|---| +| `user/docs/demo/trips/italy-2026-demo/` | New — copy of italy-2025 demo source with updated title/slug | +| `user/pages/01.trips/italy-2026-demo/` | New — demo trip page tree | +| `user/pages/01.trips/italy-2025/trip.md` | Update title to "Cycling Tuscany 2025" | +| `user/pages/01.trips/italy-2025/04.stories/` | Remove 3 demo story subfolders | +| `user/pages/01.trips/central-asia-2023/` | New — real trip page tree | +| `user/pages/01.trips/us-canada-mex-2024/` | New — real trip page tree | +| `Makefile` | Update demo-load / demo-reset targets | +| `scripts/pixelfed-import.py` | New — one-time import script | + +--- + +## Constraints + +- Never read `.env` directly +- All CSS uses design tokens — script produces no CSS +- Import script writes to `user/pages/` only; caller runs `make content-push` afterwards to commit and sync +- The `italy-2025` trip must never appear in `demo-load` or `demo-reset` after this change