JellyCord is a small social app crafted to help you stay connected with friends and share your vibe. It includes:
- Web app built with Next.js App Router, Tailwind CSS v4, and Supabase for auth/data
- Dynamic OG image generation and a customizable public profile page
- Desktop app built with Electron + React with a simple WebRTC demo
- Lightweight Socket.IO signaling server (Bun) for peer-to-peer connectivity
.
├─ server/ # Go chat server (rooms/chat/JWT, Docker)
├─ cli/ # Go CLI chat client
├─ web/ # Next.js 16 app (React 19, Tailwind v4)
│ ├─ app/ # App Router pages, API routes, middleware
│ ├─ components/ # UI components (Radix UI, shadcn-style), utilities
│ └─ package.json
├─ desktop/ # Electron + React app (electron-vite)
│ ├─ src/ # main/preload/renderer
│ ├─ server/signaling/ # Socket.IO signaling server (Bun)
│ └─ package.json
└─ README.md
- Supabase OAuth login and session management
- Public profile with avatar, banner, links, color theme
- Status feed with CRUD API routes backed by Supabase tables
- OG image endpoint that renders profile metadata
- Tailwind CSS v4 theming with light/dark support
- Electron desktop app showcasing WebRTC (camera/microphone), uses signaling server
- Node.js 20+
- npm (or your preferred package manager)
- Supabase project (URL and anon key)
- Optional: Bun (for the signaling server in
desktop/server/signaling)
- Install dependencies:
cd web
npm install- Create
.env.localinweb/:
NEXT_PUBLIC_SUPABASE_URL=<your-supabase-url>
NEXT_PUBLIC_SUPABASE_ANON_KEY=<your-supabase-anon-key>
NEXT_PUBLIC_APP_URL=http://localhost:3000- Run the dev server:
npm run devThe app runs at http://localhost:3000.
Create the following tables in your Supabase project. Adjust types and constraints as you see fit.
-- profiles
create table if not exists public.profiles (
id uuid primary key references auth.users(id) on delete cascade,
username text unique,
name text,
bio text,
avatar text,
character text,
banner text,
primary_color text,
links jsonb
);
-- statuses
create table if not exists public.statuses (
id uuid primary key default gen_random_uuid(),
user_id uuid not null references public.profiles(id) on delete cascade,
content text,
mood text,
created_at timestamp with time zone default now()
);
-- Useful index for filtering by user
create index if not exists idx_statuses_user_id on public.statuses(user_id);- Install dependencies:
cd desktop
npm install- Start in development:
npm run dev- Typecheck and build:
npm run typecheck
npm run buildThe Electron app uses electron-vite and React. Source code lives under desktop/src.
The Electron WebRTC demo connects to a Socket.IO signaling server:
cd desktop/server/signaling
bun install
npm run start # or: bun run index.tsBy default, this server listens on http://localhost:3000. The Electron renderer connects to that URL.
Note: The web app also defaults to port 3000 in development. If you need both running simultaneously, run the web app on a different port:
cd web
PORT=3001 npm run devJellyCord includes a production-ready Go backend and a modern TUI (Terminal User Interface) client.
You can install the JellyCord CLI using several methods:
- Homebrew (macOS/Linux):
brew tap shayyz-code/tap brew install jellycord
- Scoop (Windows):
scoop bucket add jellycord https://github.com/shayyz-code/scoop-bucket scoop install jellycord
- Shell Installer (Universal):
- macOS/Linux:
curl -fsSL https://raw.githubusercontent.com/shayyz-code/jellycord/main/scripts/install-cli.sh | bash - Windows (PowerShell):
iex (irm https://raw.githubusercontent.com/shayyz-code/jellycord/main/scripts/install-cli.ps1)
- macOS/Linux:
- Go Install:
go install github.com/shayyz-code/jellycord/cli/cmd/jellycord@latest
Build both binaries locally:
make go-buildStart the server (automatically handles Redis via Docker):
make server-runThe server uses structured JSON logging (slog) and supports graceful shutdown. You can configure it via a .env file (see .env.example).
The Jellycord CLI is designed to be easily configurable. It looks for its configuration file in the following order of priority:
- Environment Variable:
JELLYCORD_CONFIG=/path/to/config.json - Home Directory:
~/.jellycord.json(macOS/Linux) or%USERPROFILE%\.jellycord.json(Windows) - Standard OS Config:
~/Library/Application Support/jellycord/config.json(macOS) or%AppData%\jellycord\config.json(Windows)
Example ~/.jellycord.json:
{
"server_url": "https://api.jellycord.com",
"token": "your-jwt-token-here",
"username": "your-username",
"last_room": "general"
}- Modern TUI: Built with Bubble Tea and Lipgloss for a polished chat experience.
- Slash Commands: Use
/helpin-app to see available commands like/clear,/whoami, and/exit. - Session Persistence: Automatically manages login tokens and room history.
- Auto-Login: Prompts for credentials if no session is found.
Deploy your own JellyCord instance to a VPS with one command:
make deployThis uses a push-based deployment system that synchronizes source code and configurations directly to your remote server.
- API routes (web):
/app/api/profile/route.ts– profile CRUD backed by Supabase/app/api/status/route.ts– status feed CRUD/app/api/og/route.tsx– dynamic OG image
- Auth:
/app/auth/callback/route.ts– Supabase OAuth code exchange and profile bootstrapmiddleware.ts+lib/middleware-utils.ts– session propagation for SSR
- Styling:
app/globals.css– Tailwind v4 tokens and theming
npm run dev– start Next.js dev servernpm run build– build for productionnpm run start– start production servernpm run lint– lint the codebase
npm run dev– start Electron in developmentnpm run build– build Electron appnpm run build:mac|win|linux– package for platformsnpm run typecheck– run TypeScript checksnpm run lint– lint the codebase
npm run start(via Bun) – start the Socket.IO server
- Web can be deployed to any Next-compatible host (e.g., Vercel). Set the environment variables used above.
- Ensure
NEXT_PUBLIC_APP_URLis set to your deployed origin for correct OG image and robots/sitemap URLs. - For the desktop auto-updater, see
desktop/electron-builder.ymlanddesktop/dev-app-update.yml.
- Prod compose:
docker-compose.prod.yml - Deploy config: copy
.env.deploy.exampleto.env.deployand set:JELLYCORD_VPS_IPJELLYCORD_BIND_IP(default127.0.0.1)JELLYCORD_HOST_PORT(default8080)
- Secrets: copy
.env.secrets.exampleto.env.secretsand set:JELLYCORD_JWT_SECRETJELLYCORD_ADMIN_KEY- Optional bootstrap admin:
JELLYCORD_BOOTSTRAP_ADMIN_USERNAMEJELLYCORD_BOOTSTRAP_ADMIN_PASSWORD
Run on VPS:
./scripts/vps-deploy.sh
cd ~/jellycord
cp .env.deploy.example .env.deploy
nano .env.deploy
cp .env.secrets.example .env.secrets
nano .env.secrets
docker compose --env-file .env.deploy -f docker-compose.prod.yml --env-file .env.secrets up -d --buildHealth and readiness checks:
curl -fsS http://127.0.0.1:${JELLYCORD_HOST_PORT:-8080}/livez
curl -fsS http://127.0.0.1:${JELLYCORD_HOST_PORT:-8080}/readyzCreate users easily as admin:
./jellycord admin create-user --server http://127.0.0.1:${JELLYCORD_HOST_PORT:-8080}This works with either:
--admin-key(orJELLYCORD_ADMIN_KEYenv var), or- a logged-in admin token from
./jellycord login
Open issues and pull requests are welcome. Please lint and typecheck before submitting changes.