docs/02-core-concepts
Monday 2 March 2026

Core Concepts

This guide covers the fundamental building blocks of Mau. Understanding these concepts is essential for building Mau applications.

Table of Contents

  1. Storage Model
  2. Data Format
  3. Identity & Authentication
  4. Addressing Scheme
  5. Peer-to-Peer Architecture

Storage Model

Everything is a File

Mau adopts the Unix philosophy: everything is a file. This radical simplicity has profound implications.

Directory Structure

~/.mau/                                    # Root directory
├── .mau/                                  # Reserved metadata directory
│   ├── account.pgp                        # Your encrypted private key
│   ├── alice-FPR.pgp                      # Friend's public key
│   ├── bob-FPR.pgp                        # Friend's public key
│   └── coworkers/                         # Key groups (keyrings)
│       └── charlie-FPR.pgp
│
├── alice-FPR/                             # Your posts (alice = you)
│   ├── hello-world.json.pgp              # Post file
│   ├── recipe-lasagna.json.pgp           # Another post
│   └── recipe-lasagna.json.pgp.versions/ # Version history
│       └── abc123...xyz.pgp              # Old version (SHA256 hash)
│
├── bob-FPR/                               # Bob's synced posts
│   ├── comment-on-hello.json.pgp
│   └── status-update.json.pgp
│
└── .charlie-FPR/                          # Hidden = unfollowed (kept for history)
    └── old-post.json.pgp

Key Rules

  1. User directories are named by fingerprint

    • Your posts: <your-fingerprint>/
    • Friends’ posts: <friend-fingerprint>/
  2. Files use .pgp extension

    • All content is PGP-encrypted
    • File format: OpenPGP Message Format (RFC 4880)
  3. Hidden directories (.prefix) are ignored

    • Unfollow someone? Prefix their directory with .
    • Data is preserved, but clients won’t sync it
  4. .mau/ is reserved

    • Stores keys and metadata
    • account.pgp = your encrypted private key
    • Other files = friends’ public keys
  5. Versioning uses subdirectories

    • Format: <filename>.versions/<sha256-hash>.pgp
    • Keeps history for contracts, signed documents, etc.

Why Files?

This design gives you:

Backup with standard tools: tar czf backup.tar.gz ~/.mau
Restore from backup: Extract and you’re back
Delete everything: rm -rf ~/.mau
Inspect with text tools: ls, grep, find
Network file systems: Store on NAS, Dropbox, etc.
Multiple clients: Terminal app, GUI, web interface—all access the same files


Data Format

JSON-LD + Schema.org

Mau uses JSON-LD (JSON for Linked Data) with Schema.org vocabulary.

Why JSON-LD?

  • Structured content - Not just text, but typed objects (recipes, events, reviews…)
  • Extensible - Add new types without breaking old clients
  • Web-compatible - Millions of websites already use it for SEO
  • Developer-friendly - Just JSON with special @ keys

Basic Example

 1{
 2  "@context": "https://schema.org",
 3  "@type": "SocialMediaPosting",
 4  "headline": "Loving peer-to-peer social media!",
 5  "articleBody": "Mau gives me full control over my data.",
 6  "author": {
 7    "@type": "Person",
 8    "name": "Alice",
 9    "identifier": "abc123...xyz"
10  },
11  "datePublished": "2026-02-27T10:00:00Z"
12}

Schema.org Types

Common types for social apps:

Type Use Case
SocialMediaPosting Status updates, tweets
Comment Replies to posts
Message Private messages
Recipe Cooking instructions
Review Product/place reviews
Event Meetups, conferences
Article Blog posts
ImageObject Photos
VideoObject Videos
FollowAction Follow someone
LikeAction Like a post

See Schema.org full list for 800+ types.

Actions and References

Reference other content using Mau addresses:

 1{
 2  "@context": "https://schema.org",
 3  "@type": "Comment",
 4  "text": "Great post!",
 5  "about": "/p2p/alice-FPR/hello-world.json",
 6  "author": {
 7    "@type": "Person",
 8    "name": "Bob"
 9  }
10}

Like someone’s post:

1{
2  "@context": "https://schema.org",
3  "@type": "LikeAction",
4  "agent": {
5    "@type": "Person",
6    "identifier": "bob-FPR"
7  },
8  "object": "/p2p/alice-FPR/hello-world.json"
9}

Multiple Languages

Schema.org supports localization:

 1{
 2  "@context": "https://schema.org",
 3  "@type": "Article",
 4  "headline": {
 5    "@language": "en",
 6    "@value": "Hello World"
 7  },
 8  "alternativeHeadline": {
 9    "@language": "ar",
10    "@value": "مرحبا بالعالم"
11  }
12}

