Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 0 additions & 30 deletions ;q

This file was deleted.

277 changes: 125 additions & 152 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,165 +1,138 @@
# OpenChat (monorepo)

This repository contains a small monorepo with a frontend (Next + React), a backend (Express + Socket.io,Prisma), and shared packages (`@openchat/lib`, `@openchat/components`).

This README explains how to get the project running locally and developer recommendations.

Requirements

# Node.js: >= 20.19 (recommended 20.x). A `.nvmrc` file is included for convenience.
# OpenChat (monorepo)

This repository contains a monorepo for OpenChat:

- `apps/frontend` — Next + React client
- `apps/backend` — Express + Socket.io server (with Prisma schema)
- `packages/lib` — shared utilities (helpers, socket client)
- `packages/components` — shared UI components

This README covers how to set up the project locally, common workflows for developing across the workspace, and troubleshooting tips.

## Requirements

- Node.js: >= 20.x (20.x recommended). Use `nvm` to manage Node versions — a `.nvmrc` is included.
- pnpm: v7+ (workspace-aware). Install with `npm i -g pnpm` if needed.

## Quick setup

1. Use the recommended Node version:

```bash
nvm install 20
nvm use 20
node -v # should be >= 20.x (20.x recommended)
```

2. Install dependencies (from repo root):

```bash
pnpm install
```

3. Run development servers:

```bash
pnpm run dev # runs frontend + backend concurrently (defined in root package.json)
# or run individually
pnpm dev:frontend
pnpm dev:backend
```

