Cross-app data bundle format (.mana / .manapkg) for onboarding flows, templates, and sequential content release. Implementation deferred. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
7.5 KiB
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.
{
"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:
{
"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:
// 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
"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:
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)
-
packages/bundle/— new package@manacore/bundleschema.ts— TypeScript types for.manaformat (Blueprint, Step, Trigger, DashboardConfig)parser.ts— parse & validate.manaJSON or.manapkgZIPresolver.ts— resolve variables, relative dates (+Nd), asset referencesimporter.ts— write data into app collections via cross-app-stores write API
-
ManaCore:
bundlescollection — add tomanacore-store.ts -
ManaCore: Import UI
- Drag & drop or file picker on dashboard or settings page
- Variable prompt dialog (if
variablesdefined) - Preview: shows what will be created across which apps
- Confirmation → apply step
releaseOn: "import"immediately
-
ManaCore:
bundle-progressDashboard Widget- Shows bundle name, progress bar, current/next step label
- Lists completed ✅ / active ▶ / locked 🔒 steps
Phase 2: Sequential Release
-
Bundle Runner — background check on app start
- Query
bundlescollection forstatus: 'active' - For each pending step: check if
releaseAt <= now→ apply & mark applied - Uses existing
cross-app-storeswrite path
- Query
-
Reactive Triggers (task:completed, step-completed)
- Subscribe via
liveQueryon relevant collections - Trigger condition check → apply next step
- Subscribe via
Phase 3: Asset Support
.manapkgZIP parsing — use a lightweight JS ZIP lib (e.g.fflate)- Asset upload to MinIO on import via
@manacore/shared-storage - External URL download with offline fallback (queue for later)
Phase 4: Tooling (optional, later)
- Bundle authoring CLI —
mana-bundle create,mana-bundle validate,mana-bundle pack 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?