← All projects
Project / Engineering notebook

Muninn

A journaling and wellbeing platform with browser-side encryption, offline drafts and local search. Currently in closed beta.

Status
Closed beta
Role
Creator / Developer
ReactNestJSPostgreSQLWebCryptoIndexedDB

A private space for reflection

Muninn brings everyday writing, memories, mood tracking and reflection together. The aim is to preserve more than the text of an entry: what happened, how it felt and which patterns become visible when returning to it later.

Journals contain dated entries with tags, categories, attachments and revision history. Timelines and local search help revisit earlier experiences; weekly reflections and structured wellbeing questionnaires provide another way to look back. Encrypted account exports support portability, including synchronized attachments.

Muninn's dark-themed journal workspace with Work & Growth, Everyday Moments, Small Joys and Weekend Adventures journals
The journal workspace groups entries into distinct spaces, with cover images, descriptions and entry counts. Screenshots show the web application's dark theme.View full size ↗ (opens in a new tab)

Returning to earlier experiences

The timeline brings dated entries and mood records into a calendar. Selecting a day reveals its entries alongside the month view, so a date becomes a route back into the writing. The separate Memories view revisits entries from the same day in previous years.

Muninn's October calendar with entry and mood indicators and two journal entries for the selected day
A selected day connects the calendar to its entries, while entry and mood counts remain visible across the month.View full size ↗ (opens in a new tab)

Privacy as an architectural constraint

Journal content and attachments are encrypted in the browser before upload. Current entry formats also encrypt titles, tags and categories. WebCrypto supplies AES-256-GCM encryption, with fresh data keys for entry revisions and attachments.

Recovery is part of the privacy story. An authenticated, email-confirmed browser can recover account access, and the service can recover account keys. This is client-side encryption with server-assisted recovery, not end-to-end encryption against the service. Some structural and wellbeing metadata remains visible to the backend.

Search runs over an in-memory index of locally decrypted entries. Neither queries nor that decrypted index are sent to the backend, and the plaintext index is not persisted.

Offline editing and synchronization

IndexedDB holds encrypted drafts and cached history. Changes that cannot reach the API are queued as encrypted requests and retried when connectivity returns. Stable identifiers, idempotent mutations, version checks and incremental change feeds support synchronization.

Concurrent edits are surfaced as conflicts, preserving local work for deliberate reconciliation. Offline access depends on the content and keys already available in that browser.

Architecture and delivery

The backend is a NestJS modular monolith with explicit boundaries for journals, entries, identity, attachments, synchronization and wellbeing. Domain behavior and application use cases are separated from HTTP, persistence, storage and AI providers.

PostgreSQL and Drizzle handle records and encrypted payloads; Azure Blob Storage holds encrypted files. An OpenAPI contract produces TypeScript clients for the React application, which uses MUI, TanStack Router and TanStack Query.

An Nx and pnpm monorepo contains the API, web app, public website and shared branding. Applications retain independent versions and deployment artifacts. Docker and Azure DevOps support delivery, while separate infrastructure uses Kubernetes, Helm and Argo CD. Vitest, Supertest and Playwright cover testing boundaries; OpenTelemetry, structured logging and Seq support diagnostics.

AI workflows include summaries, tag suggestions and visual memories. Controls exist at deployment, journal and request level, with selected content reviewed before external processing. Production backend AI is disabled by default. Provider previews are distinguished from actual model output, and self-reported mood remains separate from inferred observations.

Muninn visual-memory preview showing a generated sketch with dated scenes, an AI-generated label and a Prompt audit action
A captured development build shows a visual-memory preview with its AI-generated origin and a prompt-audit action. This illustrates the optional workflow, not production availability.View full size ↗ (opens in a new tab)

Current status

Muninn is in closed beta, focused on the React web application and backend. Native iOS and Android clients using SwiftUI and Jetpack Compose are planned; they are not part of the currently implemented client experience.