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
.
├─ 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 dev- 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.
Open issues and pull requests are welcome. Please lint and typecheck before submitting changes.