diff --git a/README.md b/README.md
index 73993cc..948bde5 100644
--- a/README.md
+++ b/README.md
@@ -1,76 +1,148 @@
-# VibeXCode
+# VibeXcode
-**VibeXCode** is a modern, collaborative group chat and forum platform built using **Next.js**, **Tailwind CSS**, **Socket.IO**, **MongoDB**, and **Appwrite**. It supports real-time messaging, image sharing, and authentication with both Appwrite and Firebase (including social login options).
+A developer community platform โ real-time forum chat, a multi-language code playground, leaderboards, and a Q&A space โ built on Next.js 15.
-## ๐ Features
+**Live:** https://vibexcode.netlify.app
-- ๐ User Authentication with Appwrite & Firebase
-- ๐ฌ Real-time group chat using Socket.IO
-- ๐ผ๏ธ Image sharing support
-- ๐ Light and Dark mode UI
-- ๐ค Editable user profiles (name, email)
-- ๐งโ๐ป Developer-friendly tech stack
-- ๐ฑ Responsive design
+---
+
+## Stack
+
+| Layer | Choice | Why |
+| --- | --- | --- |
+| Framework | Next.js 15 (App Router) + React 19 | File-based routing, server components for SEO/metadata, API routes in the same project โ one deploy, no CORS |
+| Language | TypeScript | The frontend/backend contract is the riskiest surface; type-checking catches it at compile time |
+| Styling | Tailwind 4 | Small bundle, no custom CSS, fast iteration |
+| State | Redux Toolkit | Centralizes auth and theme state shared across pages |
+| Editor | Monaco (`@monaco-editor/react`) | Same engine as VS Code, multi-language, familiar to devs |
+| Auth | Firebase Auth | Mature social-login flows (Google/GitHub/Facebook) and email/password without me handling tokens or password hashing |
+| DB | MongoDB Atlas + Mongoose | Document model fits chat messages, submissions, and user profiles; Mongoose layers schemas + validation on top |
+| Code execution | Judge0 (RapidAPI) | Sandboxes user code in containers โ submissions never run on our infrastructure |
+| Real-time | Socket.IO (dev) / pluggable | Rooms keyed by conversation ID; messages also persisted to Mongo so refresh shows history (see "Known issues" for the deploy-time caveat) |
+| Hosting | Netlify | Static + serverless functions, generous free tier |
---
-## ๐ธ Screenshots
+## What's interesting
-### ๐ Main Page โ Light Mode
+The features are conventional. The decisions inside them are where the depth lives.
-
+### Code execution: never on our servers
+The playground compiles user code in **Judge0**, an external sandbox. Flow:
-### ๐ Main Page โ Dark Mode
+1. Client `POST /api/judge0/submit` with source + language ID
+2. Our route forwards to RapidAPI's Judge0 endpoint, returns a `token`
+3. Client polls `/api/judge0/result/` until `status.id > 2` (completed)
+4. UI renders stdout / stderr / time / memory
-
+If a user submits malicious code, the blast radius is their own Judge0 container โ not our app. The trade-off is network latency (typically 1โ4 s) and an external dependency. The polling is a known limitation; webhook callback would be better and is a planned change.
+### Real-time chat with persistent history
-### ๐ Dashboard Page
+Each conversation has an ID. On open, the client joins a Socket.IO room keyed by that ID. New messages emit only to that room **and** are persisted to the `Message` collection in Mongo, so a refresh re-fetches history without missing anything sent in-flight. Real-time without persistence is amnesia; persistence without real-time is polling. You need both.
-
+### Auth: one source of truth
+Firebase handles auth end-to-end. An earlier version of this codebase ran Appwrite + Firebase in parallel, which was a real production wart (Appwrite Cloud's free tier auto-pauses after a week of inactivity โ red 403s on every page that called `authservice.checkUser()`). The current code uses Firebase only; the legacy `authservice` interface is preserved as a Firebase-backed shim so the consolidation didn't ripple through every page.
-### ๐ค Profile Page
+### Page metadata, properly
-
+Root layout exports rich Open Graph + Twitter card metadata + canonical URL, with a per-route `title` template (`Playground ยท VibeXcode`). Each major route has its own minimal `layout.tsx` that overrides title/description so link previews and search results are page-accurate, not site-default.
+---
+## Project structure
+
+```
+.
+โโโ app/
+โ โโโ layout.tsx # Root layout, full SEO metadata
+โ โโโ page.tsx # Landing
+โ โโโ api/ # Next.js API routes (REST)
+โ โ โโโ judge0/ # Submit + poll for code execution
+โ โ โโโ messages/ # Chat history
+โ โ โโโ questions/ # Q&A questions
+โ โ โโโ submit/ # Solution submissions
+โ โ โโโ tasks/ # Personal todos
+โ โ โโโ ...
+โ โโโ playground/ # Monaco editor + Judge0 flow
+โ โโโ community/, Forums/ # Real-time chat
+โ โโโ Dashboard/, Profile/ # User-scoped views
+โ โโโ Leaderboards/ # Top performers
+โ โโโ login/, signup/ # Auth flows (Firebase)
+โ โโโ appwrite/auth.ts # Firebase-backed auth service (legacy folder name)
+โ โโโ components/ # Shared UI
+โโโ lib/
+โ โโโ firebase.ts # Firebase client init
+โ โโโ mongodb.ts # Lazy Mongoose connection
+โ โโโ judge0.ts # Submit + poll wrapper
+โ โโโ useSocket.ts # Socket.IO React hook
+โโโ models/ # Mongoose schemas
+โ โโโ Users.ts
+โ โโโ Messages.ts
+โ โโโ Questions.ts
+โ โโโ Submissions.ts
+โ โโโ Tasks.ts
+โโโ pages/api/socketio.ts # Pages-router Socket.IO server (legacy; see "Known issues")
+โโโ public/
+```
---
-## โ๏ธ Tech Stack
+## Running locally
+
+Requirements: **Node โฅ 18**.
+
+```bash
+git clone https://github.com/Valkyriezz/VibexCode.git
+cd VibexCode
+npm install
+cp .env.example .env.local # then fill in the values
+npm run dev # http://localhost:3000
+```
+
+`.env.local` needs (see `.env.example` for the full list):
-- **Frontend**: Next.js, Tailwind CSS
-- **Real-time Communication**: Socket.IO
-- **Authentication**: Appwrite, Firebase
-- **Database**: MongoDB
-- **Deployment**: Vercel / Netlify / Custom
+- `MONGODB_URI` โ MongoDB Atlas or local
+- `RAPIDAPI_KEY` โ Judge0 (Run button fails with 401 without this)
+- Firebase web SDK config (`NEXT_PUBLIC_FIREBASE_*`)
+
+Build the production bundle and serve it:
+
+```bash
+npm run build
+npm start
+```
---
-## ๐ Getting Started
+## Deploying
-### Prerequisites
+The app is deploy-target-agnostic. Configure the env vars above on the host and `npm run build` works. Netlify is the current target (auto-builds on push to `main`, ~2 min).
-- Node.js โฅ 18
-- MongoDB (local or Atlas)
-- Appwrite project & API keys
-- Firebase setup (for optional social login)
+---
-### Setup
+## Known issues / what's next
-```bash
-# Clone the repo
-git clone https://github.com/yourusername/vibexcode.git
-cd vibexcode
+- **Real-time chat on serverless.** `pages/api/socketio.ts` requires a long-lived process. Netlify Functions are short-lived, so the deployed `/api/socketio` route returns 500. Local dev is fine. Fix is to migrate to a managed real-time service (Pusher / Ably) or move the host to Render/Railway.
+- **Judge0 polling.** Polling every second up to 10 attempts is brittle for slow programs. Webhook callback is the right answer โ Judge0 supports it on paid tiers.
+- **Reset password URL.** With Firebase, the reset email carries `oobCode` instead of Appwrite's `userId`+`secret`. The `/resetPassword` page still reads the legacy params; needs updating.
+- **No automatic DB migrations.** Mongo schemas are defined inline; for v2 a `_migrations` collection + numbered scripts would be the right shape.
+- **No rate limiting.** API routes are open. Realistic to add via `@vercel/edge` or middleware before scale.
+- **No tests for the chat layer.** API route tests for Judge0 are planned.
-# Install dependencies
-npm install
+---
+
+## Things I intentionally did *not* build
+
+- A heavyweight design system (MUI etc.). Tailwind keeps the bundle small and review attention on the logic.
+- Per-tenant auth / multi-org. Single-tenant by design; a real product would need this.
+- A separate frontend host. One URL is simpler to operate; we can split later if traffic justifies it.
+- Premature abstractions (repository pattern, service layer, DI containers). At this size they cost more than they save.
+
+---
-# Create and configure .env.local
-cp .env.example .env.local
-# Fill in Appwrite, Firebase, and MongoDB credentials
+## Why these trade-offs
-# Run the development server
-npm run dev
+The brief I built this against valued **depth and production-readiness over breadth of features**. The visible features (chat, playground, forum, leaderboard) are conventional. The interesting parts are the seams: how user code is sandboxed, how auth was consolidated, how chat persistence and real-time delivery share the same data path, how metadata is structured. Where I cut a corner I tried to leave a clean seam (`Known issues` above) so the next iteration is small.
diff --git a/app/Dashboard/layout.tsx b/app/Dashboard/layout.tsx
new file mode 100644
index 0000000..cbdf488
--- /dev/null
+++ b/app/Dashboard/layout.tsx
@@ -0,0 +1,15 @@
+import type { Metadata } from "next";
+
+export const metadata: Metadata = {
+ title: "Dashboard",
+ description:
+ "Your VibeXcode dashboard โ solved questions, personal todos, leaderboard standing, and community at a glance.",
+};
+
+export default function DashboardLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return <>{children}>;
+}
diff --git a/app/Forums/layout.tsx b/app/Forums/layout.tsx
new file mode 100644
index 0000000..8dee938
--- /dev/null
+++ b/app/Forums/layout.tsx
@@ -0,0 +1,15 @@
+import type { Metadata } from "next";
+
+export const metadata: Metadata = {
+ title: "Forums",
+ description:
+ "Real-time topic forums on dev, competitive programming, Python, games, and general โ chat with the VibeXcode community.",
+};
+
+export default function ForumsLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return <>{children}>;
+}
diff --git a/app/Leaderboards/layout.tsx b/app/Leaderboards/layout.tsx
new file mode 100644
index 0000000..ebc70a7
--- /dev/null
+++ b/app/Leaderboards/layout.tsx
@@ -0,0 +1,15 @@
+import type { Metadata } from "next";
+
+export const metadata: Metadata = {
+ title: "Leaderboards",
+ description:
+ "See who's solving the most questions and holding the longest streaks on VibeXcode.",
+};
+
+export default function LeaderboardsLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return <>{children}>;
+}
diff --git a/app/Profile/layout.tsx b/app/Profile/layout.tsx
new file mode 100644
index 0000000..8aafa47
--- /dev/null
+++ b/app/Profile/layout.tsx
@@ -0,0 +1,15 @@
+import type { Metadata } from "next";
+
+export const metadata: Metadata = {
+ title: "Profile",
+ description:
+ "Your VibeXcode profile โ solved questions, statistics, current streak, and preferences.",
+};
+
+export default function ProfileLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return <>{children}>;
+}
diff --git a/app/community/layout.tsx b/app/community/layout.tsx
new file mode 100644
index 0000000..bbb0738
--- /dev/null
+++ b/app/community/layout.tsx
@@ -0,0 +1,15 @@
+import type { Metadata } from "next";
+
+export const metadata: Metadata = {
+ title: "Community",
+ description:
+ "Join the VibeXcode community โ collaborative chat rooms scoped per conversation, with persistent history.",
+};
+
+export default function CommunityLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return <>{children}>;
+}
diff --git a/app/layout.tsx b/app/layout.tsx
index 5c5feed..aef9626 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -18,10 +18,56 @@ const geistMono = Geist_Mono({
subsets: ["latin"],
});
+const SITE_URL =
+ process.env.NEXT_PUBLIC_APP_URL || "https://vibexcode.netlify.app";
+const SITE_NAME = "VibeXcode";
+const SITE_TITLE = "VibeXcode โ A collaborative way to vibe and code";
+const SITE_DESCRIPTION =
+ "VibeXcode is a developer community platform with real-time forum chat, a multi-language code playground powered by Judge0, leaderboards, and a collaborative Q&A.";
+
export const metadata: Metadata = {
- title: "VibeXcode - A collaborative way to vibe and code!!",
- description:
- "VibeXcode is a developer community platform with real-time chat, a multi-language code playground powered by Judge0, and a collaborative Q&A forum.",
+ metadataBase: new URL(SITE_URL),
+ title: {
+ default: SITE_TITLE,
+ template: "%s ยท VibeXcode",
+ },
+ description: SITE_DESCRIPTION,
+ keywords: [
+ "VibeXcode",
+ "coding playground",
+ "collaborative coding",
+ "developer community",
+ "code execution",
+ "Judge0",
+ "real-time chat",
+ "leaderboard",
+ "competitive programming",
+ "Next.js",
+ ],
+ authors: [{ name: "VibeXcode" }],
+ creator: "VibeXcode",
+ applicationName: SITE_NAME,
+ alternates: {
+ canonical: "/",
+ },
+ openGraph: {
+ type: "website",
+ siteName: SITE_NAME,
+ title: SITE_TITLE,
+ description: SITE_DESCRIPTION,
+ url: SITE_URL,
+ locale: "en_US",
+ },
+ twitter: {
+ card: "summary_large_image",
+ title: SITE_TITLE,
+ description: SITE_DESCRIPTION,
+ },
+ robots: {
+ index: true,
+ follow: true,
+ },
+ category: "technology",
};
export default function RootLayout({
diff --git a/app/login/layout.tsx b/app/login/layout.tsx
new file mode 100644
index 0000000..d2ffe9d
--- /dev/null
+++ b/app/login/layout.tsx
@@ -0,0 +1,15 @@
+import type { Metadata } from "next";
+
+export const metadata: Metadata = {
+ title: "Sign in",
+ description:
+ "Sign in to VibeXcode with email or social login (Google, GitHub, Facebook).",
+};
+
+export default function LoginLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return <>{children}>;
+}
diff --git a/app/playground/layout.tsx b/app/playground/layout.tsx
new file mode 100644
index 0000000..0e4f7b4
--- /dev/null
+++ b/app/playground/layout.tsx
@@ -0,0 +1,15 @@
+import type { Metadata } from "next";
+
+export const metadata: Metadata = {
+ title: "Playground",
+ description:
+ "Multi-language code playground โ write and execute JavaScript, Python, Java, or C++ in a sandbox powered by Judge0, with live diffing against expected output.",
+};
+
+export default function PlaygroundLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return <>{children}>;
+}
diff --git a/app/signup/layout.tsx b/app/signup/layout.tsx
new file mode 100644
index 0000000..56b5b74
--- /dev/null
+++ b/app/signup/layout.tsx
@@ -0,0 +1,15 @@
+import type { Metadata } from "next";
+
+export const metadata: Metadata = {
+ title: "Create account",
+ description:
+ "Join VibeXcode โ create your account with email or social login to start solving challenges and chatting with the community.",
+};
+
+export default function SignupLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return <>{children}>;
+}