A modern Express.js backend application with real-time chat, authentication, and push notifications.
- Express.js 5.1.0 - Web framework
- TypeScript 5.8.3 - Type safety
- Sequelize 6.37.7 - ORM for MySQL
- Socket.IO 4.8.1 - Real-time WebSocket
- JWT 9.0.2 - Authentication
- Google OAuth 2.0 - Social login
- Firebase Cloud Messaging - Push notifications
- Jest 30.2.0 - Testing framework
- Swagger UI - API documentation
- JWT-based login and registration
- Google OAuth 2.0 integration
- Refresh token mechanism
- Secure password hashing with bcrypt
- WebSocket connections via Socket.IO
- Real-time message delivery
- Typing indicators
- Online/offline presence tracking
- Message status (sent/delivered/read)
- Multi-device support
- Start or retrieve existing chat rooms
- List all user chat rooms with last message
- Paginated message history
- Send text messages
- Mark messages as read/delivered
- Firebase Cloud Messaging (FCM) integration
- Device token management
- Automatic offline message notifications
- Invalid token cleanup
- Unit tests with Jest (25+ tests)
- Swagger UI interactive documentation
- Auto-generated API docs
- 100% TypeScript type safety
- Node.js 18+ or 20+
- MySQL 5.7+ or 8.0+
- pnpm (recommended) or npm
- Firebase project (for FCM)
- Google Cloud project (for OAuth)
git clone https://github.com/nabilrn/express-api-starter.git
cd express-api-starterpnpm install
# or
npm installCopy the example file and configure:
cp .env.example .envEdit .env with your credentials:
# Server
PORT=3000
# Database
DB_HOST=127.0.0.1
DB_USER=root
DB_PASSWORD=your_password
DB_NAME=simplechatapp
# JWT (generate secure random strings)
JWT_SECRET=your_jwt_secret_min_32_chars
JWT_REFRESH_SECRET=your_refresh_secret_min_32_chars
# Google OAuth (from Google Cloud Console)
GOOGLE_CLIENT_ID=your_client_id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your_client_secret
GOOGLE_CALLBACK_URL=http://localhost:3000/api/auth/google/callback
# Firebase (FCM Server Key from Firebase Console)
FCM_SERVER_KEY=your_fcm_server_key
# CORS
CLIENT_URL=http://localhost:3000cp config/config.example.json config/config.jsonEdit config/config.json with your MySQL credentials.
# Create MySQL database
mysql -u root -p
CREATE DATABASE simplechatapp;
exit;npx sequelize-cli db:migrate# Development mode with auto-reload
pnpm dev
# Production mode
pnpm build
pnpm startServer will run on http://localhost:3000
Access the interactive API documentation:
- Auto-generated Docs: http://localhost:3000/docs
- Swagger UI: http://localhost:3000/docs/swagger
# Run all tests
pnpm test
# Run tests with coverage
pnpm test -- --coverage
# Run tests in watch mode
pnpm test -- --watch- Go to the Google Cloud Console
- Create a new project or select an existing one
- Enable the Google+ API
- Go to Credentials β Create Credentials β OAuth Client ID
- Configure the OAuth consent screen
- Add authorized redirect URI:
http://localhost:3000/api/auth/google/callback - Copy the Client ID and Client Secret to your
.envfile
POST /api/auth/register
- Register a new user
- Body: { username: string, email: string, password: string }
POST /api/auth/login
- Login with credentials
- Body: { email: string, password: string }
POST /api/auth/refresh
- Get new access token using refresh token
- Body: { refreshToken: string }
GET /api/auth/google
- Initiate Google OAuth flow
GET /api/auth/google/callback
- Google OAuth callbackAll chat endpoints require JWT token in Authorization header:
Authorization: Bearer <your_jwt_token>
POST /api/chats/start
- Start or get existing chat room
- Body: { targetUserId: number }
GET /api/chats
- Get all chat rooms for current user
GET /api/chats/:roomId/messages
- Get messages in a chat room
- Query: limit (optional), beforeMessageId (optional)
POST /api/chats/:roomId/messages
- Send a message
- Body: { message: string }
PUT /api/chats/:roomId/messages/:messageId/read
- Mark message as read
PUT /api/chats/:roomId/messages/delivered
- Mark messages as deliveredPOST /api/notifications/device
- Register FCM device token
- Body: { token: string }
GET /api/notifications/device
- Get registered device tokens
DELETE /api/notifications/device
- Delete device token
- Body: { token: string }Connect with JWT token:
import io from 'socket.io-client';
const socket = io('http://localhost:3000', {
auth: { token: 'your_jwt_token' }
});
// Join a chat room
socket.emit('room:join', { roomId: 1 });
// Send a message
socket.emit('message:send', {
roomId: 1,
message: 'Hello!'
});
// Listen for new messages
socket.on('message:new', (data) => {
console.log('New message:', data);
});
// Typing indicator
socket.emit('message:typing', {
roomId: 1,
isTyping: true
});
// Mark message as read
socket.emit('message:read', {
roomId: 1,
messageId: 123
});
// Listen for user online/offline
socket.on('user:online', (data) => {
console.log('User online:', data.userId);
});
socket.on('user:offline', (data) => {
console.log('User offline:', data.userId);
});express-api-starter/
βββ src/
β βββ __tests__/ # Jest unit tests
β βββ config/ # Database & Passport config
β βββ controllers/ # Route controllers
β βββ docs/ # Swagger YAML
β βββ middleware/ # Auth & validation
β βββ models/ # Sequelize models
β βββ modules/ # Feature modules
β β βββ chat/ # Chat service, routes
β β βββ notification/ # FCM service, routes
β βββ routes/ # Express routes
β βββ socket/ # Socket.IO server & events
β βββ utils/ # Helpers & logger
β βββ index.ts # App entry point
βββ migrations/ # Database migrations
βββ config/ # Sequelize config
βββ .env.example # Environment variables template
βββ README.md # This file
# Start development server with auto-reload
pnpm dev
# Build TypeScript
pnpm build
# Start production server
pnpm start
# Run tests
pnpm test
# Run tests with coverage
pnpm test -- --coverage- users - User accounts
- tokens - Refresh tokens
- chat_rooms - Chat room metadata
- chat_participants - Room-user relationships
- messages - Chat messages
- device_tokens - FCM device tokens
See migrations in migrations/ for complete schema.
MIT License - feel free to use this project for learning or production.
Built with β€οΈ using Express.js, Socket.IO, and TypeScript