OpportunitiesEntities
    Docs
    Ring Platform

    Decentralized Self-building Future

    Sign In
    Entities
    Opportunities
    Store
    Docs
    Platform Concepts
    RING EconomySonoratek LLCGlobal ImpactAI Meets Web3
    Get Started
    Quick StartCalculatorRoadmap
    Privacy|Contact
    v1.106.26|Sonoratek LLC

    Documentation

    Concepts, value, and typical clone scenarios — less code.

    Welcome to Ring
    Quick Reference
    Getting Started
    Prerequisites
    Installation
    First Success Validation
    Next Steps
    Features
    Multi-Vendor Store
    Inventory & Stock
    Vendor Management
    Commissions & Settlements
    Membership & Credits
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Payments Overview
    Public Pools & DAO Jars
    WayForPay Payment Integration
    Wallet & Credit System
    WalletConductor
    Credit Rewards
    Affiliate & Referral Enablement
    Referral Codes (Refcodes)
    Page Curtain
    NFT Exhibition Marketplace
    Solana NFT Gates
    Token Staking System
    Owner Project Lab
    Entities
    Opportunities
    Real-Time Messaging
    Ring Tasks
    WebRTC Calls & STUNner TURN
    Peer Games
    News Module
    Member Blogs
    Public Profile Pages
    Profile Account Widgets
    Ring File Cabinet
    Username Reservation System
    Scientific Editor
    Notifications
    Push Notifications with FCM (Ring-Powered)
    Email AI-CRM
    Ring Mailer & RingdomX Mail
    Tunnel Protocol
    VideoConductor
    MediaConductor
    Generative Gallery
    Authentication
    Security & Compliance
    Admin console
    Admin Wiki
    Manage via Telegram
    Locale System
    Mobile Experience
    Performance Optimization Patterns
    Examples
    Quick Start
    Basic Setup
    White Label
    Custom Branding
    Web3 Integration
    Real World
    Advanced Features
    Customization
    Quick Start — Your First Ring Clone
    Customization Guide
    Vertical Presets (SSOT)
    Ringization playbook
    Branding
    Themes
    Features
    Localization
    Token Economics Setup
    Payment Gateway Integration
    Reference Ring deployments
    Project configuration
    Public environment variables
    Order Lab secrets
    WalletConnect Project ID (Reown Cloud)
    Supported services
    NODUS wiki (project knowledge)
    Configuration playbook
    Web3
    Token launch jurisdictions
    Wallet
    Wallet Security Tips
    Integrations
    Ethereum wallets (Wagmi v3)
    RingFileBase (object storage API)
    Ring CDN (RingFileBase edge)
    Deployment
    Self-hosted deployment
    Vercel Deployment
    Docker
    Environment Configuration
    Monitoring & Analytics
    Performance Optimization
    Backup & Recovery
    Architecture
    Data Model
    Security
    Real Time
    Discovery Mutation Sync
    PaymentConductor architecture
    WalletConductor architecture
    News Kingdom architecture
    Backend Services
    Firebase Integration
    Development
    Ring MCP Server
    OSS vs enterprise

    Quick entry (CTOs · auditors · agents)

    Welcome — mission & audiences
    Quick Reference
    Getting started
    Architecture & Auth.js
    Backend modes & databases (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Deploy (Docker · k8s)
    Security & compliance reads
    ringdom.org — LegioX homebase
    Source — MIT license (GitHub)

    Documentation

    Concepts, value, and typical clone scenarios — less code.

    Welcome to Ring
    Quick Reference
    Getting Started
    Prerequisites
    Installation
    First Success Validation
    Next Steps
    Features
    Multi-Vendor Store
    Inventory & Stock
    Vendor Management
    Commissions & Settlements
    Membership & Credits
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Payments Overview
    Public Pools & DAO Jars
    WayForPay Payment Integration
    Wallet & Credit System
    WalletConductor
    Credit Rewards
    Affiliate & Referral Enablement
    Referral Codes (Refcodes)
    Page Curtain
    NFT Exhibition Marketplace
    Solana NFT Gates
    Token Staking System
    Owner Project Lab
    Entities
    Opportunities
    Real-Time Messaging
    Ring Tasks
    WebRTC Calls & STUNner TURN
    Peer Games
    News Module
    Member Blogs
    Public Profile Pages
    Profile Account Widgets
    Ring File Cabinet
    Username Reservation System
    Scientific Editor
    Notifications
    Push Notifications with FCM (Ring-Powered)
    Email AI-CRM
    Ring Mailer & RingdomX Mail
    Tunnel Protocol
    VideoConductor
    MediaConductor
    Generative Gallery
    Authentication
    Security & Compliance
    Admin console
    Admin Wiki
    Manage via Telegram
    Locale System
    Mobile Experience
    Performance Optimization Patterns
    Examples
    Quick Start
    Basic Setup
    White Label
    Custom Branding
    Web3 Integration
    Real World
    Advanced Features
    Customization
    Quick Start — Your First Ring Clone
    Customization Guide
    Vertical Presets (SSOT)
    Ringization playbook
    Branding
    Themes
    Features
    Localization
    Token Economics Setup
    Payment Gateway Integration
    Reference Ring deployments
    Project configuration
    Public environment variables
    Order Lab secrets
    WalletConnect Project ID (Reown Cloud)
    Supported services
    NODUS wiki (project knowledge)
    Configuration playbook
    Web3
    Token launch jurisdictions
    Wallet
    Wallet Security Tips
    Integrations
    Ethereum wallets (Wagmi v3)
    RingFileBase (object storage API)
    Ring CDN (RingFileBase edge)
    Deployment
    Self-hosted deployment
    Vercel Deployment
    Docker
    Environment Configuration
    Monitoring & Analytics
    Performance Optimization
    Backup & Recovery
    Architecture
    Data Model
    Security
    Real Time
    Discovery Mutation Sync
    PaymentConductor architecture
    WalletConductor architecture
    News Kingdom architecture
    Backend Services
    Firebase Integration
    Development
    Ring MCP Server
    OSS vs enterprise

    Quick entry (CTOs · auditors · agents)

    Welcome — mission & audiences
    Quick Reference
    Getting started
    Architecture & Auth.js
    Backend modes & databases (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Deploy (Docker · k8s)
    Security & compliance reads
    ringdom.org — LegioX homebase
    Source — MIT license (GitHub)

    Documentation

    Concepts, value, and typical clone scenarios — less code.

    Welcome to Ring
    Quick Reference
    Getting Started
    Prerequisites
    Installation
    First Success Validation
    Next Steps
    Features
    Multi-Vendor Store
    Inventory & Stock
    Vendor Management
    Commissions & Settlements
    Membership & Credits
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Payments Overview
    Public Pools & DAO Jars
    WayForPay Payment Integration
    Wallet & Credit System
    WalletConductor
    Credit Rewards
    Affiliate & Referral Enablement
    Referral Codes (Refcodes)
    Page Curtain
    NFT Exhibition Marketplace
    Solana NFT Gates
    Token Staking System
    Owner Project Lab
    Entities
    Opportunities
    Real-Time Messaging
    Ring Tasks
    WebRTC Calls & STUNner TURN
    Peer Games
    News Module
    Member Blogs
    Public Profile Pages
    Profile Account Widgets
    Ring File Cabinet
    Username Reservation System
    Scientific Editor
    Notifications
    Push Notifications with FCM (Ring-Powered)
    Email AI-CRM
    Ring Mailer & RingdomX Mail
    Tunnel Protocol
    VideoConductor
    MediaConductor
    Generative Gallery
    Authentication
    Security & Compliance
    Admin console
    Admin Wiki
    Manage via Telegram
    Locale System
    Mobile Experience
    Performance Optimization Patterns
    Examples
    Quick Start
    Basic Setup
    White Label
    Custom Branding
    Web3 Integration
    Real World
    Advanced Features
    Customization
    Quick Start — Your First Ring Clone
    Customization Guide
    Vertical Presets (SSOT)
    Ringization playbook
    Branding
    Themes
    Features
    Localization
    Token Economics Setup
    Payment Gateway Integration
    Reference Ring deployments
    Project configuration
    Public environment variables
    Order Lab secrets
    WalletConnect Project ID (Reown Cloud)
    Supported services
    NODUS wiki (project knowledge)
    Configuration playbook
    Web3
    Token launch jurisdictions
    Wallet
    Wallet Security Tips
    Integrations
    Ethereum wallets (Wagmi v3)
    RingFileBase (object storage API)
    Ring CDN (RingFileBase edge)
    Deployment
    Self-hosted deployment
    Vercel Deployment
    Docker
    Environment Configuration
    Monitoring & Analytics
    Performance Optimization
    Backup & Recovery
    Architecture
    Data Model
    Security
    Real Time
    Discovery Mutation Sync
    PaymentConductor architecture
    WalletConductor architecture
    News Kingdom architecture
    Backend Services
    Firebase Integration
    Development
    Ring MCP Server
    OSS vs enterprise

    Quick entry (CTOs · auditors · agents)

    Welcome — mission & audiences
    Quick Reference
    Getting started
    Architecture & Auth.js
    Backend modes & databases (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Deploy (Docker · k8s)
    Security & compliance reads
    ringdom.org — LegioX homebase
    Source — MIT license (GitHub)
    Ring Logo

    Loading documentation...

    Preparing Ring content

    Ring Logo

    Loading documentation...

    Preparing Ring content

    Ring Logo

    Loading documentation...

    Preparing Ring content

    Notifications

    Ring tells members about new opportunities, messages, entity invitations, wallet events, calls and peer-game challenges. Every notification is stored once and delivered over the channels the member allows: the in-app inbox, push, email or SMS. Members control those channels in their preferences, including a quiet-hours window that now actually silences push and SMS at night.

    Use the Founder / Developer tabs in the docs sidebar to filter this page. Push setup (Firebase certificate, VAPID, iOS Home Screen) lives on Push Notifications (FCM).

    Status (2026-10-26): Quiet hours are enforced on the server. Mark all as read is a single SQL update and no longer times out on large inboxes. The open notifications page applies live inbox events in place instead of showing stale rows.

    BeforeNow
    Quiet hours were saved in preferences but pushes still arrivedPUSH and SMS are dropped inside the window unless the notification is urgent
    Mark all as read fetched up to 1000 rows and updated them one by oneOne bulk UPDATE marks every unread row and returns the count
    After mark all as read the list kept showing old unread itemsThe feed reloads after success and live read_all events clear it
    Long-poll clients aborted every empty poll after 15 secondsLong-poll timeout is 30 seconds, above the server's 20 second hold

    Why this matters for your community

    Notifications are how members come back. Too few and opportunities go unanswered; too many at 3 AM and members turn push off for good. Quiet hours let members keep push on without being woken up, and the urgent override keeps things like an incoming call alert working.

    Push delivery

    Chrome, Android and iOS Home Screen push, one delivery per device.

    Messaging

    Chat messages, calls and game invites raise typed notifications.

    Opportunities

    The AI Matcher notifies members who fit a new listing.

    Typical scenarios

    • A member sets quiet hours 22:00 to 08:00 in Kyiv time. A match notification created at 23:30 still lands in the in-app inbox and email, but no push buzzes the phone. In the morning the bell shows it as unread.

    Verified notification types (partial)

    TypePurpose
    OPPORTUNITYNew opportunities and applications
    MESSAGENew messages and conversations
    ENTITYEntity updates and invitations
    SYSTEMPlatform announcements
    WALLETTransaction and balance notifications
    GAME_REQUEST, GAME_UPDATEDPeer-game challenge and session updates. See Peer Games
    CALL_INVITEIncoming WebRTC call when the callee tab is hidden or closed

    Channel resolution

    Related documentation

    Push Notifications with FCM (Ring-Powered)

    Deep-dive: per-device FCM and Web Push fan-out.

    Notifications API

    Same-workflow: REST routes and preference payloads, including quietHours.

    Tunnel Protocol

    Depends-on: live inbox fan-out on notifications channels.

    WebRTC Calls & STUNner TURN

    See-also: CALL_INVITE uses the PUSH channel.

    Real-Time Messaging

    1. /
    2. /Notifications

    Updated Oct 26, 20265 min listen

    Notifications

    Ring tells members about new opportunities, messages, entity invitations, wallet events, calls and peer-game challenges. Every notification is stored once and delivered over the channels the member allows: the in-app inbox, push, email or SMS. Members control those channels in their preferences, including a quiet-hours window that now actually silences push and SMS at night.

    Use the Founder / Developer tabs in the docs sidebar to filter this page. Push setup (Firebase certificate, VAPID, iOS Home Screen) lives on Push Notifications (FCM).

    Status (2026-10-26): Quiet hours are enforced on the server. Mark all as read is a single SQL update and no longer times out on large inboxes. The open notifications page applies live inbox events in place instead of showing stale rows.

    BeforeNow
    Quiet hours were saved in preferences but pushes still arrivedPUSH and SMS are dropped inside the window unless the notification is urgent
    Mark all as read fetched up to 1000 rows and updated them one by oneOne bulk UPDATE marks every unread row and returns the count
    After mark all as read the list kept showing old unread itemsThe feed reloads after success and live read_all events clear it
    Long-poll clients aborted every empty poll after 15 secondsLong-poll timeout is 30 seconds, above the server's 20 second hold

    Why this matters for your community

    Notifications are how members come back. Too few and opportunities go unanswered; too many at 3 AM and members turn push off for good. Quiet hours let members keep push on without being woken up, and the urgent override keeps things like an incoming call alert working.

    Push delivery

    Chrome, Android and iOS Home Screen push, one delivery per device.

    Messaging

    Chat messages, calls and game invites raise typed notifications.

    Opportunities

    The AI Matcher notifies members who fit a new listing.

    Typical scenarios

    • A member sets quiet hours 22:00 to 08:00 in Kyiv time. A match notification created at 23:30 still lands in the in-app inbox and email, but no push buzzes the phone. In the morning the bell shows it as unread.

    Verified notification types (partial)

    TypePurpose
    OPPORTUNITYNew opportunities and applications
    MESSAGENew messages and conversations
    ENTITYEntity updates and invitations
    SYSTEMPlatform announcements
    WALLETTransaction and balance notifications
    GAME_REQUEST, GAME_UPDATEDPeer-game challenge and session updates. See Peer Games
    CALL_INVITEIncoming WebRTC call when the callee tab is hidden or closed

    Channel resolution

    Related documentation

    Push Notifications with FCM (Ring-Powered)

    Deep-dive: per-device FCM and Web Push fan-out.

    Notifications API

    Same-workflow: REST routes and preference payloads, including quietHours.

    Tunnel Protocol

    Depends-on: live inbox fan-out on notifications channels.

    WebRTC Calls & STUNner TURN

    See-also: CALL_INVITE uses the PUSH channel.

    Real-Time Messaging

    1. /
    2. /Notifications

    Updated Oct 26, 20265 min listen

    Notifications

    Ring tells members about new opportunities, messages, entity invitations, wallet events, calls and peer-game challenges. Every notification is stored once and delivered over the channels the member allows: the in-app inbox, push, email or SMS. Members control those channels in their preferences, including a quiet-hours window that now actually silences push and SMS at night.

    Use the Founder / Developer tabs in the docs sidebar to filter this page. Push setup (Firebase certificate, VAPID, iOS Home Screen) lives on Push Notifications (FCM).

    Status (2026-10-26): Quiet hours are enforced on the server. Mark all as read is a single SQL update and no longer times out on large inboxes. The open notifications page applies live inbox events in place instead of showing stale rows.

    BeforeNow
    Quiet hours were saved in preferences but pushes still arrivedPUSH and SMS are dropped inside the window unless the notification is urgent
    Mark all as read fetched up to 1000 rows and updated them one by oneOne bulk UPDATE marks every unread row and returns the count
    After mark all as read the list kept showing old unread itemsThe feed reloads after success and live read_all events clear it
    Long-poll clients aborted every empty poll after 15 secondsLong-poll timeout is 30 seconds, above the server's 20 second hold

    Why this matters for your community

    Notifications are how members come back. Too few and opportunities go unanswered; too many at 3 AM and members turn push off for good. Quiet hours let members keep push on without being woken up, and the urgent override keeps things like an incoming call alert working.

    Push delivery

    Chrome, Android and iOS Home Screen push, one delivery per device.

    Messaging

    Chat messages, calls and game invites raise typed notifications.

    Opportunities

    The AI Matcher notifies members who fit a new listing.

    Typical scenarios

    • A member sets quiet hours 22:00 to 08:00 in Kyiv time. A match notification created at 23:30 still lands in the in-app inbox and email, but no push buzzes the phone. In the morning the bell shows it as unread.

    Verified notification types (partial)

    TypePurpose
    OPPORTUNITYNew opportunities and applications
    MESSAGENew messages and conversations
    ENTITYEntity updates and invitations
    SYSTEMPlatform announcements
    WALLETTransaction and balance notifications
    GAME_REQUEST, GAME_UPDATEDPeer-game challenge and session updates. See Peer Games
    CALL_INVITEIncoming WebRTC call when the callee tab is hidden or closed

    Channel resolution

    Related documentation

    Push Notifications with FCM (Ring-Powered)

    Deep-dive: per-device FCM and Web Push fan-out.

    Notifications API

    Same-workflow: REST routes and preference payloads, including quietHours.

    Tunnel Protocol

    Depends-on: live inbox fan-out on notifications channels.

    WebRTC Calls & STUNner TURN

    See-also: CALL_INVITE uses the PUSH channel.

    Real-Time Messaging

    1. /
    2. /Notifications

    Updated Oct 26, 20265 min listen

  1. A busy vendor with thousands of unread items taps Mark all as read. It completes in one request and the list clears at once.
  2. Two tabs are open. Reading a notification in one tab marks it read in the other without a refresh.
  3. How one notification reaches a member

    createNotification in features/notifications/services/notification-service.ts loads the user's preferences once, then calls determineChannels(requested, preferences, priority) from features/notifications/lib/determine-channels.ts. Deliveries are built from that list, so a muted PUSH never reaches FCM.

    StepRule
    No preferences rowIN_APP always, plus PUSH when the caller asked for it
    Stored preferencesHonor channels.push and inApp opt-outs
    Quiet hourssuppressQuietChannels removes PUSH and SMS when isWithinQuietHours is true and priority is not URGENT. IN_APP and EMAIL stay

    Quiet hours contract

    Preferences store quietHours: { enabled, startTime, endTime, timezone } with times in HH:mm.

    • The current time is converted to the member's IANA timezone (fallback UTC).
    • The end time is exclusive. A start later than the end, such as 22:00 to 08:00, is an overnight window.
    • The check fails open: disabled, missing, malformed times, equal start and end, or an unreadable zone all mean "not quiet".
    • Priority defaults to NORMAL when the caller omits it. Send URGENT for anything that must interrupt.

    Inbox and read state

    PiecePathBehavior
    Mark all read HTTPapp/api/notifications/read-allCalls markAllNotificationsAsRead
    Bulk updatenotification-service.tsOne UPDATE notifications ... WHERE data->>'user_id' = $1 AND data->>'read_at' IS NULL through getSharedPgPool, then publishes the unread count
    Live patchfeatures/notifications/lib/apply-inbox-to-feed.tsApplies notification, read, read_all and delete tunnel payloads to the rows on screen, respecting the active type filter
    List UIfeatures/notifications/components/notification-list.tsxUses applyInboxToFeed for live events and reloads the cursor feed after mark all read

    The bulk update uses raw SQL on the notifications JSONB table, so it applies to PostgreSQL backends (k8s-postgres-fcm, supabase-fcm).

    Delivery channels

    • In-app: Tunnel notifications:inbox and the bell UI. On Vercel-style long polling, lib/tunnel/config.ts sets the client timeout to 30 seconds because /api/tunnel/poll holds empty polls for up to 20 seconds.
    • Push: FCM tokens (fcm_tokens) plus RFC Web Push (push_subscriptions). See Push Notifications (FCM).
    • Email and SMS: preference-gated where wired.

    Frequently asked questions

    Impact

    Do members lose notifications during quiet hours?

    No. Only push and SMS are skipped. The notification is still stored, shown in the inbox and sent by email if email is on.

    Migration

    Do I need a migration for the bulk mark-all-read?

    No. It uses the existing notifications table. Older clones on firebase-full should not rely on this path.

    Ops

    Why did a push arrive at night?

    Check that the member saved quiet hours with a valid zone, and whether the sender used URGENT priority, which bypasses the window by design.

    See-also: interactive notify that emits typed notifications.

    Page Curtain

    See-also: the other in-page prompt members see, with its own dismissal rules.

    Docs
    Features
  4. A busy vendor with thousands of unread items taps Mark all as read. It completes in one request and the list clears at once.
  5. Two tabs are open. Reading a notification in one tab marks it read in the other without a refresh.
  6. How one notification reaches a member

    createNotification in features/notifications/services/notification-service.ts loads the user's preferences once, then calls determineChannels(requested, preferences, priority) from features/notifications/lib/determine-channels.ts. Deliveries are built from that list, so a muted PUSH never reaches FCM.

    StepRule
    No preferences rowIN_APP always, plus PUSH when the caller asked for it
    Stored preferencesHonor channels.push and inApp opt-outs
    Quiet hourssuppressQuietChannels removes PUSH and SMS when isWithinQuietHours is true and priority is not URGENT. IN_APP and EMAIL stay

    Quiet hours contract

    Preferences store quietHours: { enabled, startTime, endTime, timezone } with times in HH:mm.

    • The current time is converted to the member's IANA timezone (fallback UTC).
    • The end time is exclusive. A start later than the end, such as 22:00 to 08:00, is an overnight window.
    • The check fails open: disabled, missing, malformed times, equal start and end, or an unreadable zone all mean "not quiet".
    • Priority defaults to NORMAL when the caller omits it. Send URGENT for anything that must interrupt.

    Inbox and read state

    PiecePathBehavior
    Mark all read HTTPapp/api/notifications/read-allCalls markAllNotificationsAsRead
    Bulk updatenotification-service.tsOne UPDATE notifications ... WHERE data->>'user_id' = $1 AND data->>'read_at' IS NULL through getSharedPgPool, then publishes the unread count
    Live patchfeatures/notifications/lib/apply-inbox-to-feed.tsApplies notification, read, read_all and delete tunnel payloads to the rows on screen, respecting the active type filter
    List UIfeatures/notifications/components/notification-list.tsxUses applyInboxToFeed for live events and reloads the cursor feed after mark all read

    The bulk update uses raw SQL on the notifications JSONB table, so it applies to PostgreSQL backends (k8s-postgres-fcm, supabase-fcm).

    Delivery channels

    • In-app: Tunnel notifications:inbox and the bell UI. On Vercel-style long polling, lib/tunnel/config.ts sets the client timeout to 30 seconds because /api/tunnel/poll holds empty polls for up to 20 seconds.
    • Push: FCM tokens (fcm_tokens) plus RFC Web Push (push_subscriptions). See Push Notifications (FCM).
    • Email and SMS: preference-gated where wired.

    Frequently asked questions

    Impact

    Do members lose notifications during quiet hours?

    No. Only push and SMS are skipped. The notification is still stored, shown in the inbox and sent by email if email is on.

    Migration

    Do I need a migration for the bulk mark-all-read?

    No. It uses the existing notifications table. Older clones on firebase-full should not rely on this path.

    Ops

    Why did a push arrive at night?

    Check that the member saved quiet hours with a valid zone, and whether the sender used URGENT priority, which bypasses the window by design.

    See-also: interactive notify that emits typed notifications.

    Page Curtain

    See-also: the other in-page prompt members see, with its own dismissal rules.

    Docs
    Features
  7. A busy vendor with thousands of unread items taps Mark all as read. It completes in one request and the list clears at once.
  8. Two tabs are open. Reading a notification in one tab marks it read in the other without a refresh.
  9. How one notification reaches a member

    createNotification in features/notifications/services/notification-service.ts loads the user's preferences once, then calls determineChannels(requested, preferences, priority) from features/notifications/lib/determine-channels.ts. Deliveries are built from that list, so a muted PUSH never reaches FCM.

    StepRule
    No preferences rowIN_APP always, plus PUSH when the caller asked for it
    Stored preferencesHonor channels.push and inApp opt-outs
    Quiet hourssuppressQuietChannels removes PUSH and SMS when isWithinQuietHours is true and priority is not URGENT. IN_APP and EMAIL stay

    Quiet hours contract

    Preferences store quietHours: { enabled, startTime, endTime, timezone } with times in HH:mm.

    • The current time is converted to the member's IANA timezone (fallback UTC).
    • The end time is exclusive. A start later than the end, such as 22:00 to 08:00, is an overnight window.
    • The check fails open: disabled, missing, malformed times, equal start and end, or an unreadable zone all mean "not quiet".
    • Priority defaults to NORMAL when the caller omits it. Send URGENT for anything that must interrupt.

    Inbox and read state

    PiecePathBehavior
    Mark all read HTTPapp/api/notifications/read-allCalls markAllNotificationsAsRead
    Bulk updatenotification-service.tsOne UPDATE notifications ... WHERE data->>'user_id' = $1 AND data->>'read_at' IS NULL through getSharedPgPool, then publishes the unread count
    Live patchfeatures/notifications/lib/apply-inbox-to-feed.tsApplies notification, read, read_all and delete tunnel payloads to the rows on screen, respecting the active type filter
    List UIfeatures/notifications/components/notification-list.tsxUses applyInboxToFeed for live events and reloads the cursor feed after mark all read

    The bulk update uses raw SQL on the notifications JSONB table, so it applies to PostgreSQL backends (k8s-postgres-fcm, supabase-fcm).

    Delivery channels

    • In-app: Tunnel notifications:inbox and the bell UI. On Vercel-style long polling, lib/tunnel/config.ts sets the client timeout to 30 seconds because /api/tunnel/poll holds empty polls for up to 20 seconds.
    • Push: FCM tokens (fcm_tokens) plus RFC Web Push (push_subscriptions). See Push Notifications (FCM).
    • Email and SMS: preference-gated where wired.

    Frequently asked questions

    Impact

    Do members lose notifications during quiet hours?

    No. Only push and SMS are skipped. The notification is still stored, shown in the inbox and sent by email if email is on.

    Migration

    Do I need a migration for the bulk mark-all-read?

    No. It uses the existing notifications table. Older clones on firebase-full should not rely on this path.

    Ops

    Why did a push arrive at night?

    Check that the member saved quiet hours with a valid zone, and whether the sender used URGENT priority, which bypasses the window by design.

    See-also: interactive notify that emits typed notifications.

    Page Curtain

    See-also: the other in-page prompt members see, with its own dismissal rules.

    Docs
    Features