Open the frontend URL printed by Vite (typically http://localhost:3000). The backend listens on port 4000 by default.

## Environment variables

- `NEXT_SOCKET_URL` — frontend socket URL (default: `http://localhost:4000`). Use this in `.env` at the frontend root if needed.
- `PORT` or `SOCKET_PORT` — backend port (default: `4000`).

Create an `.env` file in `apps/frontend` or `apps/backend` for local overrides when needed.

## Building

To build all packages and apps in the workspace:

```bash
pnpm build
# 🚀 OpenChat

**The Ultimate Real-Time Chat & Voice Platform.**
A high-performance monorepo featuring non-blocking voice calls, persistent sessions, and a premium messaging experience.

---

## ✨ Key Features

- **🛡️ Production-Ready Voice Calling**:
- Robust WebRTC & Socket.io signaling.
- **Non-Blocking Floating UI**: Keep chatting while on a call.
- **Server-Side Persistence**: Refresh the page? No problem. The call automatically reconnects.
- **Graceful Disconnects**: 10-second grace period for network drops.
- **💬 Real-Time Messaging**: Instant delivery via Socket.io with typing indicators and read receipts.
- **📁 Zone-Based Communities**: Organize chats into Discord-style "Zones" with dedicated text and voice channels.
- **🔐 Secure Authentication**:
- JWT + HTTP-only Cookie authentication.
- Google OAuth integration.
- Email verification system.
- **🎨 Premium UI/UX**:
- Dark-mode first, glassmorphic design.
- Smooth micro-animations powered by Framer Motion.
- Responsive, compact floating call overlays.
- **⚙️ Integrated Settings**:
- Profile management (Avatar upload/removal, bio, username).
- Account security and notifications.

---

## 🛠️ Technology Stack

| **Component** | **Technologies** |
| :--- | :--- |
| **Frontend** | [Next.js 15](https://nextjs.org/) (Turbopack), [React 19](https://react.dev/), [Tailwind CSS](https://tailwindcss.com/), [Zustand](https://zustand-demo.pmnd.rs/), [Framer Motion](https://www.framer.com/motion/) |
| **Backend** | [Node.js](https://nodejs.org/), [Express](https://expressjs.com/), [Socket.io](https://socket.io/), [Prisma ORM](https://www.prisma.io/) |
| **Database** | [PostgreSQL](https://www.postgresql.org/) |
| **Real-Time** | WebRTC (PeerConnection API), Socket.io |
| **Monorepo** | [pnpm Workspaces](https://pnpm.io/workspaces) |

---

## 🚀 Getting Started

### Prerequisites

- **Node.js** >= 20.x
- **pnpm** >= 9.x
- **PostgreSQL** instance

### Setup

1. **Clone & Install**:
```bash
git clone https://github.com/your-username/openchat.git
cd openchat
pnpm install
```

2. **Environment Configuration**:
Create `.env.local` files in both `apps/frontend` and `apps/backend` (or use the root `.env.local` for shared values).

**Backend (`apps/backend/.env`):**
```env
DATABASE_URL="postgresql://user:password@localhost:5432/openchat"
JWT_SECRET="your_secret_key"
CLIENT_URL="http://localhost:3000"
BASE_URL="http://localhost:4000"
```

**Frontend (`apps/frontend/.env.local`):**
```env
NEXT_PUBLIC_API_URL="http://localhost:4000"
NEXT_PUBLIC_GOOGLE_CLIENT_ID="your_google_id"
```

3. **Database Migration**:
```bash
cd apps/backend
pnpm prisma generate
pnpm prisma migrate dev
```

4. **Run Development Mode**:
From the project root:
```bash
pnpm dev
```
- Frontend: `http://localhost:3000`
- Backend: `http://localhost:4000`

---

## 🏗️ Project Structure

```text
├── apps/
│ ├── frontend/ # Next.js Application (Client)
│ └── backend/ # Express & Socket.io Server
├── packages/
│ ├── components/ # Shared shadcn/ui components
│ ├── lib/ # Shared utilities & API clients
│ └── types/ # Shared TypeScript interfaces
├── pnpm-workspace.yaml # Workspace configuration
└── README.md # You are here!
```

To build a single package/app (example frontend):

```bash
pnpm --filter frontend build
```

## Prisma (backend)

If you change the Prisma schema (`apps/backend/prisma/schema.prisma`) apply migrations locally with:

```bash
cd apps/backend
npx prisma migrate dev
```

Or generate clients only:

```bash
npx prisma generate
```

## Working with shared packages (developer workflow)

- Import shared code using the workspace package names, e.g.:

```ts
import { cn, socket } from '@openchat/lib'
import { Button } from '@openchat/components'
```

- During development, the Vite config and TypeScript path mappings resolve those imports to the local `src/` folders so you can edit packages in place.

- When editing a package (`packages/lib` or `packages/components`), run that package's build (or run the workspace build) so consuming apps get the latest `dist/` outputs when necessary:

```bash
pnpm --filter @openchat/lib build
pnpm build
```

## Clean generated sources

- Avoid committing generated JS inside `src/` of packages. Only `dist/` should contain build artifacts.
- The repo includes clean scripts in packages to remove stray `.js` in `src` before building. To run all clean scripts:

```bash
pnpm run clean
```

## Common tasks & useful commands

- Install dependencies: `pnpm install`
- Start frontend dev: `pnpm --filter frontend dev`
- Start backend dev: `pnpm --filter backend dev`
- Start both: `pnpm run dev`
- Build everything: `pnpm build`
- Run workspace tests (if any): `pnpm test`

## Troubleshooting

-- If Vite fails with Node crypto errors, you're likely on an unsupported Node version. Switch to Node 20.x:

```bash
nvm install 20
nvm use 20
```

- If shared imports resolve incorrectly, verify `tsconfig.json` `paths` and `apps/frontend/next.config.js` aliases are present. They map `@openchat/*` to the packages' `src` folders.

- If Tailwind styles don't appear in a consuming app, check PostCSS configuration and ensure `@tailwind` and `@import` ordering is correct in the app's `globals.css`.
---

## Publishing packages
## 📡 Voice Call Architecture

- If you plan to publish packages, add an `exports` field to each package's `package.json` and produce both ESM and CJS outputs in the build. For internal development the TypeScript path mappings and Vite aliases are sufficient.
OpenChat uses a custom-built WebRTC signaling state machine:

## How to add a new package/app
1. **Initiation**: Client A emits `call:user` via Sockets.
2. **Tracking**: Backend stores call metadata in an `activeCalls` Map for persistence.
3. **Offer/Answer**: WebRTC `RTCPeerConnection` handshake occurs through Socket.io.
4. **ICE Candidates**: Network candidates are queued and drained only after the remote description is set to ensure 100% connection success.
5. **Reconnection**: If Client B refreshes, they emit `call:check`. The server provides the current call state, allowing Client B to re-mount the `GlobalCallProvider` and re-negotiate the stream.

1. Create a new folder under `apps/` or `packages/`.
2. Add a `package.json` with the workspace name (e.g. `@openchat/yourpkg`).
3. Add TypeScript sources under `src/` and update root `pnpm build` if needed.
4. Add path mappings in the root `tsconfig.json` if you want to import it by package name during dev.
---

## CI
## 🤝 Contributing

This repository does not include any CI/workflow configuration by default. If you want CI, I can add a GitHub Actions workflow that uses Node 20 and runs builds, linting, and tests.
1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the Branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request

## Need help?
---

If you'd like, I can:
## 📄 License

- Remove remaining generated JS files under `src/` across the repo and add `prebuild` scripts to enforce a clean source tree.
- Add `exports` fields to all `package.json` files and produce ESM+CJS builds.
- Integrate Tailwind + shadcn into `apps/frontend` (or add it to other apps) and wire workspace imports for UI components.
Distributed under the **MIT License**. See `LICENSE` for more information.

Tell me which of the above you'd like next and I will implement it.
---

## License
MIT License © 2025 OpenChat
Original author and project owner.
**Built with ❤️ by the OpenChat Team.**
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
-- AlterTable
ALTER TABLE "Chat" ADD COLUMN "zoneId" INTEGER;

-- CreateTable
CREATE TABLE "Zone" (
"id" SERIAL NOT NULL,
"publicId" TEXT NOT NULL,
"name" TEXT NOT NULL,
"avatar" TEXT,
"description" TEXT,
"ownerId" INTEGER NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,

CONSTRAINT "Zone_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "ZoneMember" (
"id" SERIAL NOT NULL,
"zoneId" INTEGER NOT NULL,
"userId" INTEGER NOT NULL,
"role" "ZoneRole" NOT NULL DEFAULT 'MEMBER',
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

CONSTRAINT "ZoneMember_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "Zone_publicId_key" ON "Zone"("publicId");

-- CreateIndex
CREATE UNIQUE INDEX "ZoneMember_zoneId_userId_key" ON "ZoneMember"("zoneId", "userId");

-- AddForeignKey
ALTER TABLE "Chat" ADD CONSTRAINT "Chat_zoneId_fkey" FOREIGN KEY ("zoneId") REFERENCES "Zone"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "Zone" ADD CONSTRAINT "Zone_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "ZoneMember" ADD CONSTRAINT "ZoneMember_zoneId_fkey" FOREIGN KEY ("zoneId") REFERENCES "Zone"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "ZoneMember" ADD CONSTRAINT "ZoneMember_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
Loading