Skip to content

Repository files navigation

PingMe

Realtime chat rooms with no signup and a visible ten-minute expiry.

Live demo · Architecture · Security policy

PingMe is a full-stack portfolio project built around a simple constraint: some conversations should be easy to start and intentionally short-lived. A participant creates a six-character room, shares the link, and chats through Redis-backed realtime events. The first join starts a server-backed ten-minute TTL shared by room metadata, membership, and messages.

What it demonstrates

  • End-to-end product flow across a Next.js client, typed Elysia API, Redis, and realtime delivery
  • Runtime validation with Zod at room, identity, message, and reaction boundaries
  • Per-room HTTP-only session cookies and server-bound display identities
  • TTL-based lifecycle management for pending and active rooms
  • Realtime messages, reactions, typing state, participant events, and room destruction
  • Responsive UI with keyboard focus, reduced-motion support, empty/loading/error states, and dark mode
  • Truthful privacy boundaries: temporary retention without claiming end-to-end encryption

User flow

  1. Create a room. PingMe stores pending metadata for up to one hour.
  2. Share the generated link or six-character code.
  3. The first participant joins and starts the ten-minute room timer.
  4. Participants exchange messages and reactions through realtime events.
  5. Redis TTLs remove room, membership, and message keys when time expires—or a participant closes the room early.

Architecture

Browser
  ├─ Next.js App Router UI
  ├─ TanStack Query cache
  └─ Upstash Realtime client
          │
          ▼
Typed Elysia routes (/api)
  ├─ Zod input contracts
  ├─ per-room HTTP-only auth cookie
  └─ server-bound temporary identity
          │
          ▼
Upstash Redis + Realtime
  ├─ meta:{roomID}
  ├─ members:{roomID}
  ├─ connected:{roomID}
  └─ messages:{roomID}
       shared active-room TTL

See ARCHITECTURE.md for data flow, key design, failure handling, and trade-offs.

Tech stack

  • Next.js 16, React 19, and TypeScript
  • Elysia for the API layer and a small typed fetch client for browser requests
  • TanStack Query for server-state orchestration
  • Upstash Redis and Upstash Realtime
  • Zod for runtime schemas
  • Tailwind CSS 4 and Framer Motion
  • Bun test, ESLint, and the TypeScript compiler

Run locally

Requirements: Node.js 20+ or Bun, plus an Upstash Redis database.

git clone https://github.com/marsh15/pingme.git
cd pingme
npm install
cp .env.example .env.local

Fill in the Redis URL and token in .env.local, then start the app:

npm run dev

Open http://localhost:3000.

Environment variables

Variable Required Purpose
UPSTASH_REDIS_REST_URL Yes Upstash Redis REST endpoint
UPSTASH_REDIS_REST_TOKEN Yes Upstash Redis REST credential
NEXT_PUBLIC_APP_URL Recommended Canonical deployment URL; use http://localhost:3000 locally

Legacy KV_REST_API_URL and KV_REST_API_TOKEN names are also accepted by the configuration validator.

Quality checks

npm test
npm run lint
npx tsc --noEmit
npm run build

The unit suite covers configuration fallbacks, room-code normalization, safe identity/message contracts, reaction allowlisting, and per-room cookie/key scoping.

Privacy and security boundary

PingMe reduces retention; it is not an end-to-end encrypted messenger. Messages are processed by the application and stored as plaintext in Redis until the room expires. A room code is an invitation, not a strong access-control secret. Do not use PingMe for credentials, payment data, medical information, or other sensitive content.

Security-relevant implementation details:

  • The browser never receives membership tokens in message history or realtime payloads.
  • A server-side room membership record binds each token to one temporary display name.
  • Each room uses a separate HTTP-only, SameSite=Lax cookie.
  • API schemas trim and bound message content and allowlist reactions.
  • Active keys receive the remaining server-side room TTL.

See SECURITY.md for reporting guidance and known limitations.

Deliberate trade-offs

  • Redis lists keep the implementation compact, but reaction/delete updates are O(n) scans and are suited to small rooms.
  • The 50-person limit is a product guardrail, not a distributed rate limit.
  • Delivery is realtime but not guaranteed; clients refetch canonical message history after events.
  • Temporary deletion relies on Redis TTL guarantees and application-level delete requests, not cryptographic erasure.

License

MIT

About

PingMe is a privacy first real time chat application for instant, anonymous conversations. Create temporary rooms, share a link, and communicate no signup required.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages