Skip to main content

Platform Announcements

Communicate important information to users through platform-wide announcements and notifications.

Overview

Platform announcements allow administrators to:

  • Notify users of new features
  • Announce maintenance windows
  • Share important updates
  • Communicate policy changes
  • Celebrate milestones

Current Implementation Status

Note: BookWish does not currently have a formal announcement system implemented. This guide outlines recommended approaches and best practices for when the system is built.

Announcement Types

System Announcements

Maintenance Notifications:

  • Scheduled downtime
  • Performance upgrades
  • Database migrations
  • Feature deployments

System Issues:

  • Current outages
  • Degraded performance
  • Known bugs
  • Workarounds

Feature Announcements

New Features:

  • Major feature launches
  • Enhanced functionality
  • UI/UX improvements
  • New integrations

Feature Changes:

  • Deprecation notices
  • Breaking changes
  • Migration guides
  • Timeline for changes

Policy Announcements

Policy Updates:

  • Terms of Service changes
  • Privacy Policy updates
  • Community Guidelines revisions
  • Fee structure changes

Compliance:

  • Legal requirements
  • Regulatory changes
  • Geographic restrictions
  • Age restrictions

Community Announcements

Platform Milestones:

  • User growth milestones
  • Feature usage stats
  • Success stories
  • Thank you messages

Events & Promotions:

  • Platform events
  • Promotional periods
  • Contests or giveaways
  • Partner announcements

Database Schema

