managarten/.claude/plans/mana-bundle-format.md
Till JS 5871283d60 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 <noreply@anthropic.com>
2026-03-31 18:31:45 +02:00

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)

  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

  1. 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
  2. Reactive Triggers (task:completed, step-completed)

    • Subscribe via liveQuery on relevant collections
    • Trigger condition check → apply next step

Phase 3: Asset Support

  1. .manapkg ZIP parsing — use a lightweight JS ZIP lib (e.g. fflate)
  2. Asset upload to MinIO on import via @manacore/shared-storage
  3. External URL download with offline fallback (queue for later)

Phase 4: Tooling (optional, later)

  1. Bundle authoring CLImana-bundle create, mana-bundle validate, mana-bundle pack
  2. 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?