A production-ready real-time chat application built with Fastify, Socket.IO, PostgreSQL backend and Next.js, Mantine UI, Tailwind CSS frontend. Features OAuth authentication, direct messaging, comprehensive message management, and a beautifully styled API documentation interface with enterprise-grade security and performance optimizations.
- Frontend Application: https://chat-app-xcfio.netlify.app/
- Backend API & Documentation: https://api-xcfio.onrender.com/
- Real-time bidirectional messaging with Socket.IO and WebSocket fallbacks
- Message CRUD operations with edit, delete, and status tracking
- Message status progression (sent → delivered → read → deleted)
- Message search with full-text search across conversations
- Message pagination with cursor-based navigation for performance
- Typing indicators with real-time broadcast to participants
- Message validation with content length limits and sanitization
- Multi-provider OAuth integration (GitHub, Google) with extensible architecture
- Secure JWT tokens with signed HTTP-only cookies
- User profile management with avatar and display name support
- User search and discovery with pagination and filtering
- Session management with automatic refresh and logout capabilities
- CSRF protection with state parameter validation
- Rate limiting with IP forwarding and proxy support
- Direct conversations between two participants with validation
- Conversation lifecycle management (create, read, delete)
- Participant validation ensuring users can only access authorized conversations
- Conversation search and listing with metadata
- Real-time conversation updates when messages are sent
- Comprehensive error handling with detailed error codes and messages
- Schema validation with TypeBox for runtime type safety
- Database migrations with Drizzle ORM
- Custom API documentation with dark theme and enhanced UX
- Production logging with structured output and file rotation
- Health check endpoints for monitoring and load balancers
- Fastify v5 - High-performance Node.js web framework
- TypeScript v5 - Type-safe development with strict configuration
- Socket.IO v4 - Real-time bidirectional communication
- Node.js 24.x - Modern JavaScript runtime with latest features
- PostgreSQL - Robust relational database with UUID v7 support
- Drizzle ORM v0.44 - Type-safe SQL toolkit and query builder
- postgres v3 - High-performance PostgreSQL client
- Next.js 15 - React framework with App Router
- React 18 - UI library with concurrent features
- TypeScript - Type-safe JavaScript development
- Mantine UI v7 - Modern React components library
- Tailwind CSS v3 - Utility-first CSS framework
- @tabler/icons-react - Comprehensive icon library
- @emotion/react - CSS-in-JS library for Mantine
- @fastify/jwt v10 - JSON Web Token authentication
- @fastify/cookie v11 - Secure cookie handling with signing
- @fastify/cors v11 - Cross-origin resource sharing configuration
- @fastify/rate-limit v10 - Request rate limiting with Redis support
- @fastify/swagger v9 - OpenAPI 3.1.1 specification generation
- @fastify/swagger-ui v5 - Interactive API documentation with custom styling
- @sinclair/typebox v0.34 - Runtime type validation and schema generation
- tsx - TypeScript execution for development and production
- drizzle-kit - Database migration and studio tools
- UUID v13 - UUID v7 generation for time-ordered identifiers
- ESLint - Code linting and formatting
- PostCSS - CSS preprocessing
- Autoprefixer - CSS vendor prefixing
- Node.js 24.x.x or higher (backend) / 18.17 or higher (frontend)
- PostgreSQL 13+ with UUID extension
- npm 10.0 or higher
- Git for version control
-
Clone the repository
git clone https://github.com/xcfio/chat-app.git cd chat-app -
Install dependencies
npm install
-
Database setup
# Create PostgreSQL database createdb chatapp # Generate and run migrations cd apps/backend node --run gen
-
Configure environment
# Backend configuration cd apps/backend cp .env.example .env # Edit .env with your configuration (see Environment Configuration) # Frontend configuration cd ../frontend cp .env.example .env.local # Edit .env.local with your API endpoint
-
Start development servers
# From project root - starts both backend and frontend node --run dev # Or start individually: cd apps/backend && node --run dev cd apps/frontend && node --run dev
-
Access the application
- Frontend:
http://localhost:7700 - Backend API:
http://localhost:7200 - API Documentation:
http://localhost:7200 - Health Check:
http://localhost:7200/status - Database Studio:
http://localhost:4000(runnode --run dbin backend)
- Frontend:
Create a .env file in apps/backend:
# Server Configuration
NODE_ENV=development
PORT=7200
# Database Configuration
DATABASE_URI=postgresql://username:password@localhost:5432/chatapp
# Security Keys (Generate strong 32+ character keys)
COOKIE_SECRET=your-super-secure-cookie-secret-key-minimum-32-chars
JWT_SECRET=your-super-secure-jwt-secret-key-minimum-32-chars
# GitHub OAuth Configuration
GITHUB_CLIENT_ID=your_github_oauth_app_client_id
GITHUB_CLIENT_SECRET=your_github_oauth_app_client_secret
GITHUB_REDIRECT_URI=http://localhost:7200/auth/github/callback
# Google OAuth Configuration
GOOGLE_CLIENT_ID=your_google_oauth_app_client_id
GOOGLE_CLIENT_SECRET=your_google_oauth_app_client_secret
GOOGLE_REDIRECT_URI=http://localhost:7200/auth/google/callback
# Frontend URL for CORS and OAuth redirects
FRONTEND_URL=http://localhost:7700
# Optional: Monitoring and Analytics
SENTRY_DSN=your_sentry_dsn
DATADOG_API_KEY=your_datadog_api_keyCreate a .env.local file in apps/frontend:
# API Configuration
NEXT_PUBLIC_API_ENDPOINT=http://localhost:7200
# Optional: Analytics
NEXT_PUBLIC_GOOGLE_ANALYTICS=GA_MEASUREMENT_ID
# Optional: Error Tracking
NEXT_PUBLIC_SENTRY_DSN=your_sentry_dsn
# Optional: Environment
NEXT_PUBLIC_ENVIRONMENT=developmentGitHub OAuth App:
- Go to GitHub Settings → Developer settings → OAuth Apps
- Click "New OAuth App"
- Set Homepage URL:
http://localhost:7700 - Set Authorization callback URL:
http://localhost:7200/auth/github/callback - Copy Client ID and Client Secret to your .env file
Google OAuth App:
- Go to Google Cloud Console → APIs & Services → Credentials
- Click "Create Credentials" → OAuth 2.0 Client IDs
- Set Authorized JavaScript origins:
http://localhost:7200 - Set Authorized redirect URIs:
http://localhost:7200/auth/google/callback - Copy Client ID and Client Secret to your .env file
chat-app/
├── .github/
│ └── workflows/ # CI/CD workflows
├── apps/
│ ├── backend/ # Fastify API server
│ │ ├── src/
│ │ │ ├── database/ # Database schema and connections
│ │ │ │ ├── index.ts # Database client and table exports
│ │ │ │ ├── user.ts # User table schema with OAuth support
│ │ │ │ ├── conversation.ts # Conversation table with participants
│ │ │ │ └── message.ts # Message table with status tracking
│ │ │ ├── function/ # Utility functions and helpers
│ │ │ │ ├── error.ts # Custom error creation and handling
│ │ │ │ ├── validation.ts # Schema validation error formatting
│ │ │ │ └── css.ts # Custom CSS for API documentation
│ │ │ ├── plugin/ # Fastify plugin configurations
│ │ │ │ ├── index.ts # Plugin registration orchestrator
│ │ │ │ ├── swagger.ts # OpenAPI specification setup
│ │ │ │ ├── swagger-ui.ts # Custom-styled documentation UI
│ │ │ │ ├── socket-io.ts # Socket.IO server configuration
│ │ │ │ ├── cookie.ts # Signed cookie middleware
│ │ │ │ ├── jwt.ts # JWT authentication setup
│ │ │ │ ├── cors.ts # CORS policy configuration
│ │ │ │ └── rate-limit.ts # Rate limiting with proxy support
│ │ │ ├── routes/ # API route handlers
│ │ │ │ ├── index.ts # Route registration orchestrator
│ │ │ │ ├── conversation/ # Conversation management endpoints
│ │ │ │ ├── message/ # Message management endpoints
│ │ │ │ ├── oauth/ # OAuth authentication flows
│ │ │ │ ├── search/ # Search functionality
│ │ │ │ ├── session/ # Session management
│ │ │ │ └── user/ # User management
│ │ │ ├── socket/ # Socket.IO event handlers
│ │ │ │ └── index.ts # Connection handling and event routing
│ │ │ ├── index.ts # Main server entry point
│ │ │ └── type.ts # TypeScript type definitions and schemas
│ │ └── drizzle/ # Database migrations
│ └── frontend/ # Next.js web application
│ ├── src/
│ │ ├── app/ # Next.js App Router
│ │ │ ├── auth/ # Authentication pages
│ │ │ ├── chat/ # Chat application
│ │ │ │ └── [id]/ # Individual conversation
│ │ │ ├── globals.css # Global styles
│ │ │ ├── layout.tsx # Root layout
│ │ │ └── page.tsx # Landing page
│ │ ├── components/ # React components
│ │ │ ├── providers/ # Context providers
│ │ │ │ ├── AuthProvider.tsx
│ │ │ │ ├── MantineProvider.tsx
│ │ │ │ └── SocketProvider.tsx
│ │ │ └── ui/ # UI components
│ │ │ ├── AuthButtons.tsx
│ │ │ ├── ChatList.tsx
│ │ │ ├── ChatWindow.tsx
│ │ │ ├── MessageInput.tsx
│ │ │ ├── MessageList.tsx
│ │ │ └── UserSearch.tsx
│ │ ├── hooks/ # Custom React hooks
│ │ │ ├── useAuth.ts
│ │ │ ├── useChat.ts
│ │ │ └── useSocket.ts
│ │ ├── lib/ # Utility libraries
│ │ │ ├── api.ts # API client configuration
│ │ │ ├── auth.ts # Authentication utilities
│ │ │ ├── socket.ts # Socket.IO configuration
│ │ │ ├── types.ts # TypeScript type definitions
│ │ │ └── utils.ts # General utilities
│ │ └── styles/ # Additional stylesheets
│ └── public/ # Static assets
├── package.json # Root package configuration
├── turbo.json # Turborepo configuration (if using)
└── README.md # This file
REST API Requests:
- Fastify Router → Route matching and parameter extraction
- Plugin Chain → Rate limiting → CORS → Authentication
- Schema Validation → TypeBox runtime validation
- Route Handler → Business logic and database operations
- Response → JSON serialization and HTTP status codes
WebSocket Connections:
- Socket.IO Handshake → Cookie parsing and JWT verification
- Connection Events → User authentication and room joining
- Message Broadcasting → Event emission to relevant participants
- Error Handling → Graceful disconnection and error reporting
The application uses PostgreSQL with UUID v7 identifiers for time-ordered, collision-resistant primary keys.
CREATE TABLE "user" (
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v7(),
"type" TEXT NOT NULL CHECK (type IN ('github', 'google')),
"token" TEXT NOT NULL,
"email" TEXT UNIQUE NOT NULL,
"username" TEXT UNIQUE NOT NULL,
"name" TEXT,
"avatar" TEXT,
"last_seen" TIMESTAMP DEFAULT NOW(),
"created_at" TIMESTAMP DEFAULT NOW(),
"updated_at" TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_user_email ON "user"(email);
CREATE INDEX idx_user_username ON "user"(username);
CREATE INDEX idx_user_type ON "user"(type);CREATE TABLE "conversation" (
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v7(),
"p1" UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
"p2" UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
"created_at" TIMESTAMP DEFAULT NOW(),
"updated_at" TIMESTAMP DEFAULT NOW()
);
CREATE UNIQUE INDEX idx_conversation_participants
ON "conversation"(LEAST(p1, p2), GREATEST(p1, p2));
CREATE INDEX idx_conversation_updated ON "conversation"(updated_at DESC);CREATE TABLE "message" (
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v7(),
"content" TEXT NOT NULL CHECK (LENGTH(content) <= 2000),
"sender" UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
"conversation" UUID NOT NULL REFERENCES "conversation"(id) ON DELETE CASCADE,
"status" TEXT DEFAULT 'sent' CHECK (status IN ('sent', 'delivered', 'read', 'deleted')),
"created_at" TIMESTAMP DEFAULT NOW(),
"edited_at" TIMESTAMP
);
CREATE INDEX idx_message_conversation ON "message"(conversation, created_at DESC);
CREATE INDEX idx_message_sender ON "message"(sender);
CREATE INDEX idx_message_status ON "message"(status);
CREATE INDEX idx_message_content_search ON "message" USING gin(to_tsvector('english', content));The API includes a custom-styled, interactive documentation interface built with Swagger UI and enhanced with a modern dark theme.
Enhanced UI/UX:
- GitHub-inspired dark theme with glassmorphism effects
- Gradient backgrounds and smooth CSS animations
- Custom syntax highlighting for JSON examples
- Responsive design optimized for all screen sizes
- Interactive examples with working API calls
- Enhanced accessibility with ARIA labels and keyboard navigation
Primary Documentation:
- Interactive UI:
http://localhost:7200(backend) - Raw OpenAPI JSON:
http://localhost:7200/json - Health Check:
http://localhost:7200/status
Development Tools:
- Database Studio:
http://localhost:4000(vianode --run dbin backend) - Server Logs:
./log.json(in development mode)
// OAuth login initiation
GET /auth/github
GET /auth/google
// OAuth callbacks
GET /auth/github/callback
GET /auth/google/callback
// Session management
GET /auth/me # Get current user
POST /auth/refresh # Refresh user data
POST /auth/logout # Logout userGET /user # Get all users (paginated)
GET /user/{id} # Get specific user
GET /search/users # Search users by queryGET /conversations # Get user's conversations
GET /conversations/{id} # Get specific conversation
POST /conversations/{userId} # Create conversation with user
DELETE /conversations/{id} # Delete conversationGET /conversations/{id}/messages # Get conversation messages
POST /conversations/{id}/messages # Send new message
PATCH /messages/{id} # Edit message
DELETE /messages/{id} # Delete message
PUT /messages/{id}/read # Mark as read
GET /search/messages # Search messagesConnection Management:
- Automatic authentication on connection using JWT cookies
- User room assignment for targeted message delivery
- Connection state tracking for presence management
- Graceful disconnection handling with cleanup
Server-to-Client Events:
interface ServerToClientEvents {
new_message: (message: Message) => void
message_deleted: (data: { messageId: string; conversationId: string }) => void
message_edited: (data: { messageId: string; content: string; editedAt: string; conversationId: string }) => void
user_status_changed: (userId: string, status: UserStatus) => void
user_typing: (userId: string, isTyping: boolean) => void
error: (error: { message: string; code: string }) => void
}Client-to-Server Events:
interface ClientToServerEvents {
update_status: (status: UserStatus) => void
typing: (chatId: string, isTyping: boolean) => void
}- User clicks GitHub login button on frontend
- Frontend redirects to
/auth/githubendpoint on backend - Backend redirects to GitHub OAuth
- GitHub redirects to
/auth/github/callbackon backend - Backend processes callback and sets cookie
- Backend redirects to frontend
/authpage - Frontend calls
/auth/meto get user data - User redirected to chat interface
- User clicks Google login button on frontend
- Frontend redirects to
/auth/googleendpoint on backend - Backend redirects to Google OAuth
- Google redirects to
/auth/google/callbackon backend - Backend processes callback and sets cookie
- Backend redirects to frontend
/authpage - Frontend calls
/auth/meto get user data - User redirected to chat interface
// Frontend authentication check
useEffect(() => {
checkAuth()
}, [])
const checkAuth = async () => {
try {
const response = await auth.me()
setUser(response.data)
} catch (error) {
setUser(null)
} finally {
setLoading(false)
}
}Indexing Strategy:
- Primary keys using UUID v7 for time-ordered insertion
- Foreign key indexes for efficient joins
- Composite indexes for common query patterns
- Full-text search indexes using PostgreSQL GIN indexes
- Partial indexes for soft-deleted records
Request Optimization:
- Schema validation caching with TypeBox compilation
- Response compression with built-in Fastify compression
- ETag support for conditional requests
- Request deduplication for identical concurrent requests
Rate Limiting:
- 20 requests per 10 seconds global limit
- IP-based tracking with X-Forwarded-For support
- Graceful degradation with informative error messages
- Configurable limits per endpoint type
Code Splitting:
- Automatic code splitting with Next.js dynamic imports
- Component-level splitting for better load times
- Route-based splitting through App Router
Component Optimization:
- React.memo for expensive components
- useMemo/useCallback for expensive computations
- Debounced search to reduce API calls
Setting Up Development Environment:
-
Clone and install dependencies
git clone https://github.com/xcfio/chat-app.git cd chat-app npm install -
Set up PostgreSQL database
createdb chatapp cd apps/backend node --run gen node --run migrate -
Configure environment variables
cd apps/backend cp .env.example .env # Edit .env with your OAuth credentials cd ../frontend cp .env.example .env.local # Edit .env.local with your API endpoint
-
Start development servers
cd ../.. node --run dev -
Open applications
- Frontend:
http://localhost:7700 - Backend API:
http://localhost:7200
- Frontend:
Current Deployment:
- Frontend: Deployed on Netlify with automatic builds from GitHub
- Backend: Deployed on Render with PostgreSQL database
Production (.env.production):
# Backend
NODE_ENV=production
DATABASE_URI=postgresql://user:pass@prod-host:5432/chatapp
FRONTEND_URL=https://chat-app-xcfio.netlify.app
TRUST_PROXY=true
# Frontend
NEXT_PUBLIC_API_ENDPOINT=https://api-xcfio.onrender.com
NEXT_PUBLIC_ENVIRONMENT=productionDatabase Connection Problems:
// Debug database connectivity
const testConnection = async () => {
try {
const result = await db.select().from(table.user).limit(1)
console.log("Database connection successful")
} catch (error) {
console.error("Database connection failed:", error)
// Check: DATABASE_URI, PostgreSQL service, network connectivity
}
}OAuth Authentication Issues:
- Incorrect redirect URIs in OAuth app settings
- Mismatched client secrets
- CORS issues with frontend domain
- Cookie domain/path configuration
Socket.IO Connection Issues:
- CORS configuration for Socket.IO
- Cookie parsing in Socket.IO handshake
- WebSocket transport blocked by proxy/firewall
- Authentication token format issues
Enable Debug Logging:
# Environment variables for debugging
DEBUG=fastify:*,socket.io:*
LOG_LEVEL=debug
cd apps/backend && node --run devFrontend Debug Mode:
# Frontend debugging
NEXT_PUBLIC_DEBUG=true
cd apps/frontend && node --run dev-
Fork the repository on GitHub
-
Clone your fork locally
git clone https://github.com/your-username/chat-app.git cd chat-app -
Install dependencies
npm install
-
Set up development environment
# Backend setup createdb chatapp_dev cd apps/backend cp .env.example .env # Edit .env with your settings node --run gen # Frontend setup cd ../frontend cp .env.example .env.local # Edit .env.local with your API endpoint
-
Create feature branch
git checkout -b feature/your-feature-name
TypeScript Guidelines:
- Use strict mode with
noImplicitAnyandstrictNullChecks - Define interfaces for all data structures
- Use enums for constant values
- Implement proper error handling with typed exceptions
- Add JSDoc comments for public APIs
Database Guidelines:
- Use transactions for multi-table operations
- Add appropriate indexes for query patterns
- Use UUID v7 for all primary keys
- Follow foreign key constraints
- Add database migrations for schema changes
API Guidelines:
- Follow RESTful principles for HTTP endpoints
- Use proper HTTP status codes
- Implement consistent error responses
- Add comprehensive OpenAPI documentation
- Include request/response examples
-
Update documentation for any API changes
-
Validate code quality by running linting and type checks
-
Update CHANGELOG.md with your changes
-
Follow commit message conventions:
feat: add message search endpoint fix: resolve socket authentication timeout docs: update API documentation refactor: optimize database queries -
Submit pull request with detailed description
-
Address review feedback promptly
This project is licensed under the MIT License - see the LICENSE file for details.
For support, questions, or contributions:
- Email: [email protected]
- Discord: Join our Discord server
- GitHub Issues: Create an issue