Binary Attachments

For images/videos, use encodingFormat and contentUrl:

1{
2  "@context": "https://schema.org",
3  "@type": "ImageObject",
4  "contentUrl": "photo.jpg",
5  "encodingFormat": "image/jpeg",
6  "caption": "Sunset in Berlin"
7}

The binary file (photo.jpg) lives next to the JSON file:

alice-FPR/
├── vacation-post.json.pgp
└── vacation-post-photo.jpg.pgp  # Referenced as "photo.jpg" in JSON

Identity & Authentication

PGP Keys as Identity

Your identity in Mau is your PGP public key fingerprint.

Fingerprint Format

5D000B2F2C040A1675B49D7F0C7CB7DC36999D56
└────────── 160 bits (40 hex chars) ──────────┘
  • Derived from your public key
  • Globally unique
  • Used as your “username” everywhere

Key Generation

Default: Mau now defaults to Ed25519 keys for new accounts (faster, smaller, modern cryptography).

 1# Generate a new identity
 2gpg --full-generate-key
 3
 4# Recommended choices:
 5# - (9) ECC (sign and encrypt) *default: Curve 25519*
 6# - No expiration (or set expiration for security)
 7# - Passphrase to protect private key
 8
 9# Alternative (RSA for compatibility):
10# - (1) RSA and RSA
11# - 4096 bits
12# - No expiration
13
14# Export public key
15gpg --export alice@example.com > ~/.mau/.mau/account.pub.pgp
16
17# Export private key (encrypted with passphrase)
18gpg --export-secret-keys alice@example.com > ~/.mau/.mau/account.pgp

Ed25519 benefits:

  • Smaller keys (~256 bits vs 4096 bits RSA)
  • Faster signing and verification
  • Modern, well-audited cryptography
  • Still compatible with PGP/GPG ecosystem

Signing Content

Every post is signed to prove:

  1. It came from you (authenticity)
  2. It wasn’t tampered with (integrity)
1# Sign and encrypt a post for public viewing
2echo '{"@type":"SocialMediaPosting",...}' \
3  | gpg --sign --encrypt -r alice-FPR \
4  > hello-world.json.pgp

When others download your post, they:

  1. Decrypt it (if they’re a recipient)
  2. Verify your signature
  3. See your fingerprint as the author

Encryption for Privacy

Public post (anyone can read):

1gpg --encrypt --sign -r alice-FPR < post.json > post.json.pgp

(Encrypted to your own key, signed by you)

Private message (only Bob can read):

1gpg --encrypt --sign -r bob-FPR < message.json > message.json.pgp

Group message (Alice, Bob, and Charlie):

1gpg --encrypt --sign -r alice-FPR -r bob-FPR -r charlie-FPR < group-msg.json > group-msg.json.pgp

Friend’s Keys

When you follow someone:

  1. Get their public key fingerprint (e.g., via QR code, website, email)
  2. Download their public key
  3. Save to ~/.mau/.mau/<friend-fingerprint>.pgp
  4. Encrypt it with your key (proves you added them, not malware)
1gpg --export bob-FPR | gpg --encrypt -r alice-FPR > ~/.mau/.mau/bob-FPR.pgp

Addressing Scheme

Mau URLs

Everything in Mau has a hierarchical address:

/p2p/<user-fingerprint>/<filename>

Examples

Address Meaning
/p2p/alice-FPR List all of Alice’s files
/p2p/alice-FPR/hello-world.json Alice’s “hello-world” post
/p2p/alice-FPR/recipe-lasagna.json.versions/abc123 Old version of Alice’s recipe

File Listing

Request: GET /p2p/alice-FPR

Response:

 1[
 2  {
 3    "name": "hello-world.json",
 4    "size": 1024,
 5    "sha256": "abc123...",
 6    "modified": "2026-02-27T10:00:00Z"
 7  },
 8  {
 9    "name": "recipe-lasagna.json",
10    "size": 2048,
11    "sha256": "def456...",
12    "modified": "2026-02-26T15:30:00Z"
13  }
14]

Incremental Sync

Use If-Modified-Since header:

1GET /p2p/alice-FPR
2If-Modified-Since: Wed, 26 Feb 2026 00:00:00 GMT

Server returns only files modified after that date.

Versioning

When a file changes:

  1. Old content moves to <filename>.versions/<sha256-hash>.pgp
  2. New content overwrites <filename>.pgp

Request old version:

1GET /p2p/alice-FPR/recipe-lasagna.json.versions/abc123

Peer-to-Peer Architecture

