Conversation
Add digest post type support (Phase 1 & 2): - Add PostType.Digest enum value and DIGEST_SOURCE constant - Add digestPostIds and ad fields to PostFlags type and GraphQL fragments - Create DigestPostContent component that renders a feed of curated posts - Register in CONTENT_MAP and FeedItemComponent card type maps Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Inject stored Skadi ads into the digest feed via a new staticAd prop on Feed/useFeed, and add in-app notification controls for digest posts. Phase 3 – Ad injection: - Add staticAd support to useFeed and FeedProps - Transform DigestPostAd → Ad interface in DigestPostContent - Fix missing PostType.Digest in PostModalMap Phase 4 – Notification settings: - Add NotificationType.DigestReady - Create DigestNotification component for in-app toggle - Add digest section to InAppNotificationsTab - Update PersonalizedDigest unsubscribe logic to respect in-app channel Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…etely Extract transformDigestAd to digest/utils.ts for testability and add unit tests for the digest ad transformation and notification muting logic. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
API returns camelCase (companyName, companyLogo, callToAction) instead of snake_case. Update type, fragments, transform utils, and tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@claude review |
|
Claude finished @capJavert's task in 2m 53s —— View job PR Review: Feat/digest post type
Overall this is a solid implementation. The feature decomposition is clean — the Issues1. Static ad injected among loading placeholders [ The static ad is inserted into // current — ad can appear among placeholders
if (settings?.staticAd && newItems.length > 0) {
// fix — only inject ad when real posts exist
if (settings?.staticAd && feedQuery.data && newItems.length > 0) {2.
3. export const DIGEST_SOURCE = 'digest';This was added (mirroring 4. The 5. newItems.splice(insertAt, 0, {
type: FeedItemType.Ad,
ad: settings.staticAd.ad,
index: 0, // ← always 0
...
} as AdItem);The Minor Notes
TestsGood coverage on |
- Only inject static ad when real feed data exists, not during loading - Remove digest fields from SHARED_POST_INFO_FRAGMENT (only needed in FEED_POST_FRAGMENT) - Remove unused DIGEST_SOURCE constant Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Override insaneMode via SettingsContext.Provider to force list layout in digest post feed. Add disableAdRefresh prop to hide reload button on static ads. Add digestPostIds and ad fields to SHARED_POST_INFO_FRAGMENT. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Digest to NotificationAvatarType enum and render BriefIcon for digest notifications so the avatar displays correctly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show BriefUpgradeAlert below digest feed for non-Plus users. Add text prop to BriefUpgradeAlert for customizable copy. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Map companyLogo and callToAction from digest ad data to Ad interface. Use companyLogo as favicon when available. Render callToAction as a primary button in AdList/AdGrid with refresh+remove grouped on the right. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@claude review one more time, especially focus on notification settings page changes in regards to how brief works and now digest |
|
Claude finished @capJavert's task in 4m 15s —— View job PR Review: Notification Settings — Digest vs. Brief
Here's a focused review of the notification settings changes, tracing the full cross-channel logic across the three interacting components. Architecture OverviewThe settings page now has this structure:
Issues1.
} else if (!briefDigest) {
unsubscribePersonalizedDigest({ type: UserPersonalizedDigestType.Digest }); // ← destroys Digest
subscribePersonalizedDigest({ type: UserPersonalizedDigestType.Brief, sendType: SendType.Daily });
}With
After step 2, the Digest in-app switch still shows on (because This is pre-existing code in The fix would be to remove the 2. const emailActive = ns?.[NotificationType.BriefingReady]?.email === 'subscribed';
if (isChecked && !emailActive) {
unsubscribePersonalizedDigest({ type: UserPersonalizedDigestType.Digest });
}For a non-Plus user this is correct: Whether this causes a real problem depends on whether the backend delivers digest emails based on the subscription record or based on 3. The change from "always unsubscribe on email toggle off" to "only unsubscribe when in-app is also off" is the right cross-channel preservation logic: // Before
unsubscribePersonalizedDigest({ type: UserPersonalizedDigestType.Digest });
// After
const digestInAppActive = ns?.[NotificationType.DigestReady]?.inApp === 'subscribed';
if (!digestInAppActive) {
unsubscribePersonalizedDigest({ type: UserPersonalizedDigestType.Digest });
}This mirrors the symmetric logic in 4. const onToggleDigest = () => {
toggleSetting(NotificationType.DigestReady, 'inApp');
onLogToggle(isChecked, NotificationCategory.Digest); // ← passes current (pre-toggle) state
event_name: isEnabled ? LogEvent.EnableNotification : LogEvent.DisableNotificationWhen user is disabling (isChecked = true), this fires SummaryThe core logic — mutual cross-channel preservation between |
Add missing companyLogo and callToAction fields to transformDigestAd test expectations. Remove trailing blank line in types.ts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevent the upgrade alert from flashing before the digest feed content is ready by gating it on query completion state. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cription toggles DigestNotification could create a Digest subscription alongside an existing Brief subscription for Plus users, causing double emails and posts. Now enabling one type properly replaces the other and clears the stale in-app preference across all three toggle surfaces (DigestNotification, PresidentialBriefingNotification, PersonalizedDigest email radio). Also fixes onLogToggle passing pre-toggle state in DigestNotification and PersonalizedDigest, which logged the wrong event name. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Changes
API: dailydotdev/daily-api#3635
Summary
PostType.Digestthat renders a curated feed of posts at/posts/:idusingDigestPostContentcomponentstaticAdprop onuseFeed/FeedNotificationType.DigestReadywith in-app notification toggle and cross-channel unsubscribe logic (only fully unsubscribes when both email and in-app are off)Changes
PostType.Digestenum,DigestPostAdtype, updated post flags fragment withdigestPostIdsandadtransformDigestAdmaps backend ad shape to frontendAdinterface;staticAdparam onuseFeedinserts it at the correct index while keeping live ads disabledDigestReadynotification type,DigestNotificationcomponent for in-app tab, updatedPersonalizedDigestemail tab with cross-channel muting awarenesstransformDigestAdandisMutingDigestCompletelyTest plan
/posts/:digest-post-idand verify the curated feed renders with post cardsflags.adis nullpnpm --filter shared test— 13 new tests passEvents
Did you introduce any new tracking events?
Experiment
Did you introduce any new experiments?
Manual Testing
Caution
Please make sure existing components are not breaking/affected by this PR
Preview domain
https://feat-digest-post-type.preview.app.daily.dev