Skip to content

Arobce/ghost-terminal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GHOST TERMINAL

An anonymous, encrypted real-time chat platform styled like an old-school command terminal. Create secret rooms, share invite codes, pick a handle, and communicate with end-to-end style encryption. The server never sees your messages.

Ghost Terminal landing screen

Motivation

Traditional chat apps require accounts, store messages in plaintext, and track user data. Ghost Terminal flips that — no sign-ups, no accounts, no plaintext storage. Just an invite code and a handle. Messages are encrypted on your device before they ever leave the browser.

Built as a capstone project demonstrating Singleton, Repository, and Service Layer architectural patterns with real-time WebSocket communication and client-side encryption.

Tech Stack

Layer Technology
Backend Express.js (Node.js)
Database MongoDB (Atlas)
Real-Time Socket.io
Frontend React (Vite)
Encryption AES-256-GCM (Web Crypto API)
Security Helmet, CORS, express-rate-limit
Validation express-validator
Hashing bcryptjs

Architecture

Client (React + Vite)
    │
    ├── REST API (axios)
    │
    └── WebSocket (Socket.io-client)
                │
                ▼
          Express.js Server
                │
       Routes → Controllers → Services → Repositories → MongoDB
                │
          Socket.io Handler ──→ Services → Repositories → MongoDB

Design Patterns

  • Singleton — Single MongoDB connection instance shared across the app (config/db.js)
  • Repository — All database operations isolated in repository classes. No other layer touches MongoDB directly.
  • Service Layer — All business logic lives in services. Controllers are thin request/response handlers.

Features

  • Create encrypted chat rooms with auto-generated 6-character invite codes
  • Join rooms via invite code — no account required
  • Real-time messaging via Socket.io
  • AES-256-GCM encryption — messages encrypted client-side, stored encrypted, decrypted client-side
  • Message history loaded and decrypted on room join
  • Room expiry with auto-deletion (TTL index)
  • Optional room password (bcrypt hashed)
  • Typing indicators and online user list
  • Copy invite code to clipboard
  • Matrix/hacker terminal UI — scanlines, glitch text, screen flicker, neon glow

Screenshots

Landing Screen

Ghost Terminal landing screen

Chat Room

Ghost Terminal chat room

Setup

Prerequisites

  • Node.js (v18+)
  • MongoDB (local or Atlas)

1. Clone the repository

git clone <repo-url>
cd ghost-terminal

2. Server setup

cd server
cp .env.example .env

Edit .env with your MongoDB connection string:

PORT=3001
MONGODB_URI=mongodb+srv://<username>:<password>@<cluster>.mongodb.net/?retryWrites=true&w=majority
DB_NAME=ghost_terminal
CORS_ORIGIN=http://localhost:5173
NODE_ENV=development

Install and run:

npm install
npm run dev

3. Client setup

cd client

The .env file should contain:

VITE_API_URL=http://localhost:3001/api
VITE_SOCKET_URL=http://localhost:3001

Install and run:

npm install
npm run dev

The app will be available at http://localhost:5173.

API Documentation

Rooms

Method Endpoint Description
POST /api/rooms Create a new room
POST /api/rooms/join Join a room via invite code
GET /api/rooms/:id Get room info and participants
DELETE /api/rooms/:id Delete a room (creator only)

Messages

Method Endpoint Description
GET /api/messages/:roomId Get message history (paginated)
DELETE /api/messages/:roomId Purge all messages in a room

Example Requests

Create Room:

POST /api/rooms
{
  "roomName": "Operation Midnight",
  "creatorHandle": "neo",
  "password": "optional",
  "expiresInHours": 24
}

Join Room:

POST /api/rooms/join
{
  "inviteCode": "X7K9M2",
  "handle": "trinity",
  "password": "optional"
}

Socket.io Events

Client → Server

Event Payload Description
join_room { roomId, handle } Enter a chat room
leave_room { roomId, handle } Leave a chat room
send_message { roomId, handle, encryptedContent } Send encrypted message
typing { roomId, handle } Typing indicator on
stop_typing { roomId, handle } Typing indicator off

Server → Client

Event Payload Description
new_message { _id, handle, encryptedContent, timestamp } New message in room
user_joined { handle, participants } User entered room
user_left { handle, participants } User left room
user_typing { handle } Show typing status
user_stop_typing { handle } Hide typing status

Encryption

Messages are encrypted using AES-256-GCM via the browser's Web Crypto API.

  1. An encryption key is derived from inviteCode + roomId using PBKDF2 (SHA-256, 100,000 iterations)
  2. Each message is encrypted with a random 12-byte IV
  3. The IV and ciphertext are combined and base64 encoded
  4. The server stores and transmits only the base64 ciphertext
  5. Receiving clients derive the same key and decrypt locally

The server never has access to plaintext messages or encryption keys.

Project Structure

ghost-terminal/
├── client/                          # React frontend (Vite)
│   ├── src/
│   │   ├── components/
│   │   │   ├── Terminal.jsx         # Main terminal wrapper
│   │   │   ├── ChatRoom.jsx        # Active chat view
│   │   │   ├── JoinRoom.jsx        # Create/join room screen
│   │   │   ├── MessageList.jsx     # Message display
│   │   │   ├── MessageInput.jsx    # Terminal-style input
│   │   │   ├── RoomHeader.jsx      # Room info bar
│   │   │   ├── Scanlines.jsx       # CRT overlay effect
│   │   │   └── GlitchText.jsx      # Glitch animation
│   │   ├── hooks/
│   │   │   ├── useSocket.js        # Socket.io connection
│   │   │   └── useEncryption.js    # Encrypt/decrypt hook
│   │   ├── utils/
│   │   │   ├── crypto.js           # AES-256-GCM helpers
│   │   │   └── api.js              # REST API wrapper
│   │   └── styles/
│   │       └── terminal.css        # Terminal theme
│   └── package.json
│
├── server/                          # Express.js backend
│   ├── src/
│   │   ├── config/
│   │   │   ├── db.js               # Singleton DB connection
│   │   │   ├── env.js              # Environment config
│   │   │   └── socket.js           # Socket.io setup
│   │   ├── controllers/            # Request/response handlers
│   │   ├── services/               # Business logic
│   │   ├── repositories/           # MongoDB operations
│   │   ├── routes/                 # API route definitions
│   │   ├── middleware/             # Error handler, validation, rate limit
│   │   ├── validators/            # Input validation schemas
│   │   ├── socket/
│   │   │   └── chatHandler.js      # Real-time event handlers
│   │   └── utils/                  # AppError, code generator
│   ├── server.js                   # Entry point
│   └── package.json
│
├── .gitignore
└── README.md

Known Limitations

  • Encryption key is derived from the invite code — anyone with the code can decrypt messages
  • No persistent user authentication — handles are per-session
  • No message editing or deletion for individual messages
  • Room creator verification for deletion relies on the handle string
  • No file/image sharing support

Future Improvements

  • Matrix rain canvas background animation
  • Message self-destruct (auto-delete after read)
  • Room theme options (amber, blue, classic green)
  • Export chat as .txt terminal log
  • Bot commands (/clear, /users, /info)
  • Sound effects on message send (toggleable)
  • End-to-end encryption with public/private key pairs instead of shared secret

About

An anonymous, encrypted real-time chat platform styled like an old-school command terminal.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors