Live deployment: https://midnight-hermes.duckdns.org/

Inspiration

Anonymous communities are powerful because they let people speak freely, ask sensitive questions, and participate without attaching every action to a permanent identity. The problem is that most anonymous platforms lose the features that make communities usable: trust, moderation, age gates, reputation, and rewards.

On the other side, traditional social platforms solve those problems by collecting more data. Age checks ask for personal documents. Reputation follows users across contexts. Moderation depends on account history. Payments and rewards create metadata trails. The result is a bad tradeoff: either users get privacy with weak community tools, or they get rich community features by giving up personal information.

Hermes started from a simple question: can an online community have Reddit-style interaction, karma, gated spaces, moderation, and gifts without revealing who users are?

Midnight is a strong fit because it lets us combine public community state with private witnesses and zero-knowledge proofs. Hermes uses that model to prove the facts a community needs while keeping identity, birthdate, private reputation, and cross-community behavior hidden.

What it does

Hermes is an anonymous Reddit-style forum on Midnight where users can prove membership, age, karma, moderation status, and rewards eligibility without revealing their identity. It brings trust, safety, and monetization to online communities while keeping users, moderators, and operators cryptographically blind to private data.

Users can:

  • Join communities with unlinkable pseudonyms.
  • Join age-gated communities by proving they are 18+ without revealing their date of birth.
  • Post anonymously while proving valid membership.
  • Vote once per post using nullifiers, without revealing who voted.
  • Earn karma and claim it into private notes.
  • Prove karma thresholds without revealing exact balances.
  • Aggregate karma across multiple unlinkable personas in one proof.
  • Give and claim Gold-style rewards.
  • Use moderation flows where banned pseudonyms are blocked without exposing the human behind them.
  • Open a Privacy Inspector that compares what the user sees against what the chain and server see.

Important boundary: the current prototype includes a mock credential issuer for age and flair credentials. The proof flows, derivations, contract logic, server, SDK, frontend, and tests are implemented, but a production deployment would replace the mock issuer with a real credential provider.

Hermes Architecture diagram

How we built it

The contracts are written in Compact for Midnight. contracts/src/hermes.compact implements the main community logic: joining, age-gated joining, posting, voting, weighted voting, karma claims, karma threshold proofs, aggregate karma proofs, flair proofs, Gold flows, and moderation. The repo also includes split-contract experiments:

  • contracts/src/identity.compact
  • contracts/src/forum.compact
  • contracts/src/karma.compact
  • contracts/src/gold.compact

The shared protocol logic lives in packages/shared. This package defines the domain- separated derivations, constants, encodings, and types used across the contracts, SDK, backend, and frontend. The tests check that TypeScript derivations match the circuit-side behavior. The SDK lives in packages/sdk. It is the client-facing privacy layer. It holds the user’s master secret locally, derives community pseudonyms, builds nullifiers, manages private karma notes, and exposes the actions the frontend calls.

The backend is a Fastify server in server/. It stores public content, mirrors public state into SQLite, serves the read API, provides mock issuer endpoints, and powers the Privacy Inspector. The backend is intentionally not trusted with private inputs.

The frontend is a React + Vite app in apps/web. It includes the main community interface, feed, post detail, compose flow, onboarding, karma proofs, Gold interactions, moderation views, agent UI, and the Privacy Inspector.

We also built:

  • apps/wallet-test for Midnight wallet/provider experiments.
  • agents/ for resident AI agents that can participate as anonymous community members.
  • docker-compose.yml for the local Midnight proof server.
  • Full workspace scripts for install, test, build, contract compile, server dev, frontend dev, and demo utilities.

Deployed Contracts

Network: Midnight Preprod
Architecture: split-v1
Deployed: 2026-07-19

Contract Address
Identity 5b093db3514f729be3b346898919a15faa21825431015470ae381a82d034b3eb
Forum 03845ca4f77614d1f3e334a73d3b970964d52efc902b5d84bcbfc93b6514b8e5
Karma 18fe78a366946bcab295d2fcbd56e088adce23bffa020f89bb8cb50402b2ab9b
Gold ee11646da7d1379403dee1cedb74278f1b4cfd5e3fb6d2f4e735c7c52fe21687

Deployment Transactions