CREATE TABLE announcements (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
title VARCHAR(255) NOT NULL,
message TEXT NOT NULL,
type VARCHAR(50) NOT NULL, -- 'info', 'warning', 'error', 'success'
priority VARCHAR(50), -- 'low', 'medium', 'high', 'urgent'

-- Targeting
target_tiers TEXT[], -- ['free', 'premium'], NULL = all
target_user_ids TEXT[], -- Specific users, NULL = all

-- Scheduling
start_at TIMESTAMP NOT NULL,
end_at TIMESTAMP, -- NULL = no expiration

-- Display settings
dismissible BOOLEAN DEFAULT true,
show_banner BOOLEAN DEFAULT false,
show_notification BOOLEAN DEFAULT true,
require_acknowledgment BOOLEAN DEFAULT false,

-- Tracking
created_by VARCHAR(255) NOT NULL, -- Admin user ID
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE announcement_reads (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
announcement_id UUID NOT NULL REFERENCES announcements(id) ON DELETE CASCADE,
user_id VARCHAR(255) NOT NULL,
read_at TIMESTAMP DEFAULT NOW(),
acknowledged_at TIMESTAMP,
UNIQUE(announcement_id, user_id)
);

CREATE INDEX idx_announcements_active ON announcements(start_at, end_at);
CREATE INDEX idx_announcement_reads_user ON announcement_reads(user_id);

Announcement Model

interface Announcement {
id: string;
title: string;
message: string;
type: 'info' | 'warning' | 'error' | 'success';
priority: 'low' | 'medium' | 'high' | 'urgent';

// Targeting
targetTiers?: UserTier[];
targetUserIds?: string[];

// Scheduling
startAt: Date;
endAt?: Date;

// Display
dismissible: boolean;
showBanner: boolean;
showNotification: boolean;
requireAcknowledgment: boolean;

// Meta
createdBy: string;
createdAt: Date;
updatedAt: Date;
}

Creating Announcements

General Announcement

All Users:

INSERT INTO announcements (
title,
message,
type,
priority,
start_at,
dismissible,
created_by
) VALUES (
'New Feature: Dark Mode',
'Dark mode is now available in settings! Toggle between light and dark themes to match your preference.',
'info',
'medium',
NOW(),
true,
'admin_user_id'
);

Maintenance Announcement

Scheduled Downtime:

INSERT INTO announcements (
title,
message,
type,
priority,
start_at,
end_at,
dismissible,
show_banner,
created_by
) VALUES (
'Scheduled Maintenance - Dec 15',
'BookWish will be undergoing scheduled maintenance on December 15 from 2:00 AM to 4:00 AM EST. The platform will be unavailable during this time. We apologize for any inconvenience.',
'warning',
'high',
NOW(),
'2025-12-15 04:00:00',
false,
true,
'admin_user_id'
);

Targeted Announcement

Premium Users Only:

INSERT INTO announcements (
title,
message,
type,
priority,
target_tiers,
start_at,
created_by
) VALUES (
'New Premium Feature: Unlimited Collections',
'Thank you for being a premium subscriber! You now have access to unlimited book collections. Create as many custom collections as you want to organize your reading.',
'success',
'medium',
ARRAY['premium'],
NOW(),
'admin_user_id'
);

Store Owners Only:

INSERT INTO announcements (
title,
message,
type,
priority,
target_tiers,
start_at,
show_banner,
created_by
) VALUES (
'New Store Feature: Bulk Import',
'You can now bulk import inventory using CSV files! Visit your store dashboard to try this time-saving feature.',
'info',
'high',
ARRAY['bookstore'],
NOW(),
true,
'admin_user_id'
);

Urgent Announcement

Critical Issue:

INSERT INTO announcements (
title,
message,
type,
priority,
start_at,
dismissible,
show_banner,
require_acknowledgment,
created_by
) VALUES (
'Security Update Required',
'We have detected a security issue affecting some accounts. Please reset your password immediately. Click here to reset: [link]',
'error',
'urgent',
NOW(),
false,
true,
true,
'admin_user_id'
);

Managing Announcements

Viewing Active Announcements

All Active:

SELECT * FROM announcements
WHERE start_at <= NOW()
AND (end_at IS NULL OR end_at > NOW())
ORDER BY priority DESC, start_at DESC;

By Type:

SELECT * FROM announcements
WHERE type = 'warning'
AND start_at <= NOW()
AND (end_at IS NULL OR end_at > NOW());

By Tier:

SELECT * FROM announcements
WHERE 'premium' = ANY(target_tiers)
OR target_tiers IS NULL -- Include announcements for all users
AND start_at <= NOW()
AND (end_at IS NULL OR end_at > NOW());

Updating Announcements

Update Message:

UPDATE announcements
SET message = 'Updated message content',
updated_at = NOW()
WHERE id = 'announcement_id';

Extend Duration:

UPDATE announcements
SET end_at = '2025-12-20 00:00:00',
updated_at = NOW()
WHERE id = 'announcement_id';

Change Priority:

UPDATE announcements
SET priority = 'urgent',
updated_at = NOW()
WHERE id = 'announcement_id';

Ending Announcements

End Immediately:

UPDATE announcements
SET end_at = NOW(),
updated_at = NOW()
WHERE id = 'announcement_id';

Delete Announcement:

-- Only delete if not started or mistakenly created
DELETE FROM announcements
WHERE id = 'announcement_id';

Delivery Methods

In-App Banner

Top Banner:

  • Displayed at top of app/website
  • Visible on all pages
  • Color-coded by type (info=blue, warning=yellow, error=red)
  • Can be dismissed (if dismissible)

Implementation:

// Frontend component
function AnnouncementBanner() {
const announcements = useAnnouncements({ showBanner: true });

if (!announcements.length) return null;

return (
<div className="announcement-banner">
{announcements.map(a => (
<Banner
key={a.id}
type={a.type}
message={a.message}
dismissible={a.dismissible}
onDismiss={() => markRead(a.id)}
/>
))}
</div>
);
}

Push Notifications

Mobile/Browser Notifications:

  • Sent when announcement published
  • Respects user notification preferences
  • Can be targeted by tier
  • Tracked for delivery/open rates

Implementation:

// When creating announcement
async function publishAnnouncement(announcement: Announcement) {
await db.announcements.insert(announcement);

if (announcement.showNotification) {
await pushService.sendToUsers({
title: announcement.title,
body: announcement.message,
targetTiers: announcement.targetTiers,
targetUserIds: announcement.targetUserIds,
});
}
}

Email Notifications

Critical Announcements:

  • Sent for urgent/high-priority items
  • Respects email preferences
  • Formatted email template
  • Tracking for opens/clicks

When to Email:

  • Urgent security issues
  • Major breaking changes
  • Extended outages
  • Critical policy updates

In-App Notification Center

Notification Inbox:

  • List of all announcements for user
  • Mark as read
  • Archive/dismiss
  • Link to full details

Implementation:

GET /api/announcements
Authorization: Bearer <user_token>

Response:
{
"announcements": [
{
"id": "...",
"title": "...",
"message": "...",
"type": "info",
"read": false,
"createdAt": "..."
}
]
}

Targeting Announcements

By User Tier

Free Users:

target_tiers = ARRAY['free']

Premium Users:

target_tiers = ARRAY['premium']

Store Owners:

target_tiers = ARRAY['bookstore']

Multiple Tiers:

target_tiers = ARRAY['premium', 'bookstore']

All Users:

target_tiers = NULL

By Specific Users

Beta Testers:

target_user_ids = ARRAY['user1', 'user2', 'user3']

Affected Users:

-- Users affected by specific issue
target_user_ids = (
SELECT ARRAY_AGG(user_id)
FROM affected_users_table
WHERE condition = true
)

By Geography

Note: Requires user location data

-- Store in announcement metadata or separate field
metadata = {
"targetCountries": ["US", "CA"],
"targetRegions": ["NA"]
}

Scheduling Announcements

Immediate Announcement

start_at = NOW()
end_at = NULL -- No end date

Scheduled Start

start_at = '2025-12-15 09:00:00'  -- Future date
end_at = NULL

Limited Duration

start_at = NOW()
end_at = NOW() + INTERVAL '7 days' -- Expires in 7 days

Recurring Announcements

Manual Recurring:

  • Create new announcement each time
  • Copy from template
  • Adjust dates

Automated Recurring (Future):

-- Potential future schema
recurrence_rule = 'WEEKLY' -- or 'MONTHLY', 'DAILY'
recurrence_end_date = '2026-01-01'

Tracking & Analytics

Read Rates

Announcement Read Rate:

SELECT a.title,
COUNT(DISTINCT ar.user_id) as read_count,
(SELECT COUNT(*) FROM users WHERE tier = ANY(a.target_tiers OR ARRAY['free', 'premium', 'bookstore', 'admin'])) as target_count
FROM announcements a
LEFT JOIN announcement_reads ar ON a.id = ar.announcement_id
WHERE a.id = 'announcement_id'
GROUP BY a.id, a.title;

Acknowledgment Tracking

For Critical Announcements:

SELECT a.title,
COUNT(ar.user_id) FILTER (WHERE ar.acknowledged_at IS NOT NULL) as acknowledged,
COUNT(ar.user_id) as read
FROM announcements a
LEFT JOIN announcement_reads ar ON a.id = ar.announcement_id
WHERE a.require_acknowledgment = true
GROUP BY a.id, a.title;

Engagement Metrics

Click-Through Rates:

  • Track links in announcement
  • Monitor user actions
  • Measure effectiveness

Best Practices

Writing Announcements

Be Clear and Concise:

  • Lead with the most important info
  • Use simple language
  • Avoid jargon
  • Include call-to-action

Be Timely:

  • Announce features when ready
  • Give advance notice for changes
  • Update status regularly
  • Archive old announcements

Be Helpful:

  • Explain the impact
  • Provide next steps
  • Link to more information
  • Offer support contact

Frequency

Don't Over-Announce:

  • Combine related updates
  • Avoid announcement fatigue
  • Respect user attention
  • Use appropriate channels

Priority Levels:

  • Reserve "urgent" for critical issues
  • Use "high" sparingly
  • Most should be "medium" or "low"

Testing

Before Publishing:

  • Preview the announcement
  • Test on different devices
  • Check targeting logic
  • Verify links work
  • Proofread carefully

Announcement Templates

New Feature Launch

Title: New Feature: [Feature Name]
Message: We're excited to announce [feature name]! [Brief description of what it does and why it's valuable]. [How to access/use it]. Learn more: [link]
Type: info
Priority: medium

