Features

Media, Emoji & AI (short)

Media uploads

Media (images, video, audio) are uploaded to Cloudinary and the returned secure URL is stored on the message document. See Getting Started → Cloudinaryfor detailed setup, presets and code examples.

Emoji support

The chat input integrates emoji-mart for picking emojis which are inserted as unicode characters. No schema change is required—emojis are stored as text.

AI assistant

The project can send prompts to Vercel's groq model via@vercel/ai. For full configuration and an example API route, see Getting Started → AI (Groq).

Real-time Subscription

Messages are subscribed to in real-time using subscribeMessagesByRoomId which sets up a Firestore listener:

const q = query(
  collection(db, "rooms", roomId, "messages"),
  orderBy("createdAt", "asc")
);

return onSnapshot(q, (snapshot) => {
  const messages = snapshot.docs.map(doc => ({
    id: doc.id,
    ...doc.data()
  }));
  onChange(messages);
});

The listener automatically fires whenever a new message is added or an existing message is modified, keeping the UI synchronized.

Using the Hook

Components use useMessages to get the current message list:

const { messages, isLoading, error } = useMessages(roomId);

// messages is automatically updated when new messages arrive
// The hook handles subscription cleanup on unmount

Unread Count Management

How Unread Counts Work

Unread counts are stored per-user in the room document:

rooms/{roomId} {
  unreadCounts: {
    "uid1": 3,
    "uid2": 0,
    "uid3": 5
  }
}
  • Incremented: When a message is sent, counts are incremented for all participants except the sender and users currently viewing the room (tracked via room presence)
  • Reset: When a user opens a room, resetUnreadCount sets their count to 0
  • Displayed: Room list items show a badge with the unread count if it's greater than 0

Integration with Room Presence

The template uses room presence (Realtime Database) to determine who is currently viewing a room:

  • When a user opens a room, useRoomPresence calls enterRoom(uid, roomId)
  • When sending a message, the service checks room presence to exclude active viewers from unread count increments
  • When leaving a room, leaveRoom(uid, roomId) is called automatically

This ensures users don't get unread badges for messages they're actively viewing.

Attachments & media

Messages can include an attachments array. Attachments use the project's Cloudinary helpers; images and videos are returned as objects that match the UploadMediashape and are stored on the message as attachments: UploadMedia[].

rooms/{roomId}/messages/{messageId} {
  senderId: string;
  text?: string;
  type: 'text' | 'system' | 'media' | 'audio';
  attachments?: UploadMedia[]; // UploadMedia is UploadImage | UploadVideo
  createdAt: Timestamp;
}

Client helpers: src/features/chat/services/cloudinary.service.tsand the hook src/features/chat/hooks/use-upload-media.ts.

Emoji

The input uses emoji-mart to insert unicode emoji into the message text. No schema change is necessary.

AI assistant (short)

The repo includes a server API at src/app/api/chat/route.ts which calls the@ai-sdk/groq model via streamText. See Getting Started → AI (Groq) for full details and examples.

Message Types

The template currently supports these message types:

  • "text" – Regular user messages with text content
  • "system" – System-generated messages (e.g. "created the group") that are styled differently in the UI

You can extend this to support "image", "file", or "reply" types by updating the message type definition and adding appropriate UI components.

Implementation Details

Key files for messaging:

  • features/chat/services/messages.service.ts – sendMessage, subscribeMessagesByRoomId
  • features/chat/hooks/use-messages.ts – React hook for subscribing to messages
  • features/chat/hooks/use-send-message.ts – React hook for sending messages
  • features/chat/services/unread-count.service.ts – resetUnreadCount function
  • features/chat/components/room-pane/chat-message-list.tsx – Component that renders the message list