Components

Mau peers run three main modules:

┌──────────────────────────────────────────────┐
│             Mau Peer                          │
│                                               │
│  ┌─────────────┐  ┌──────────────┐          │
│  │HTTP Server  │  │HTTP Client   │          │
│  │(Serve files)│  │(Sync files)  │          │
│  └─────────────┘  └──────────────┘          │
│                                               │
│  ┌────────────────────────────────┐          │
│  │  Peer Discovery                │          │
│  │  - Kademlia DHT                │          │
│  │  - mDNS (local network)        │          │
│  └────────────────────────────────┘          │
│                                               │
│  ┌────────────────────────────────┐          │
│  │  Storage Layer (Filesystem)    │          │
│  └────────────────────────────────┘          │
└──────────────────────────────────────────────┘

1. HTTP Server

Exposes your content:

  • GET /<fingerprint> → File list
  • GET /<fingerprint>/<filename> → Download file
  • GET /<fingerprint>/<filename>.versions/<hash> → Download version

Authentication: TLS 1.3 with client certificates (mutual TLS)

  • Server presents certificate with its fingerprint
  • Client presents certificate with its fingerprint
  • Both verify each other’s identity

2. HTTP Client

Syncs from friends:

  1. For each friend in .mau/
  2. Request: GET /<friend-fpr>?since=<last-sync>
  3. Download new/updated files
  4. Verify signatures
  5. Save to <friend-fpr>/

3. Peer Discovery

mDNS (Local Network)

Broadcasts on LAN:

5D000B2F2C040A1675B49D7F0C7CB7DC36999D56._mau._tcp.local.

Announces:

  • Fingerprint (service name)
  • IP + Port (address)
  • Protocol (_mau._tcp)

Peers on the same WiFi discover each other instantly.

Kademlia DHT (Internet)

Distributed hash table for finding peers anywhere:

  1. Bootstrap: Connect to a few known peers
  2. PING: Check if a node is alive
  3. FIND_NODE: Recursively search for a target fingerprint

Simplified Kademlia (Mau doesn’t store arbitrary values):

  • /kad/ping → “Are you alive?”
  • /kad/find_peer/<fingerprint> → “Where is this person?”

Returns:

 1[
 2  {
 3    "fingerprint": "bob-FPR",
 4    "addresses": ["192.168.1.100:8080", "bob.example.com:443"]
 5  },
 6  {
 7    "fingerprint": "charlie-FPR",
 8    "addresses": ["charlie.example.com:443"]
 9  }
10]

4. NAT Traversal

For peers behind firewalls:

  • UPnP - Automatically open ports on router
  • NAT-PMP - Apple’s NAT traversal protocol
  • Hole punching - Coordinate with a relay peer

Data Flow Example

Alice wants to sync Bob’s posts:

┌─────────┐                          ┌─────────┐
│  Alice  │                          │   Bob   │
└────┬────┘                          └────┬────┘
     │                                     │
     │ 1. Find Bob                         │
     ├─────── /kad/find_peer/bob-FPR ─────>│
     │<─────── {addresses: [bob.com:443]}──┤
     │                                     │
     │ 2. Connect with mutual TLS          │
     ├─────── TLS Handshake ───────────────>│
     │  (Alice's cert + Bob's cert)        │
     │                                     │
     │ 3. Request file list                │
     ├─────── GET /bob-FPR?since=...  ─────>│
     │<─────── [{name: "new-post.json"}]───┤
     │                                     │
     │ 4. Download file                    │
     ├─────── GET /bob-FPR/new-post.json ──>│
     │<─────── <encrypted content> ─────────┤
     │                                     │
     │ 5. Verify & save locally            │
     │  - Check Bob's signature            │
     │  - Decrypt                          │
     │  - Save to ~/.mau/bob-FPR/          │
     │                                     │

Design Principles

1. Simplicity

  • Files, not databases
  • HTTP, not custom protocols
  • PGP, not new crypto

2. Interoperability

  • Schema.org = web-compatible
  • HTTP = works with proxies, CDNs, browsers
  • OpenPGP = any implementation works

3. Privacy by Default

  • End-to-end encryption
  • Can’t read others’ private data
  • No metadata leaks (TLS hides content)

4. Decentralization

  • No central servers
  • No single point of failure
  • No gatekeepers

5. Evolvable

  • New Schema.org types → new features
  • HTTP/3 upgrade → free performance
  • Algorithm upgrades (PGP keys) → user’s choice

Next Steps

Now that you understand the core concepts, let’s build something:

👉 Quick Start Guide - Build your first Mau app in 15 minutes

For deeper dives: