Curtus is a web-based platform designed to facilitate focused study and accountability. Made with a calm and polished user interface, it provides shared virtual spaces where users can work collaboratively in real-time.
Whether you're studying for exams or just need a quiet place to get work done alongside others, Curtus helps you stay on track without getting distracted.
- Study Rooms: Join open community rooms or create private, invite-only rooms for you and your friends.
- WebRTC Video & Chat: Peer-to-peer WebRTC mesh architecture for ultra-low latency video streaming, keeping you visually accountable alongside real-time text chat.
- Focus Timer: Built-in study timers to track your deep work sessions automatically.
- Global Leaderboards: Track your total study duration, maintain daily streaks, and view global rankings.
- Task & D-Day Tracking: Organize daily to-dos and set countdowns for upcoming deadlines or exams.
- White Noise Library: Built-in ambient audio to help you stay focused.
- YouTube Picture-in-Picture: Watch lectures or ambient streams directly in the app without switching tabs.
- Configurable Environment: Modify UI themes, timers, sound cues, and privacy controls to fit your workflow.
Curtus uses a decoupled architecture. The frontend handles standard requests and UI state, while a standalone Node.js server acts as the WebRTC signaling layer and real-time state synchronizer. Video feeds are established via direct peer-to-peer connections to minimize server bandwidth.
graph TD
Client["Web Client (Next.js and React)"]
PeerClient["Peer Web Client"]
subgraph Frontend ["Next.js Web Server"]
NextApp["Next.js App Router"]
Auth["Better-Auth"]
NextApp <--> Auth
end
subgraph Realtime ["Socket.IO Server"]
SocketServer["Standalone Node.js Server"]
Events["Signaling, Event Handlers and State Sync"]
SocketServer <--> Events
end
subgraph Infrastructure ["Data and Caching"]
Postgres[("Neon Postgres DB")]
Prisma["Prisma ORM"]
Redis[("Upstash Redis")]
Prisma <--> Postgres
end
Client <-->|REST and RSC| NextApp
Client <-->|WebSockets| SocketServer
Client <-->|WebRTC P2P Mesh Video| PeerClient
NextApp <-->|Queries and Mutations| Prisma
SocketServer <-->|Queries and Mutations| Prisma
SocketServer <-->|PubSub and Presence| Redis
NextApp <-->|Rate Limiting| Redis
- Frontend Application: Next.js 16 (App Router), React 19
- Video Streaming Layer: WebRTC (P2P Mesh Network)
- Styling & Components: Tailwind CSS v4, Radix UI, Shadcn
- Animation: Framer Motion, GSAP
- Database Layer: Neon Postgres, Prisma v7 ORM
- Real-time Server: Socket.IO (Node.js) for WebRTC signaling and data sync
- Caching & Rate Limiting: Upstash Redis, RateLimit, QStash
- Observability: OpenTelemetry, Prometheus, Grafana Cloud (Tempo)
- Video Capacity Restrictions: Video calls utilize a peer-to-peer (P2P) WebRTC mesh network architecture. Because each participant must send and receive streams to every other participant, bandwidth and CPU usage scale exponentially. Therefore, video streams are limited to a maximum of 4 concurrent users per room to maintain performance and client stability.
- Microphones Intentionally Disabled: To strictly preserve the quiet, distraction-free "study library" atmosphere, audio transmission (microphones) is permanently disabled. Communication is strictly limited to text chat and visual accountability.
Follow these instructions to set up the project locally for development.
- Node.js:
v20.x - Package Manager: npm
- Postgres Database: Local instance or hosted (e.g., Neon)
- Redis: Local instance or hosted (e.g., Upstash)
Clone the repository and install dependencies for both the Next.js application and the Socket.IO server:
# Install Next.js dependencies
npm ci
# Install socket server dependencies
npm ci --prefix serverCopy the example environment file:
cp .env.example .envRequired configuration:
DATABASE_URL/PRISMA_DATABASE_URL: Postgres connection string.BETTER_AUTH_URL/BETTER_AUTH_SECRET: Authentication credentials.UPSTASH_REDIS_URL/UPSTASH_REDIS_TOKEN: Redis connection parameters.NEXT_PUBLIC_APP_URL/NEXT_PUBLIC_SOCKET_URL: Public URIs for the frontend and socket server.
(Note: OAuth keys such as GOOGLE_CLIENT_ID are optional but required for social login).
Generate the Prisma client and optionally seed the database:
# Generate Prisma client
npx prisma generate
# Seed initial data
npm run db:seedCurtus requires both the Next.js web server and the Socket.IO server to run concurrently.
Terminal 1 (Next.js Application):
npm run devTerminal 2 (Socket.IO Server):
npm run dev --prefix serverThe application will be accessible at http://localhost:3000.
npm run dev— Start the Next.js application in development mode.npm run build— Create a production build of the Next.js application.npm start— Run the compiled Next.js application.npm run check— Execute ESLint and TypeScript type checking.npm test— Run Vitest unit and integration tests.npm run format— Format the codebase using Prettier.
This repository implements a robust observability pipeline:
- Structured JSON Logs: Unified logging across web and socket servers with correlation parameters (
request_id,trace_id,room_id). - Distributed Tracing: OpenTelemetry traces exported to Grafana Cloud Tempo.
- Metrics: Socket server exposes a Prometheus metrics endpoint via
GET /metrics.
Refer to docs/observability.md and docs/observability-runbook.md for complete setup instructions.
Contributions are welcome. Please refer to our Contribution Guidelines to understand our workflow and expectations before submitting a pull request.
A massive thank you to the Yeolpumta (YPT) app. I used YPT extensively during my high school exam days, and it served as a core inspiration for this app.
Curtus is licensed under the AGPL-3.0 License.
Important: If you run a modified version of this software as a network service, the AGPL generally requires you to make the corresponding source code available to users of that service. Make sure you understand your obligations before deploying a modified build. See the
LICENSEfile for more details.
Built with ❣️ by @dextertwts/amaan



