Five Services is a full-stack freelance marketplace application where users can offer services, book professionals, and communicate in real-time. It features a modern service booking flow, role-based authentication (Client/Freelancer), and a real-time messaging system powered by Socket.IO.
This project is a monorepo designed to demonstrate advanced full-stack patterns, separating the real-time socket server from the Next.js application logic while maintaining a shared type-safe database layer.
- Role-Based Access Control: Distinct flows for Clients (Buyers) and Freelancers (Sellers).
- Service Booking System: Comprehensive booking workflow with status tracking.
- Real-Time Messaging: Instant chat functionality between clients and freelancers using Socket.IO.
- Live Online Status: Real-time user presence detection.
- Media Sharing: Support for sending images and files in chat (integrated with Cloudinary).
- Modern UI/UX: Built with Tailwind CSS, Shadcn UI, and smooth animations.
- Framework: Next.js 16 (App Router)
- Language: TypeScript
- Styling: Tailwind CSS, Shadcn UI, Magic UI
- State/Animations: Motion (Framer Motion), React Hook Form
- Runtime: Node.js
- API Endpoints: Server Actions
- Real-Time: Socket.IO, Express
- Language: TypeScript
- Database Host: NeonDb
- Database: PostgreSQL (Single shared instance)
- ORM: Prisma (Managed within the Frontend/Next.js layer)
- Monorepo Management: npm workspaces
- Linting: ESLint
This project uses a monorepo structure to separate the frontend application from the real-time socket server.
/root
├── /frontend → Next.js application (owns Database & Prisma)
├── /backend → Socket.IO server (lightweight, real-time only)
└── package.json → Shared scripts for the entire monorepo
In this architecture, the Frontend (Next.js) serves as the primary backend for CRUD operations, authentication, and business logic using Server Actions and API routes. Therefore, it owns the Prisma schema and migrations. The Backend folder is strictly for the Socket.IO server to handle ephemeral real-time connections. This separation ensures the socket server remains lightweight and stateless, while the Next.js app handles data integrity.
Both the frontend and backend require environment variables to function correctly.
Required for database connections, authentication, and API endpoints.
DATABASE_URL="postgresql://..."
BETTER_AUTH_SECRET="your-secret"
BETTER_AUTH_URL="http://localhost:3000"
NEXT_PUBLIC_SOCKET_URL="http://localhost:9000"
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME="your-cloud-name"Refrence .env.example in the frontend directory for a complete list.
Required for database access (via the shared Prisma client) and server configuration.
DATABASE_URL="postgresql://..."
PORT=9000Follow these steps to run the project on a fresh machine.
git clone <repository-url>
cd five-servicesFirst, set up your environment variables by copying the example file:
cp frontend/.env.example frontend/.envAction Required: Open the newly created
frontend/.envfile and populate the required environment variables (such asDATABASE_URLand Authentication secrets) to matching your local integration. This step is mandatory for the app to run.
Run the setup script which installs dependencies, generates the Prisma client, and runs migrations.
npm run setup:devNote: setup:dev automatically runs npm install, generates the Prisma client, and pushes DB migrations.
This will start both the Next.js frontend and the Socket.IO backend concurrently.
npm run devThe app should now be accessible at:
- Frontend:
http://localhost:3000 - Socket Server:
http://localhost:9000
Here is a breakdown of the available commands in the root package.json:
npm run install:all- Installs dependencies for the root, frontend, and backend.npm run prisma:generate- Regenerates the Prisma client (useful after schema changes).npm run prisma:migrate- Runs database migrations to keep the DB schema in sync.npm run dev- Starts both frontend and backend in development mode.npm run build- Builds the Next.js frontend application for production.
When to use them?
- Use
setup:devwhen you first pull the repo. - Use
devfor daily development. - Use
prisma:generateifPrismaClienttypes are out of sync.
- Server-Side Only: Prisma is instantiated and run only on the server side of Next.js (in Server Actions or API routes). No sensitive database logic is exposed to the client browser.
- Shared Access: The backend (Socket.IO) imports the generated Prisma client from the frontend directory. This allows the socket server to validate session tokens or save messages directly to the shared database without duplicating the schema.
- Frontend: The Next.js application is production-ready and can be deployed to Vercel or any Node.js hosting platform.
- Backend: The Socket.IO server is a separate Node.js process and should be deployed to a service that supports persistent connections (e.g., Railway, Heroku, or a VPS).
- Environment: ensure
DATABASE_URLis consistent across both deployments so they share the same data.
This application was built as a comprehensive Portfolio & Learning Project to demonstrate:
- Full-Stack Proficiency: end-to-end development handling database, auth, UI, and deployment.
- Real-Time Systems: Implementing complex socket logic for messaging and presence.
- Architecture: Making deliberate choices (like monorepo & shared Prisma types) to solve specific structural challenges in modern web apps.