GhostLink

GhostLink: Anonymous, E2EE chat with direct crypto payments, built for World App.

GhostLink

Created At

ETHGlobal New Delhi

Winner of

World

World - Best Mini App Honorable Mention

Project Description

GhostLink is a secure, privacy-first chat app built as a World App Mini App. The whole point is anonymous conversations and direct wallet-to-wallet payments, with end-to-end encryption handled entirely on the client. The server never sees message content it just routes ciphertext.

Core Principles: Pseudonymous identity: no email, no phone. Your wallet address is your identity. Sign-in happens through the Worldcoin MiniKit. Once you’re in, you pick a public username that’s shown in the app. End-to-end encryption (E2EE): everything is encrypted before it leaves your device. Only the recipient can decrypt. The server just stores gibberish.

How Encryption Works • On first use, the browser generates an ECDH key pair and keeps the private key in localStorage. • The public key is uploaded to the server so others can fetch it. • When two people start a chat, each combines their private key with the other’s public key to derive the same shared secret—never transmitted anywhere. • That shared key is used with AES-GCM to encrypt/decrypt messages.

Features • Realtime chat powered by WebSockets. All channels are private and authenticated. • Friend system you add people by username. Requests are pushed live; once accepted, you can chat. • In chat crypto payments: integrated with Worldcoin MiniKit. You hit “Pay,” enter amount, and it executes from your World App wallet. The server just logs a confirmation string like PAYMENT::Sent 1 WLD. Profiles username plus optional profile picture (UploadThing).

How it's Made

GhostLink is privacy-first, server-agnostic by design. The server only routes encrypted data and stores user directories. It never sees message content. Everything else is engineered around that principle.

Architectural Foundation: Next.js + TypeScript

The app is a single Next.js 15 App Router project, fully in TypeScript. • Server Actions are the core backend mechanism. Sending a message or adding a friend is just a direct call to a secure server function—no REST layer. • TypeScript runs end-to-end, from Drizzle schemas to React components. With cryptographic data and complex payloads, type safety was non-negotiable.

Data Layer: Drizzle + Neon (Postgres)

Schema lives in one place. Drizzle generates typed clients off that schema, so all DB operations inside Server Actions are checked at build time. That removes most runtime query errors. Neon provides Postgres as a serverless, scalable backend.

Real-time: Pusher

Real-time state comes from Pusher. A Server Action writes to the DB, then triggers a server-side Pusher client to emit events. The frontend listens on private channels (authenticated through a small API route). It’s instant sync without maintaining our own WebSocket infra.

Partner Tech: Worldcoin MiniKit + Mainnet

MiniKit bridges GhostLink to real wallets, providing identity and payments.

Identity & Auth

Login uses walletAuth, a SIWE flow. The client requests a nonce, the World App signs it, and the server verifies. This is off-chain—no gas, no transaction—but the signature proves control of a real mainnet address. That wallet is the user’s identity.

Payments

Inside a chat, pay is called with recipient, amount, and token. The World App executes an on-chain transfer: a real transaction signed and broadcasted to the network. GhostLink never touches private keys or RPC calls. After confirmation, the server logs a neutral chat message like PAYMENT::Sent 1 WLD.

This makes GhostLink web3-native without handling custody, fees, or chain logic itself.

Client-Side End-to-End Encryption

All encryption is orchestrated in the browser. 1. On first load, Web Crypto generates an ECDH key pair. Private key stays in localStorage. 2. The public key is uploaded so others can fetch it. 3. When you open a chat, your private key + their public key = a shared secret, never transmitted. 4. That shared secret becomes the AES-GCM key for encrypting and decrypting messages.

The server only ever sees opaque ciphertext. Key management, derivation, and message crypto all happen on the client.

That’s GhostLink in full: Next.js + TS for a unified app, Drizzle + Neon for type-safe persistence, Pusher for live updates, MiniKit for mainnet identity and payments, and Web Crypto for true client-side E2EE. The server is deliberately dumb.

background image mobile

Join the mailing list

Get the latest news and updates