๐Ÿ€„MJPF

Mahjong Portable Format

An open, platform-neutral way to share a Mahjong deal so two people can play the exact same hand and compare scores โ€” with no server, no account, and no network.

.mjpf spec 1.3.0

Read the spec Implement it Schema & examples

The idea in one line: a Mahjong deal is just a seed and a rule set. Encode those in a tiny QR code, and anyone can replay the identical wall and compete โ€” entirely offline.

Why MJPF exists

Most "play with a friend" features need a backend: accounts, matchmaking, a server to hold state. MJPF takes the opposite approach. Because a good Mahjong engine is deterministic โ€” the whole game is a pure function of one seed โ€” you don't need to send the game. You send the seed.

Share a deal as a QR code or a short copyable code. Your friend plays the same tiles in the same order. When you're both done, you compare results โ€” by eye, or by passing a one-line result code back. No round-trip to any server ever happens. It works on a plane, in a tunnel, across platforms, forever.

What's in the box

A deal

Seed + rule set + opponent tier. The fully platform-neutral core โ€” fits one QR code. Reconstructs a fresh game on the identical wall.

A challenge

A deal plus the challenger's score-to-beat. "Here's my deal โ€” I got 8 faan. Beat it."

A result

A played outcome for a deal, to send back. Compare without trusting a server with either score.

A resume bundle

The full move-by-move log, behind a capability flag โ€” hand off a game in progress, or a complete replay.

Built to last

PrincipleHow MJPF does it
Platform-neutralJSON over UTF-8; 64-bit seeds carried as strings; compression is plain raw DEFLATE. No language- or vendor-specific serialization in the portable core.
Self-describingEvery document states its format, its semver version, and the capabilities it requires โ€” so a reader knows whether it can safely act on it.
Forward-compatibleOld readers accept newer minor versions: unknown fields and advisory capabilities are ignored; a document is refused only when it requires something the reader doesn't know.
ExtensibleA reserved vendor namespace lets any app attach its own data that everyone else ignores gracefully โ€” no coordination, no fork.
Private by designGame data only. No accounts, contacts, location, or device ids โ€” ever.

The transport: MJQR

MJQR is how a document travels: canonical JSON, compressed with raw DEFLATE, base64-encoded. A bare deal fits one QR code. The same string is a copyable code you can paste anywhere โ€” the universal fallback. On Apple devices, AirDrop and the share sheet are conveniences on top; they're never required.

Start implementing โ†’ See it in a real app โ†’