Build a lightweight 1:1 chat application demonstrating:
- Real-time messaging with WebSocket
- Heart reaction on toggle
- Long-press animation
Use React Native with Expo. You may use any libraries or npm packages.
Note: This is a frontend-focused challenge. The REST API server (json-server) and WebSocket server are already implemented and provided. Your task is to build the React Native Expo frontend that connects to these existing services.
UI Guideline: A chat screen video asset is provided as a UI guideline and inspiration. This is just a reference - feel free to optimize and enhance the design as you see fit. Recommended improvements include animations, emoji interactions, and other UX enhancements.
- Real-time messaging using WebSocket
- Display messages in a chat bubble UI
- Show sender avatar, message text, timestamp
- Distinguish between sent and received messages
- Input field to type and send messages
- Auto-scroll to latest message
- Show typing indicators (optional)
- Show message delivery status (sent, delivered, read - optional)
- Toggle Heart: Each message should have a heart toggle button that allows users to add or remove a heart from that specific message
- Long Press Animation: When a user long-presses a message, it should toggle the heart (add if not present, remove if present) and trigger a fluid animation that fills the screen with lots of hearts (eg: animated heart emojis floating across the screen)
- When user toggles the heart, it persists and is linked to the specific message
- Hearts are stored in the database and persist across app restarts
- Multiple hearts can be added to different messages
- Hearts are displayed within the message bubble component
- WebSocket server running on port 3002
- Handle real-time message sending/receiving
- Handle heart emoji events
- Broadcast messages to the correct recipient
- Store messages and hearts in database
- Bot functionality: Automatically responds when messages are sent to bot users
- Bot users are identified by
isBot: truein the user object - Uses Faker library to generate contextual, varied responses
- Responses are contextual based on message patterns (greetings, questions, etc.)
- Generates natural-sounding responses with varied content
- Bot users are identified by
- users: List of users with id, name, avatar, bio, isBot (optional, for bot users)
- threads: 1:1 threads between two users
- messages: Chat messages with sender, receiver, text, timestamp
- hearts: Heart emoji records linked to specific messages (messageId, sender, receiver, timestamp)
Bot Users:
- Bot users have
isBot: truein their user object - When a message is sent to a bot, the server uses Faker to generate contextual responses
- Responses vary based on message patterns (greetings, questions, help requests, etc.)
- Uses Faker's lorem ipsum generator for natural-sounding, varied text
- A default ChatBot user is included in the database (
id: "bot001")
GET /messages?threadId={id}- Get messages for a threadGET /hearts?messageId={id}- Get hearts for a specific messageDELETE /hearts/{id}- Delete a heart (used for cleanup/flush operations)DELETE /messages/{id}- Delete a message (used for cleanup/flush operations)DELETE /threads/{id}- Delete a thread (used for cleanup/flush operations)
Note:
- Creating/Updating: Messages and hearts are created and updated in real-time via WebSocket events (
message,heart,remove_heart). This allows instant updates to all connected clients without needing to poll the server. - Fetching: The REST API (
GET /messages,GET /hearts) is used to fetch existing data when the app first loads or when you need to retrieve historical data. - No POST endpoints: Hearts are not created via
POST /heartsendpoint. Instead, they are created through WebSocket events (heartevent) for real-time communication. The server handles persistence automatically when it receives WebSocket events.
Message Events:
message- Send/receive a new message- Send:
socket.emit('message', { senderId, receiverId, text }) - Receive:
socket.on('message', (message) => { ... })- Receives the message object with id, threadId, timestamp, etc.
- Send:
message_sent- Confirmation when a message is sent and saved- Receive:
socket.on('message_sent', (message) => { ... })- Confirms message was saved with final id and threadId
- Receive:
Heart Events:
heart- Send/receive a heart emoji (linked to a specific message)- Send:
socket.emit('heart', { senderId, receiverId, threadId, messageId }) - Receive:
socket.on('heart', (heart) => { ... })- Receives heart object with id, messageId, senderId, receiverId, timestamp
- Send:
heart_sent- Confirmation when a heart is sent- Receive:
socket.on('heart_sent', (heart) => { ... })- Confirms heart was saved and persisted
- Receive:
remove_heart- Remove a heart from a message- Send:
socket.emit('remove_heart', { heartId, senderId, receiverId, messageId })
- Send:
heart_removed- Confirmation when a heart is removed- Receive:
socket.on('heart_removed', ({ heartId, messageId }) => { ... })- Confirms heart was removed
- Receive:
Other Events:
typing- Typing indicator- Send:
socket.emit('typing', { senderId, receiverId, isTyping: true/false }) - Receive:
socket.on('typing', ({ senderId, isTyping }) => { ... })
- Send:
user_online- User online status (emitted when user joins withonline: true, and when user disconnects withonline: false)- Receive:
socket.on('user_online', ({ userId, online }) => { ... })- Listen for online status changes - Join:
socket.emit('join', userId)- User must join first to set online status
- Receive:
- Code architecture & clarity
- State management (messages, hearts)
- User experience (smooth chat UI, real-time updates, persistence)
- Message reactions (beyond just hearts)
- Typing indicators
- Message read receipts
- Online/offline status
- Working Expo project
- All features implemented and functional
yarn installStart both the REST API and WebSocket servers:
yarn run devOr start them separately:
# Terminal 1: REST API Server
yarn run api
# Terminal 2: WebSocket Server
yarn run wsThe REST API server will run on http://localhost:3001 and the WebSocket server on ws://localhost:3002.
The db.json file contains:
- users: Users available to chat with (for selecting chat partner)
- threads: 1:1 thread records
- messages: Chat messages
- hearts: Heart emoji records
You can extend db.json with additional data as needed. The REST API server (json-server) will automatically create REST endpoints for any top-level keys.
The WebSocket server handles real-time communication:
- Message broadcasting between users
- Heart emoji events
- Connection management
- Data persistence to
db.json
See server.js for the WebSocket server implementation.
