</> CodeNest
A full-stack realtime collaborative code editor with Monaco-powered IDE, Yjs CRDT synchronization, multi-language code execution via Piston, snippet sharing with social features, and a complete admin moderation panel.
Features • Screenshots • Quick Start • API Docs • Architecture
- Realtime Collaborative Editing — Yjs CRDT-based document synchronization over WebSocket with conflict-free concurrent editing and live cursor positions
- Monaco Code Editor — Full VS Code editing experience with IntelliSense, syntax highlighting for 25+ languages, customizable themes, keymaps, and minimap
- Multi-Language Code Execution — Run code in JavaScript, Python, Java, Go, Rust, C/C++, and 20+ languages via the Piston execution engine
- Snippet Sharing Platform — Create, fork, tag, and share code snippets publicly with full-text search, filtering by language/tag, and popularity sorting
- Collaboration Rooms — Create private or public rooms, invite participants by username, and code together with real-time presence indicators
- Social Features — Like snippets, write threaded comments with replies, view public profiles, and report inappropriate content
- JWT Authentication — Secure register/login flow with bcrypt password hashing, token expiry, and banned-user enforcement
- Role-Based Admin Panel — Full moderation dashboard with user management, snippet/comment moderation, report queue resolution, and analytics
- Customizable Preferences — Per-user editor settings (theme, font, tab size, keymap, word wrap, line numbers), appearance mode, and privacy controls
- Swagger API Documentation — Interactive OpenAPI 3.1 docs served at
/api-docswith all endpoints, schemas, and authentication flows - Avatar Uploads — Cloudinary-powered profile picture uploads with image optimization
- Security Hardened — Helmet headers, CORS whitelist, tiered rate limiting, input sanitization, express-validator schemas, and mongo-sanitize
All screenshots are captured from the live deployment.
A high-level visual map of the system. Both diagrams render natively on GitHub thanks to Mermaid support.
How the core collections relate to each other and how real-time delivery fans out.
graph LR
User(("User"))
Snippet(["Snippet"])
Comment(["Comment"])
Like(["Like"])
Room(["Room"])
Report(["Report"])
User -- "creates" --> Snippet
User -- "writes" --> Comment
User -- "toggles" --> Like
User -- "owns" --> Room
User -- "joins" --> Room
User -- "files" --> Report
Snippet -- "receives" --> Comment
Comment -- "replies to" --> Comment
Like -- "targets" --> Snippet
Snippet -- "belongs to" --> Room
Report -- "targets" --> Snippet
Report -- "targets" --> Comment
How a single browser action travels through the stack.
flowchart LR
Browser["React 19 SPA<br/>(Vite + Tailwind v4)"]
API["Express 5 API<br/>(REST + JWT)"]
WS["Socket.io<br/>(presence + cursors)"]
YJS["y-websocket<br/>(CRDT sync)"]
DB[("MongoDB<br/>Mongoose 9")]
CDN[("Cloudinary<br/>avatars")]
Piston[("Piston API<br/>code execution")]
Browser -- "Axios + JWT (Bearer)" --> API
Browser <-. "WebSocket (JWT handshake)" .-> WS
Browser <-. "WebSocket (JWT query)" .-> YJS
API --> DB
API -- "stream upload" --> CDN
API -- "POST /execute" --> Piston
WS -. "presence:userJoined" .-> Browser
WS -. "cursor:update" .-> Browser
YJS -. "CRDT doc sync" .-> Browser
- React 19: Modern UI library with hooks, context, and concurrent features
- Vite 6: Lightning-fast build tool with HMR and optimized production bundles
- Tailwind CSS 4: Utility-first CSS framework with Vite plugin integration
- Monaco Editor: VS Code's editor component with full language support and IntelliSense
- Yjs + y-monaco: CRDT-based real-time collaborative editing bound to Monaco
- Socket.io Client: Real-time presence and cursor position broadcasting
- React Router 7: Declarative client-side routing with nested layouts and guards
- Axios: Promise-based HTTP client with JWT interceptors
- React Hot Toast: Lightweight toast notification system
- clsx: Conditional className utility
- Node.js: Server-side JavaScript runtime (ES Modules)
- Express 5: Minimal web framework with async error handling
- MongoDB (Mongoose 9): NoSQL database with schema validation, compound indexes, and text search
- Socket.io 4: Real-time bidirectional communication for presence and cursor events
- y-websocket + Yjs: WebSocket server for CRDT document synchronization
- JSON Web Token (JWT): Stateless authentication with configurable expiry
- bcrypt: Password hashing with salt rounds
- Piston API: Sandboxed multi-language code execution proxy
- Cloudinary: Cloud-based image upload and optimization
- Swagger UI Express: Interactive OpenAPI 3.1 documentation
- Helmet: HTTP security headers
- express-rate-limit: Tiered rate limiting (global, auth, code-run, write, admin)
- express-validator: Request payload validation with custom sanitizers
- express-mongo-sanitize: NoSQL injection prevention
- Multer: Multipart file upload handling
- Morgan: HTTP request logging
- Node.js v20+ and npm
- MongoDB — MongoDB Atlas (free tier) or local instance
- Cloudinary account (optional, for avatar uploads)
1. Clone the repository:
git clone https://github.com/Serkanbyx/codenest.git
cd codenest2. Set up environment variables:
cp server/.env.example server/.env
cp client/.env.example client/.envserver/.env
NODE_ENV=development
PORT=5000
MONGO_URI=mongodb://127.0.0.1:27017/codenest
JWT_SECRET=your_super_secret_key_here
JWT_EXPIRES_IN=7d
CORS_ORIGIN=http://localhost:5173
PISTON_BASE_URL=https://emkc.org/api/v2/piston
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secret
ADMIN_EMAIL=[email protected]
ADMIN_PASSWORD=your_admin_password
MAX_CODE_PAYLOAD_KB=64client/.env
VITE_API_URL=http://localhost:5000/api
VITE_SOCKET_URL=http://localhost:5000
VITE_YJS_URL=ws://localhost:50003. Install dependencies:
cd server && npm install
cd ../client && npm install4. Seed the admin user:
cd server && npm run seed5. Run the application:
# Terminal 1 — Backend
cd server && npm run dev
# Terminal 2 — Frontend
cd client && npm run devThe API will be available at http://localhost:5000 and the client at http://localhost:5173.
- Register — Create a new account with username, email, and password
- Login — Authenticate and receive a JWT for protected actions
- Explore Snippets — Browse public snippets on the homepage, filter by language or tags
- Create a Snippet — Write code in the editor and save as public or private snippet
- Fork a Snippet — Clone any public snippet to your own collection and modify it
- Create a Room — Start a collaboration room and invite participants by username
- Code Together — Edit code simultaneously with live cursors and presence indicators
- Run Code — Execute code in 25+ languages directly from the editor
- Interact — Like snippets, write comments, and report inappropriate content
- Customize — Adjust editor theme, font, keymap, and privacy settings
- Admin Panel — Moderators can manage users, review reports, and moderate content
The app uses stateless JWT authentication. On login, the server issues a signed token containing the user ID. The client stores the token in memory and attaches it as a Bearer header on every subsequent API request.
// Axios interceptor attaches JWT automatically
axiosInstance.interceptors.request.use((config) => {
const token = getStoredToken();
if (token) config.headers.Authorization = `Bearer ${token}`;
return config;
});Collaboration is powered by two parallel WebSocket channels:
- Socket.io — Handles room presence (join/leave events) and cursor position broadcasting with token-bucket throttling (20 events/sec).
- y-websocket (Yjs) — Manages the CRDT document state. Each room maps to a Yjs document that synchronizes edits conflict-free across all connected clients via
y-monacobindings.
// y-websocket upgrade path: /yjs/{roomId}?token=JWT
// Socket.io path: /socket.io (with JWT in handshake auth)Code execution is proxied through the Piston API. The server validates the language against a supported list, resolves the latest runtime version, and forwards the code payload. Results (stdout, stderr, exit code) are returned to the client.
The admin panel uses role-based access control (adminOnly middleware). Admins can view dashboard statistics, manage user roles/bans, moderate snippets/comments (active → hidden → removed), and resolve user reports with configurable actions (noop, hide, remove, ban).
Full interactive documentation is available at /api-docs (Swagger UI).
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /api/auth/register |
No | Create a new user |
| POST | /api/auth/login |
No | Login and receive JWT |
| GET | /api/auth/me |
Yes | Get current user profile |
| PATCH | /api/auth/me |
Yes | Update profile (displayName, bio, avatar) |
| PATCH | /api/auth/password |
Yes | Change password |
| DELETE | /api/auth/me |
Yes | Delete account |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /api/snippets |
Yes | Create a snippet |
| GET | /api/snippets/me |
Yes | List own snippets (paginated) |
| GET | /api/snippets/public |
Optional | Explore public snippets with filters |
| GET | /api/snippets/:id |
Optional | Read a single snippet |
| PATCH | /api/snippets/:id |
Yes | Update a snippet |
| DELETE | /api/snippets/:id |
Yes | Delete a snippet |
| POST | /api/snippets/:id/fork |
Yes | Fork a public snippet |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /api/rooms |
Yes | Create a collaboration room |
| GET | /api/rooms/me |
Yes | List own/joined rooms |
| GET | /api/rooms/:roomId |
Optional | Read room details |
| POST | /api/rooms/:roomId/join |
Yes | Join a room |
| POST | /api/rooms/:roomId/leave |
Yes | Leave a room |
| POST | /api/rooms/:roomId/participants |
Yes | Add participant by username |
| PATCH | /api/rooms/:roomId |
Yes | Update room settings |
| DELETE | /api/rooms/:roomId |
Yes | Delete a room |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | /api/code/runtimes |
Optional | List supported runtimes |
| POST | /api/code/run |
Yes | Execute code (rate limited: 8/min) |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | /api/comments/snippet/:snippetId |
Optional | List snippet comments |
| GET | /api/comments/:commentId/replies |
Optional | List comment replies |
| POST | /api/comments |
Yes | Create a comment or reply |
| PATCH | /api/comments/:id |
Yes | Update a comment |
| DELETE | /api/comments/:id |
Yes | Soft-delete a comment |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /api/likes/:snippetId |
Yes | Toggle like on a snippet |
| GET | /api/likes/me |
Yes | List liked snippets |
| GET | /api/likes/:snippetId/me |
Yes | Check like state |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| PATCH | /api/profile/me/preferences |
Yes | Update preferences |
| GET | /api/profile/:username |
Optional | Read public profile |
| GET | /api/profile/:username/snippets |
Optional | List profile snippets |
| GET | /api/profile/:username/likes |
Optional | List profile likes |
| GET | /api/profile/:username/comments |
Optional | List profile comments |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /api/reports |
Yes | Create a moderation report |
| GET | /api/reports/me |
Yes | List own reports |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | /api/admin/stats |
Admin | Dashboard statistics |
| GET | /api/admin/users |
Admin | List all users |
| GET | /api/admin/users/:id |
Admin | User details |
| PATCH | /api/admin/users/:id/role |
Admin | Update user role |
| PATCH | /api/admin/users/:id/ban |
Admin | Ban/unban user |
| DELETE | /api/admin/users/:id |
Admin | Delete user |
| GET | /api/admin/snippets |
Admin | List snippets for moderation |
| PATCH | /api/admin/snippets/:id/status |
Admin | Moderate snippet status |
| DELETE | /api/admin/snippets/:id |
Admin | Hard-delete snippet |
| GET | /api/admin/comments |
Admin | List comments for moderation |
| PATCH | /api/admin/comments/:id/status |
Admin | Moderate comment status |
| GET | /api/admin/reports |
Admin | List report queue |
| PATCH | /api/admin/reports/:id |
Admin | Resolve/dismiss a report |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /api/upload/avatar |
Yes | Upload avatar (multipart) |
All protected endpoints require
Authorization: Bearer <token>header. Rate limits vary by tier: global (300/15min), auth (10/15min), code-run (8/min), write (30/min), admin (60/15min).
A clean monorepo layout with an explicit backend / frontend split. Each panel below is collapsible — expand the one you care about.
Server — Express 5 API + Socket.io + y-websocket
server/
├── config/ # env validation, db connection, swagger spec
├── controllers/ # auth, snippet, room, code, comment, like, report, admin, profile, upload
├── middleware/ # auth (protect/optionalAuth/adminOnly), rateLimiters, validate, sanitize, upload, errorHandler, notFound, socketAuth
├── models/ # User, Snippet, Room, Comment, Like, Report (Mongoose schemas)
├── routes/ # one file per resource group (10 route files)
├── scripts/ # seedAdmin.js, migrateSnippetIndexes.js
├── sockets/ # Socket.io init, presenceHandlers, cursorHandlers, yjsServer, socketUtils
├── utils/ # ApiError, generateToken, pistonClient, cloudinary, constants, escapeRegex
├── validators/ # express-validator schemas per resource (8 validator files)
├── index.js # Express app composition, HTTP server, Socket.io + Yjs attach
├── .env.example
└── package.json
Client — React 19 + Vite 6 SPA
client/
├── public/ # static assets
├── src/
│ ├── api/ # Axios instance + 11 service modules (auth, snippet, room, code, comment, like, report, admin, profile, upload)
│ ├── components/
│ │ ├── auth/ # AuthCard, PasswordField, PasswordStrengthMeter
│ │ ├── common/ # Avatar, Spinner, FormField, ConfirmModal, Skeleton, EmptyState, ToggleSwitch, RoleBadge, StatusBadge…
│ │ ├── editor/ # MonacoPane, EditorToolbar, LanguageSelect, OutputPanel, UserListSidebar, SaveSnippetModal
│ │ ├── layout/ # Navbar, Footer
│ │ └── snippets/ # SnippetCard, SnippetGrid, SnippetFilters, CommentThread, CommentItem
│ ├── context/ # AuthContext, SocketContext, PreferencesContext
│ ├── hooks/ # useYjsRoom, useSocket, useDebounce, useLocalStorage, useCopyToClipboard, useGuestId
│ ├── layouts/ # MainLayout, AdminLayout, SettingsLayout
│ ├── pages/
│ │ ├── admin/ # AdminDashboardPage, AdminUsersPage, AdminSnippetsPage, AdminCommentsPage, AdminReportsPage
│ │ ├── auth/ # LoginPage, RegisterPage
│ │ ├── home/ # HomePage
│ │ ├── misc/ # NotFoundPage, ForbiddenPage
│ │ ├── profile/ # ProfilePage
│ │ ├── rooms/ # RoomsHubPage, EditorPage
│ │ ├── settings/ # ProfileSettingsPage, AccountSettingsPage, AppearanceSettingsPage, EditorSettingsPage, PrivacySettingsPage, NotificationsSettingsPage
│ │ └── snippets/ # SnippetDetailPage, EditSnippetPage, MySnippetsPage
│ ├── routes/ # ProtectedRoute, AdminRoute, GuestOnlyRoute
│ ├── App.jsx # router + providers + scroll-to-top
│ └── main.jsx # entry point
├── .env.example
└── package.json
Repository root — docs, governance & shared assets
codenest/
├── client/ # → see Client panel above
├── server/ # → see Server panel above
├── docs/ # build-guide.md
├── assets/ # screenshots/
├── .github/
│ ├── ISSUE_TEMPLATE/ # bug_report.yml, feature_request.yml, config.yml
│ └── PULL_REQUEST_TEMPLATE.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── SECURITY.md
├── LICENSE
└── README.md
- Helmet — Sets strict HTTP security headers (CSP, HSTS, X-Frame-Options, etc.)
- CORS Whitelist — Only the configured client origin can access the API
- Tiered Rate Limiting — Global, auth, code-run, write, and admin rate limiters with draft-7 standard headers
- JWT Authentication — Signed tokens with configurable expiry, Bearer scheme enforcement
- bcrypt Hashing — Passwords hashed with 12 salt rounds, never stored in plaintext
- Input Validation — All request bodies validated via express-validator schemas before reaching controllers
- Mongo Sanitize — Prevents NoSQL injection by stripping
$and.from user input - Payload Limits — JSON body size capped at 64KB (96KB for code execution)
- Socket Authentication — WebSocket connections require valid JWT in handshake/query params
- Cursor Throttling — Token-bucket rate limiting on cursor events (20/sec) to prevent flooding
- Banned User Enforcement — Banned users are rejected at both HTTP and WebSocket layers
- Sensitive Field Stripping — Password and internal fields are never exposed in API responses
1. Create a new Web Service on Render:
| Setting | Value |
|---|---|
| Root Directory | server |
| Build Command | npm install |
| Start Command | npm start |
| Environment | Node |
2. Add environment variables:
| Variable | Value |
|---|---|
NODE_ENV |
production |
PORT |
5000 |
MONGO_URI |
Your MongoDB Atlas connection string |
JWT_SECRET |
A strong random secret |
JWT_EXPIRES_IN |
7d |
CORS_ORIGIN |
Your Netlify deployment URL |
PISTON_BASE_URL |
https://emkc.org/api/v2/piston |
CLOUDINARY_CLOUD_NAME |
Your Cloudinary cloud name |
CLOUDINARY_API_KEY |
Your Cloudinary API key |
CLOUDINARY_API_SECRET |
Your Cloudinary API secret |
1. Create a new site on Netlify:
| Setting | Value |
|---|---|
| Base Directory | client |
| Build Command | npm run build |
| Publish Directory | client/dist |
2. Add environment variables:
| Variable | Value |
|---|---|
VITE_API_URL |
https://your-api.onrender.com/api |
VITE_SOCKET_URL |
https://your-api.onrender.com |
VITE_YJS_URL |
wss://your-api.onrender.com |
3. Add a _redirects file for SPA routing:
/* /index.html 200
Important: Make sure
CORS_ORIGINin the backend matches your Netlify URL exactly (no trailing slash).
✅ JWT-based authentication (register, login, password change, account deletion) ✅ Monaco Editor with full language support and customizable settings ✅ Real-time collaborative editing via Yjs CRDT over WebSocket ✅ Live cursor positions and presence indicators via Socket.io ✅ Multi-language code execution (25+ languages) via Piston ✅ Snippet CRUD with public/private visibility and tagging ✅ Snippet forking with lineage tracking ✅ Full-text search across snippets (title, description, tags) ✅ Threaded comments with nested replies ✅ Like/unlike toggle with aggregated counts ✅ Public user profiles with activity feeds ✅ Collaboration rooms with participant management ✅ Room language switching (owner-only) ✅ Avatar upload via Cloudinary ✅ Admin dashboard with aggregate statistics ✅ User management (role assignment, banning) ✅ Content moderation (snippets, comments) ✅ Report queue with resolution actions ✅ Customizable editor preferences (theme, font, keymap, etc.) ✅ Privacy settings (show/hide email, likes, comments) ✅ Protected and admin-only routes ✅ Swagger/OpenAPI documentation ✅ Tiered rate limiting ✅ Security hardening (Helmet, sanitize, CORS, etc.)
- 🔮 Email verification and password reset flow
- 🔮 OAuth integration (GitHub, Google)
- 🔮 Real-time notifications via WebSocket
- 🔮 Snippet version history and diff view
- 🔮 Room chat sidebar
- 🔮 File-based projects (multi-file editor)
- 🔮 Embedded snippet sharing (iframe/embed code)
- 🔮 AI-powered code suggestions
- 🔮 Dark/light theme toggle with system preference sync
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch:
git checkout -b feat/amazing-feature - Commit your changes following the convention below
- Push to the branch:
git push origin feat/amazing-feature - Open a Pull Request using the provided PR template
| Prefix | Description |
|---|---|
feat: |
New feature |
fix: |
Bug fix |
refactor: |
Code refactoring |
docs: |
Documentation changes |
style: |
Code style (formatting, no logic change) |
chore: |
Maintenance and dependency updates |
test: |
Adding or updating tests |
This project is licensed under the MIT License — see the LICENSE file for details.
Serkan Bayraktar
- Monaco Editor — VS Code's powerful editor component
- Yjs — CRDT framework for real-time collaboration
- Piston — Sandboxed code execution engine
- Socket.io — Real-time bidirectional event-based communication
- Tailwind CSS — Utility-first CSS framework
- Express.js — Fast, unopinionated web framework
- Cloudinary — Image upload and optimization service
⭐ If you like this project, don't forget to give it a star!








