From 5871283d60fb8a38042beb3befe035d706dbff85 Mon Sep 17 00:00:00 2001 From: Till JS Date: Tue, 31 Mar 2026 18:31:45 +0200 Subject: [PATCH] docs: add Mana Bundle Format plan Cross-app data bundle format (.mana / .manapkg) for onboarding flows, templates, and sequential content release. Implementation deferred. Co-Authored-By: Claude Sonnet 4.6 --- .claude/plans/mana-bundle-format.md | 240 ++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 .claude/plans/mana-bundle-format.md diff --git a/.claude/plans/mana-bundle-format.md b/.claude/plans/mana-bundle-format.md new file mode 100644 index 000000000..ba05a4b11 --- /dev/null +++ b/.claude/plans/mana-bundle-format.md @@ -0,0 +1,240 @@ +# Mana Bundle Format + +**Status:** Planned (not started) +**Priority:** Low — implement after local-first migration is complete +**Scope:** New `@manacore/bundle` package + ManaCore import UI + optional `.manapkg` tooling + +--- + +## Vision + +A portable, shareable file format (`.mana` / `.manapkg`) that can be opened in ManaCore and: + +- Creates data across multiple apps (Todo, Calendar, Contacts, Storage, ...) +- Configures dashboard layouts +- Optionally releases content sequentially (day-by-day courses, onboarding flows) + +Primary use cases: + +- Onboarding courses (e.g. GTD setup, productivity starter kit) +- Cross-app templates shared between users +- App-internal onboarding when a user first activates an app +- Future: third-party ecosystem (coaches, companies publishing setups) + +--- + +## File Format + +### Simple: `.mana` (JSON) + +For small bundles without binary assets. + +```json +{ + "version": "1.0", + "type": "blueprint", + "meta": { + "name": "GTD Onboarding", + "description": "Startet dich mit Todo, Kalender & Kontakten", + "author": "mana.how", + "createdAt": "2026-03-31" + }, + "variables": { + "userName": { "type": "string", "prompt": "Wie heißt du?" }, + "startDate": { "type": "date", "default": "today" } + }, + "steps": [ ... ], + "dashboard": { ... } +} +``` + +### Rich: `.manapkg` (ZIP archive) + +For bundles with images, PDFs, audio files. + +``` +onboarding.manapkg +├── manifest.json # name, version, author, asset index +├── blueprint.json # full step/data definition +└── assets/ + ├── avatar.png + ├── cheatsheet.pdf + └── day1-banner.jpg +``` + +Assets referenced in blueprint as `asset://avatar.png` → resolved to MinIO URLs on import. + +--- + +## Data Model + +### Step Structure + +Each step defines what data to create and when to release it: + +```json +{ + "id": "day-1", + "label": "Tag 1: Grundlagen", + "releaseOn": "import", + "data": { + "todo": { + "projects": [{ "id": "onboarding", "name": "Onboarding" }], + "tasks": [{ "title": "App-Tour abschließen", "projectId": "onboarding", "dueDate": "+0d" }] + }, + "calendar": { + "events": [{ "title": "Kick-off", "startDate": "+0d" }] + }, + "contacts": { + "contacts": [ + { "name": "Mana Support", "email": "hi@mana.how", "photoAsset": "asset://avatar.png" } + ] + } + } +} +``` + +### Release Triggers + +Three modes, combinable via `any` / `all`: + +```json +// Time-based (relative to importDate) +"releaseOn": { "trigger": "time", "after": "+1d" } + +// Completion-based (task done, event attended, etc.) +"releaseOn": { "trigger": "task:completed", "taskId": "$day-1.todo.tasks[0].id" } + +// Combination (whichever comes first) +"releaseOn": { + "any": [ + { "trigger": "time", "after": "+1d" }, + { "trigger": "step-completed", "stepId": "day-1" } + ] +} +``` + +Supported trigger types (initial set): + +- `"import"` — immediately on bundle import +- `"time"` + `after: "+Nd"` — N days after import +- `"step-completed"` + `stepId` — after another step's data has been applied +- `"task:completed"` + `taskId` — when a specific task is checked off + +### Dashboard Configuration + +```json +"dashboard": { + "layout": [ + { "type": "tasks-today", "size": "medium", "position": { "x": 0, "y": 0 } }, + { "type": "calendar-upcoming", "size": "medium", "position": { "x": 4, "y": 0 } }, + { "type": "bundle-progress", "size": "small", "position": { "x": 8, "y": 0 } } + ] +} +``` + +--- + +## Binary / Asset Handling + +| Asset size | Strategy | +| --------------- | -------------------------------------------------- | +| Small (< 50 KB) | Base64 inline in blueprint.json | +| Medium / Large | `.manapkg` ZIP with `assets/` folder | +| Hosted assets | External URL (`https://...`), downloaded on import | + +On import: assets are uploaded to MinIO → URL stored in record. Bundle stays self-contained if `.manapkg`. + +--- + +## ManaCore State: `bundles` Collection + +A new collection in the ManaCore local-store tracks installed bundles and their progress: + +```typescript +interface BundleRecord { + id: string; + name: string; + importedAt: string; // ISO date + anchor: string; // = importedAt, base for relative dates + status: 'active' | 'completed' | 'paused'; + appliedSteps: string[]; // step IDs already applied + pendingSteps: PendingStep[]; +} + +interface PendingStep { + stepId: string; + label: string; + releaseAt?: string; // resolved ISO datetime (for time-triggers) + trigger?: object; // original trigger definition (for reactive triggers) + applied: boolean; +} +``` + +--- + +## Implementation Plan + +### Phase 1: Core Format + Import (MVP) + +1. **`packages/bundle/`** — new package `@manacore/bundle` + - `schema.ts` — TypeScript types for `.mana` format (Blueprint, Step, Trigger, DashboardConfig) + - `parser.ts` — parse & validate `.mana` JSON or `.manapkg` ZIP + - `resolver.ts` — resolve variables, relative dates (`+Nd`), asset references + - `importer.ts` — write data into app collections via cross-app-stores write API + +2. **ManaCore: `bundles` collection** — add to `manacore-store.ts` + +3. **ManaCore: Import UI** + - Drag & drop or file picker on dashboard or settings page + - Variable prompt dialog (if `variables` defined) + - Preview: shows what will be created across which apps + - Confirmation → apply step `releaseOn: "import"` immediately + +4. **ManaCore: `bundle-progress` Dashboard Widget** + - Shows bundle name, progress bar, current/next step label + - Lists completed ✅ / active ▶ / locked 🔒 steps + +### Phase 2: Sequential Release + +5. **Bundle Runner** — background check on app start + - Query `bundles` collection for `status: 'active'` + - For each pending step: check if `releaseAt <= now` → apply & mark applied + - Uses existing `cross-app-stores` write path + +6. **Reactive Triggers** (task:completed, step-completed) + - Subscribe via `liveQuery` on relevant collections + - Trigger condition check → apply next step + +### Phase 3: Asset Support + +7. **`.manapkg` ZIP parsing** — use a lightweight JS ZIP lib (e.g. `fflate`) +8. **Asset upload to MinIO** on import via `@manacore/shared-storage` +9. **External URL download** with offline fallback (queue for later) + +### Phase 4: Tooling (optional, later) + +10. **Bundle authoring CLI** — `mana-bundle create`, `mana-bundle validate`, `mana-bundle pack` +11. **`manacore://` deep link + QR** — open bundle from URL, encode small bundles in QR + +--- + +## Key Files (when implementing) + +| File | Purpose | +| ------------------------------------------------------------------------- | ------------------------------- | +| `packages/bundle/src/schema.ts` | TypeScript types for the format | +| `packages/bundle/src/importer.ts` | Write data into app collections | +| `apps/manacore/apps/web/src/lib/data/manacore-store.ts` | Add `bundles` collection | +| `apps/manacore/apps/web/src/lib/data/cross-app-stores.ts` | Extend write API if needed | +| `apps/manacore/apps/web/src/routes/(app)/+page.svelte` | Import UI entry point | +| `apps/manacore/apps/web/src/lib/components/widgets/BundleProgress.svelte` | Dashboard widget | + +--- + +## Open Questions (resolve when starting) + +- Should bundles be synced via mana-sync so they appear on all devices? (probably yes) +- Max asset size limit for `.manapkg`? +- Should there be a way to "uninstall" a bundle (delete created data)? +- Do we need bundle signing/trust for third-party bundles?