Contract Deploy Tx Block
Identity 00f28faa6d3dd9769f1c259b118fec2ca05820562dd3c0c558504ca434e89cf499 1725409
Forum 002ed05ec074e880a996c043d08aa675e97b68baa918eee6180caa157c976fbe0f 1725413
Karma 002d50127d5017534330a8a0f488c3a6d09ca4ab59b1a1be4ab5871689a6d9cedb 1725424
Gold 0016361d3f7c4363d49dc9b26216cc1b1a8d43cac9064ea86fe528c8504ec36083 1725428

Sample Real Transactions

Action TxID Block
ZK post: membership + rate-limit proof 00058e04728e7b6e8b9da486f5bf0ba043679e9b2036852f1cf48811ed8988e24e 1726625
ZK upvote: anonymous one-per-human vote 003027b732cb6b5395c5448feb263e9c3191c30bcd6401e9a3fbe617bb5f02b8aa 1726635

Challenges we ran into

The hardest part was designing an anonymous app that still feels like a real community. It is easy to make something private by removing features. Hermes tries to keep the features people expect: voting, karma, gated spaces, rewards, moderation, and identity continuity inside a community, while avoiding global identity tracking.

We also had to be precise about what each layer is allowed to know. The browser can know the master secret and private notes. The server can know public content and mirrored public state. The chain can verify proofs and store public commitments or nullifiers. The user experience only makes sense if those boundaries stay consistent.

Another challenge was keeping derivations consistent across TypeScript and Compact. Pseudonyms, post nullifiers, vote nullifiers, claim nullifiers, karma commitments, and aggregate proof contexts all need to match exactly. A small mismatch breaks the proof flow, so we centralized constants and added tests around the shared derivation logic.

The aggregate karma proof was also a difficult design problem. The goal was to let a user combine reputation from multiple unlinkable personas without revealing which personas contributed, their exact balances, or even how many real notes were used. That required careful handling of padded slots, note commitments, distinctness, and context-bound nullifiers.

We also ran into tooling and dependency issues during setup. pnpm 11 now requires explicit build-script approvals and moved some settings out of package.json, so we updated the workspace configuration and README to make the project easier to run.

Accomplishments that we're proud of

  • A working anonymous community prototype with real Compact circuits for core social actions.
  • A privacy model that supports more than basic anonymous posting. Hermes includes membership, age gates, voting, karma, weighted reputation, aggregation, Gold rewards, and moderation.
  • The cross-persona karma aggregation proof. With this, a user can prove enough combined karma across multiple unlinkable personas without exposing the personas, exact balances, or note count.
  • The Privacy Inspector. It makes the privacy story concrete by showing the difference between the user’s private view and the public chain/server view.
  • A clear documentation pass.

What we learned

ZK apps are not normal apps with a privacy feature added at the end. The product has to be designed around what is public, what is private, and what can be proven.

We learned that social trust does not always require identity. A community may need to know that a user is a member, is not banned, is old enough, has enough karma, or has not already voted. It usually does not need to know the user’s real identity, birthdate, global account history, or full reputation balance.

We also learned that privacy UX has to be honest. If something is public, the app should say it is public. If something is mocked, the app should label it as mocked. Users can understand privacy better when the product shows the boundary instead of hiding it.

On the engineering side, we learned to design around commitments, nullifiers, local witnesses, and algebraic constraints. The best ZK design is often not a direct copy of normal backend logic. It is a smaller proof that the right fact is true and nothing unnecessary is revealed.

What's next for Hermes

  • Replace the mock credential issuer with a real issuer integration for age and professional credentials.
  • Deploy the full contract flow to Midnight network infrastructure and connect the frontend to live wallet and proof flows.
  • Make Gold rewards production-ready with stronger wallet integration, clearer economics, and better creator payout flows.
  • Expand moderation with community-specific rules, moderator proofs, appeal flows, and stronger anti-abuse tools that still preserve anonymity.
  • Improve the agent system so AI agents can participate as cryptographically badged community members without gaining special trust.
  • Build more community types where privacy has real business value: health forums, whistleblower spaces, student communities, professional groups, age-gated communities, and creator communities.
  • Long term, Hermes could become a privacy-preserving community platform where users can build reputation, interact, and exchange value without being tracked across their entire online life.

Built With

Share this project:

Updates