ワンクリックで
notifications
Reference for the notification system. Use when adding new notification types or modifying notification handling.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Reference for the notification system. Use when adding new notification types or modifying notification handling.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Generate a manual preview/test harness page for the post-item list components. Use when you want to visually preview PublicationPostItem Small/Medium/Large across the PostsListBlock, StandardSitePostBlock, and reader feed layouts, with toggles for highlight-first-post, card border, cover image, publication footer, and a page-width slider.
Update the app's default theme colors (accent, background, primary, highlights) consistently across every place a default is hardcoded. Use when changing the default accent/background/highlight colors so no surface (portaled modals, emails, presets, CSS fallbacks) drifts out of sync.
Generate a manual preview/test harness page for the Subscribe button components. Use when you want to visually preview SubscribeButton / SubscribeInput across logged-in/out and newsletter-mode variants, with checkboxes for whether the viewer has an email / atproto handle.
Reference for the AT Protocol lexicon system. Use when working with lexicons, adding new record types, or modifying AT Protocol schemas.
Draft design documents and specs with research-informed questioning
| name | notifications |
| description | Reference for the notification system. Use when adding new notification types or modifying notification handling. |
| user-invocable | false |
Notifications are stored in the database and hydrated with related data before being rendered. The system supports multiple notification types (comments, subscriptions, etc.) that are processed in parallel.
src/notifications.ts - Core notification types and hydration logicapp/(home-pages)/notifications/NotificationList.tsx - Renders all notification typesapp/(home-pages)/notifications/Notification.tsx - Base notification componentCommentNotification.tsx, FollowNotification.tsx)src/notifications.ts)Add your type to the NotificationData union:
export type NotificationData =
| { type: "comment"; comment_uri: string; parent_uri?: string }
| { type: "subscribe"; subscription_uri: string }
| { type: "your_type"; your_field: string }; // Add here
Add to the HydratedNotification union:
export type HydratedNotification =
| HydratedCommentNotification
| HydratedSubscribeNotification
| HydratedYourNotification; // Add here
src/notifications.ts)export type HydratedYourNotification = Awaited<
ReturnType<typeof hydrateYourNotifications>
>[0];
async function hydrateYourNotifications(notifications: NotificationRow[]) {
const yourNotifications = notifications.filter(
(n): n is NotificationRow & { data: ExtractNotificationType<"your_type"> } =>
(n.data as NotificationData)?.type === "your_type",
);
if (yourNotifications.length === 0) return [];
// Fetch related data with joins
const { data } = await supabaseServerClient
.from("your_table")
.select("*, related_table(*)")
.in("uri", yourNotifications.map((n) => n.data.your_field));
return yourNotifications.map((notification) => ({
id: notification.id,
recipient: notification.recipient,
created_at: notification.created_at,
type: "your_type" as const,
your_field: notification.data.your_field,
yourData: data?.find((d) => d.uri === notification.data.your_field)!,
}));
}
Add to hydrateNotifications parallel array:
const [commentNotifications, subscribeNotifications, yourNotifications] = await Promise.all([
hydrateCommentNotifications(notifications),
hydrateSubscribeNotifications(notifications),
hydrateYourNotifications(notifications), // Add here
]);
const allHydrated = [...commentNotifications, ...subscribeNotifications, ...yourNotifications];
import { Notification, pingIdentityToUpdateNotification } from "src/notifications";
import { v7 } from "uuid";
// When the event occurs:
const recipient = /* determine who should receive it */;
if (recipient !== currentUser) {
const notification: Notification = {
id: v7(),
recipient,
data: {
type: "your_type",
your_field: "value",
},
};
await supabaseServerClient.from("notifications").insert(notification);
await pingIdentityToUpdateNotification(recipient);
}
Create a new component (e.g., YourNotification.tsx):
import { HydratedYourNotification } from "src/notifications";
import { Notification } from "./Notification";
export const YourNotification = (props: HydratedYourNotification) => {
// Extract data from props.yourData
return (
<Notification
timestamp={props.created_at}
href={/* link to relevant page */}
icon={/* icon or avatar */}
actionText={<>Message to display</>}
content={/* optional additional content */}
/>
);
};
NotificationList.tsx)Import and render your notification type:
import { YourNotification } from "./YourNotification";
// In the map function:
if (n.type === "your_type") {
return <YourNotification key={n.id} {...n} />;
}
See the implementation in:
src/notifications.ts:88-125 - Hydration logicapp/lish/subscribeToPublication.ts:55-68 - Triggerapp/(home-pages)/notifications/FollowNotification.tsx - Componentapp/(home-pages)/notifications/NotificationList.tsx:40-42 - Rendering