managarten/apps/matrix/CLAUDE.md
Till JS 22a73943e1 chore: complete ManaCore → Mana rename (docs, go modules, plists, images)
Final cleanup of references missed in previous rename commits:

- Dockerfiles: PUBLIC_MANA_CORE_AUTH_URL → PUBLIC_MANA_AUTH_URL
- Go modules: github.com/manacore/* → github.com/mana/* (7 go.mod files)
- launchd plists: com.manacore.* → com.mana.* (14 files renamed + content)
- Image assets: *_Manacore_AI_Credits* → *_Mana_AI_Credits* (11 files)
- .env.example files: ManaCore brand strings → Mana
- .prettierignore: stale apps/manacore/* paths → apps/mana/*
- Markdown docs (CLAUDE.md, /docs/*): mana-core-auth → mana-auth, etc.

Excluded from rename: .claude/, devlog/, manascore/ (historical content),
client testimonials, blueprints, npm package refs (@mana-core/*).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:26:10 +02:00

7.1 KiB

Manalink

Secure Matrix messaging client - a bridge to decentralized communication.

Production URL: https://link.mana.how

Project Overview

Manalink is a privacy-focused Matrix client built with SvelteKit. It connects to Matrix homeservers (default: matrix.mana.how) and supports PWA installation for mobile devices.

Tech Stack

Layer Technology
Frontend SvelteKit 2, Svelte 5 (runes), Tailwind CSS 4
Matrix SDK matrix-js-sdk + matrix-sdk-crypto-wasm
State Management Svelte 5 runes ($state, $derived)
Icons @mana/shared-icons (Phosphor)
PWA @vite-pwa/sveltekit + Workbox
Date Handling date-fns

Project Structure

apps/matrix/
├── apps/
│   └── web/                      # SvelteKit web client (PWA)
│       ├── src/
│       │   ├── routes/
│       │   │   ├── (auth)/       # Login flow
│       │   │   ├── (app)/        # Protected chat routes
│       │   │   └── health/       # Health check endpoint
│       │   └── lib/
│       │       ├── matrix/       # Matrix SDK integration
│       │       │   ├── store.svelte.ts  # Reactive Matrix store
│       │       │   ├── client.ts        # Login/auth functions
│       │       │   ├── crypto.ts        # E2EE utilities
│       │       │   ├── types.ts         # TypeScript types
│       │       │   └── polyfills.ts     # Browser polyfills
│       │       └── components/
│       │           ├── chat/     # Chat UI components
│       │           ├── call/     # VoIP call components
│       │           └── crypto/   # E2EE verification UI
│       ├── static/               # PWA icons and assets
│       ├── scripts/
│       │   └── generate-icons.mjs  # Icon generation script
│       └── package.json
└── packages/
    └── shared/                   # Shared types

Development

# Start the web client
pnpm dev:matrix:web

# Or from monorepo root
pnpm matrix:dev

# Generate PWA icons (after changing favicon.svg)
cd apps/matrix/apps/web && node scripts/generate-icons.mjs

The client runs on http://localhost:5180

PWA Features

Manalink is a Progressive Web App with:

  • Installable on iOS/Android homescreen
  • Offline support via Service Worker caching
  • Push notifications (Web Push API)
  • App shortcuts for quick actions

Caching Strategy

Content Strategy TTL
Matrix API NetworkFirst 5 min
Images/Avatars CacheFirst 30 days
Fonts CacheFirst 1 year
App Shell StaleWhileRevalidate -

Installation

  1. Open https://[your-domain] in a mobile browser
  2. Tap "Add to Home Screen" (iOS) or install prompt (Android/Chrome)
  3. Launch from homescreen for fullscreen app experience

Key Files

Matrix Store (src/lib/matrix/store.svelte.ts)

Central reactive store using Svelte 5 runes:

import { matrixStore } from '$lib/matrix';

// State
matrixStore.syncState      // 'STOPPED' | 'PREPARED' | 'SYNCING' | etc.
matrixStore.isReady        // boolean - client ready for use
matrixStore.rooms          // SimpleRoom[] - all rooms
matrixStore.messages       // SimpleMessage[] - current room messages
matrixStore.currentRoom    // Room | null - selected room

// Actions
await matrixStore.initialize(credentials);
matrixStore.selectRoom(roomId);
await matrixStore.sendMessage('Hello!');
await matrixStore.sendTyping(true);
matrixStore.logout();

Login Client (src/lib/matrix/client.ts)

import { loginWithPassword, checkHomeserver } from '$lib/matrix';

const result = await loginWithPassword('matrix.mana.how', 'user', 'password');
if (result.success) {
  await matrixStore.initialize(result.credentials);
}

Features

Phase 1 (Current)

  • Password login + SSO (Mana Core)
  • Room list (DMs and groups)
  • Message timeline with pagination
  • Send text messages
  • Typing indicators
  • Read receipts
  • Unread/highlight counts
  • Room creation
  • Room settings
  • Message search
  • PWA support

Phase 2 (In Progress)

  • End-to-end encryption (E2EE)
  • File/image uploads
  • Message editing/deletion
  • User search/invite
  • Message reactions

Phase 3 (Future)

  • VoIP calls (WebRTC)
  • Video calls
  • Screen sharing
  • Capacitor native wrapper

Configuration

Environment Variables

No environment variables required for basic usage. The client stores credentials in localStorage.

Default Homeserver

The login page defaults to matrix.mana.how but any Matrix homeserver can be used.

Test Account

For testing the SSO login flow:

Matrix SDK Notes

Browser Polyfills

matrix-js-sdk requires polyfills for browser usage. These are automatically loaded in src/lib/matrix/polyfills.ts:

  • Buffer from buffer package
  • global mapped to globalThis
  • process.env stub

Vite Configuration

Special Vite config for Matrix SDK + PWA:

// WASM headers for crypto
server: {
  headers: {
    'Cross-Origin-Opener-Policy': 'same-origin',
    'Cross-Origin-Embedder-Policy': 'require-corp',
  },
},
// PWA plugin
plugins: [
  SvelteKitPWA({
    registerType: 'autoUpdate',
    manifest: { ... },
    workbox: { ... },
  }),
],

Client-Side Only

matrix-js-sdk only works client-side. Always guard with:

import { browser } from '$app/environment';

if (browser) {
  await matrixStore.initialize();
}

Troubleshooting

Can't see the login page / stuck on loading

The app auto-logs in if credentials are stored in localStorage. To reset:

  1. Browser console method:

    localStorage.removeItem('matrix_credentials');
    location.reload();
    
  2. Direct URL: Navigate to https://link.mana.how/login directly

  3. If logged in: Use the logout button in settings or navigation

"super.off is not a function"

This is a known issue with typed-event-emitter. Make sure polyfills are loaded before any matrix-js-sdk imports.

Login fails with network error

  1. Check if homeserver is reachable: curl https://matrix.mana.how/_matrix/client/versions
  2. Verify CORS is configured on Synapse
  3. Try without https:// prefix in homeserver field

Messages not loading

The initial sync can take time depending on room history. Check matrixStore.syncState for status.

PWA not installing

  1. Ensure HTTPS is enabled
  2. Check manifest.json is served correctly
  3. Verify icons exist at specified paths
  4. Check DevTools > Application > Manifest for errors