From 58ccc746a5409c66030b73eb01ef8b276a748a27 Mon Sep 17 00:00:00 2001 From: "prompt.ac/@jeffrey" Date: Wed, 9 Sep 2026 16:47:16 -0400 Subject: [PATCH] push: a sender keeps its own notification icon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit webPayload stamped the aesthetic.computer mark onto every notification, so a caller that passed an icon of its own watched it get overwritten on the way out — and the service worker's own fallback could never fire, because note.icon was always already set. Default to the mark, honor an icon when one is given, and let the diary and its chat name the face they wanted. The chat instance carries it in its config beside its topic; undefined keeps the default. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01AGbWC1RD3FzZTgbW7S4zDx --- session-server/chat-manager.mjs | 3 +++ shared/push.mjs | 7 +++++-- system/netlify/functions/sotce-net.mjs | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/session-server/chat-manager.mjs b/session-server/chat-manager.mjs index 0d2e993904..a97457183c 100644 --- a/session-server/chat-manager.mjs +++ b/session-server/chat-manager.mjs @@ -41,6 +41,8 @@ export const chatInstances = { // Dedicated topic — sotce chat pings must never fan out to the shared // "mood" topic that aesthetic.computer devices subscribe to. topic: "chat-sotce", + // And its own face in the notification, not the aesthetic.computer mark. + icon: "https://assets.aesthetic.computer/sotce-net/cookie.png", }, "chat-clock.aesthetic.computer": { name: "chat-clock", @@ -959,6 +961,7 @@ export class ChatManager { broadcastToTopic(this.db, instance.config.topic, { title, body: text, + icon: instance.config.icon, // undefined keeps the default mark urgent: true, // time-sensitive on iOS, Urgency: high on web ttl: 0, // don't store undelivered chat pings data: { piece: "chat" }, diff --git a/shared/push.mjs b/shared/push.mjs index a9a2da3f4f..e0df524973 100644 --- a/shared/push.mjs +++ b/shared/push.mjs @@ -321,14 +321,17 @@ async function sendAPNsBatch(tokens, note) { } // 📦 Notification shape -// note = { title, body, image?, data? (flat string map, e.g. { piece }), +// note = { title, body, icon?, image?, data? (flat string map, e.g. { piece }), // urgent?, ttl? } +// `icon` is the small badge the OS draws beside the text. It defaults to the +// aesthetic.computer mark, but a sender with its own face — sotce.net's +// cookie — passes one and keeps it. function webPayload(note) { return JSON.stringify({ title: note.title, body: note.body, - icon: ICON, + icon: note.icon || ICON, image: note.image, data: note.data || {}, }); diff --git a/system/netlify/functions/sotce-net.mjs b/system/netlify/functions/sotce-net.mjs index 8a84a24543..c2f38efb45 100644 --- a/system/netlify/functions/sotce-net.mjs +++ b/system/netlify/functions/sotce-net.mjs @@ -11240,6 +11240,7 @@ export const handler = async (event, context) => { { title: "Sotce Net", body: "A new page has been written.", + icon: "https://assets.aesthetic.computer/sotce-net/cookie.png", data: { piece: "" }, ttl: 3600, }, -- 2.51.2