mit einem Klick
notifications
// Reference for the notification system. Use when adding new notification types or modifying notification handling.
// Reference for the notification system. Use when adding new notification types or modifying notification handling.
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