diff --git a/HISTORY.md b/HISTORY.md
index c626b18..92084d7 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -21,7 +21,7 @@
- **Profile display-name persistence** — Profile name updates now save to `users.display_name` in the database and are returned consistently as `display_name`, `displayName`, and `name` aliases from auth/profile responses. The Profile page and Sidebar now display the saved name reliably after reloads and new sessions, with profile route coverage added.
-- **Private calendar subscription feed** — Added a token-protected `feed.ics` calendar subscription flow for Apple Calendar, Google Calendar/Android, Outlook, and generic ICS clients. Settings now has a Calendar Feed card with create, copy, regenerate, revoke, and preview actions, plus platform guidance and bearer-link privacy copy. The Calendar page includes an Add All entry point that routes users to the subscription setup. The public feed endpoint does not require session cookies, uses stable per-bill-cycle event UIDs to avoid duplicate subscribed events, emits all-day DATE events with CRLF/no-BOM/no-VTIMEZONE ICS output, and is backed by the new idempotent `calendar_tokens` migration.
+- **Private calendar subscription feed** — Added a token-protected `feed.ics` calendar subscription flow for Apple Calendar, Google Calendar/Android, Outlook, and generic ICS clients. The Calendar page now opens an in-place "Subscribe Calendar" dialog that explains what will happen, previews upcoming feed events, and lets users create/copy the feed without losing context. Settings keeps the Calendar Feed management card with regenerate, revoke, preview, platform guidance, and bearer-link privacy copy. The public feed endpoint does not require session cookies, uses stable per-bill-cycle event UIDs to avoid duplicate subscribed events, emits all-day DATE events with CRLF/no-BOM/no-VTIMEZONE ICS output, and is backed by the new idempotent `calendar_tokens` migration.
- **Improved unmatch flow — choice dialog + bulk deselect** — Clicking Unmatch on a linked transaction in the Bill modal now opens a two-option choice dialog instead of immediately removing the match. Option 1 ("Unmatch this payment only") confirms via a single AlertDialog and removes only that transaction. Option 2 ("Review all similar matches") fetches all linked transactions for the bill whose payee normalizes to the same prefix and opens a checklist dialog where each similar match is pre-checked. Users can deselect individual transactions to keep them matched, use All/None quick-selects, and optionally check a "Remove merchant rule" checkbox (shown only when a merchant rule matching the payee pattern exists on the bill). The confirm button shows the count of selected transactions and is disabled when nothing is selected. New backend endpoint `POST /api/transactions/unmatch-bulk` handles mixed `provider_sync` (restores balance + soft-deletes payment) and `transaction_match` (standard unmatch service) entries in a single database transaction.
diff --git a/client/components/CalendarFeedManager.jsx b/client/components/CalendarFeedManager.jsx
new file mode 100644
index 0000000..36cc361
--- /dev/null
+++ b/client/components/CalendarFeedManager.jsx
@@ -0,0 +1,226 @@
+import React, { useCallback, useEffect, useState } from 'react';
+import { Link } from 'react-router-dom';
+import { CalendarDays, Copy, Eye, KeyRound, RefreshCw, ShieldOff, Settings2 } from 'lucide-react';
+import { toast } from 'sonner';
+import { api } from '@/api';
+import { cn } from '@/lib/utils';
+import { Button } from '@/components/ui/button';
+import { Input } from '@/components/ui/input';
+
+function PlatformNote({ title, children }) {
+ return (
+
Generate a private feed URL for your bill calendar.
+
+
+
2. Copy
+
Paste it into Apple, Google, Outlook, or Android calendar setup.
+
+
+
3. Subscribe
+
Your calendar app refreshes bill due dates when it checks the feed.
+
+
+
+ )}
+
+ {!loading && active && (
+ <>
+
+ Anyone with this URL can see the bill events in this feed. Regenerate or revoke it if it was shared somewhere it should not be.
+
+
+
+
+
+
+
+
+
+
+ Add a calendar subscription with the copied URL. The feed uses all-day dates to avoid timezone shifts.
+
+
+ In Google Calendar on the web, use Other calendars, From URL. Android follows Google Calendar sync.
+
+
+ Subscribe from Outlook on the web with this URL. Imported copies will not update; subscriptions will.
+
+
+ Bill Tracker emits stable event IDs per bill cycle so subscribed calendars can update without double-adding events.
+
+
+
+
+
+
Next events that will appear
+
+ Last fetched: {feed.last_used_at ? new Date(feed.last_used_at).toLocaleString() : 'Not yet'}
+
+