Unread Tracking

Real-time unread message counter and read receipt tracker for Convex with watermark-based read positions and React hooks.

Installation

npm install convex-unread-tracking

About Unread Tracking

**Full-featured read tracking for chat and messaging apps.**

Drop-in unread state management using a watermark system with explicit per-message overrides.

- Per-user, per-channel read positions
- Message accounting & subscription management
- Muted senders, channel archival & group ops
- Automatic cleanup via built-in crons

Includes React hooks with optimistic mark-as-read and localStorage offline support.

Benefits

Use cases

how to track unread messages in Convex chat app

Use convex-unread-tracking to register messages with insertMessage() when sent, then call getUnreadCount() to get real-time unread counts per channel. The component tracks read positions using watermarks and provides automatic cleanup via crons.

Convex read receipts and message tracking

The component provides markReadUpTo() for watermark-based read tracking and getLastRead() for scroll anchoring. It supports explicit range overrides with markReadRange() and single message unread marking with markOneUnread().

bulk message subscriptions Convex teams

Use group operations like addToGroup() and subscribeAll() to manage team-wide channel subscriptions. The component supports muting senders with muteSender() and archiving entire channels with archive().

optimistic UI unread messages React Convex

The useMarkAsRead and useOptimisticUnreadCount hooks provide immediate UI feedback when marking messages as read, with localStorage fallback for offline scenarios. Call markRead() optimistically, then confirmRead() after server sync.

Frequently asked questions

How does the watermark system work for read tracking?

The convex-unread-tracking component uses timestamps as watermarks to mark everything up to a specific time as read via markReadUpTo(). You can override this with explicit ranges using markReadRange() or mark individual messages unread with markOneUnread().

Can I track unread counts across multiple channels at once?

Yes, convex-unread-tracking provides getTotalUnreadCount() for aggregate counts across all user subscriptions and getSingleUnreads() for batch fetching per-channel counts. Both methods work with the subscription management system.

How do I handle team-wide channel subscriptions?

Use the group operations in convex-unread-tracking: addToGroup() to add users to a group, then subscribeAll() or unsubscribeAll() to manage entire team subscriptions to channels in bulk operations.

Does this component handle message cleanup automatically?

Yes, convex-unread-tracking includes a cleanup mutation designed for Convex cron jobs. Set up a daily cron to automatically garbage collect old tracking data and maintain database performance.

How do the React hooks handle offline scenarios?

The convex-unread-tracking React hooks use localStorage to persist optimistic state when offline. Call markRead() for immediate UI updates, then confirmRead() once the server mutation succeeds to sync the optimistic state.

Links