Maintenance Window

Title: Scheduled Maintenance - [Date]
Message: BookWish will undergo scheduled maintenance on [date] from [start time] to [end time] [timezone]. The platform will be unavailable during this period. We apologize for any inconvenience and appreciate your patience.
Type: warning
Priority: high
Show Banner: true

Security Issue

Title: Important Security Update
Message: We've identified a security issue affecting [scope]. Please [required action] immediately. [What we're doing]. Questions? Contact security@bookwish.com
Type: error
Priority: urgent
Require Acknowledgment: true
Show Banner: true

Policy Update

Title: Updated Terms of Service
Message: We've updated our Terms of Service to [reason]. Key changes include: [bullet points]. The new terms take effect [date]. Review full terms: [link]
Type: info
Priority: medium

Admin API Endpoints

Proposed Endpoints

Create Announcement:

POST /api/admin/announcements
Authorization: Bearer <admin_token>
Content-Type: application/json

{
"title": "Announcement Title",
"message": "Announcement message",
"type": "info",
"priority": "medium",
"targetTiers": ["premium"],
"startAt": "2025-12-15T09:00:00Z"
}

List Announcements:

GET /api/admin/announcements
GET /api/admin/announcements?active=true
GET /api/admin/announcements?type=warning
Authorization: Bearer <admin_token>

Update Announcement:

PUT /api/admin/announcements/:id
Authorization: Bearer <admin_token>
Content-Type: application/json

{
"message": "Updated message",
"endAt": "2025-12-20T00:00:00Z"
}

Delete Announcement:

DELETE /api/admin/announcements/:id
Authorization: Bearer <admin_token>

Get Analytics:

GET /api/admin/announcements/:id/analytics
Authorization: Bearer <admin_token>

Response:
{
"reads": 1500,
"acknowledged": 1200,
"targetUsers": 2000,
"readRate": 75
}

Next Steps