You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Show a "via connected app" label on chat posts from a connected app #344
Heading chat on a public pad is public, and a connected app posts there as the document owner. Visitors read its summary as the owner's own words. History already labels an MCP version "Connected app", but chat has no label.
After this change, a post that carries metadata.via = 'connected_app' shows a muted "via connected app" in its message footer, beside "edited". It shows on desktop and phone, on group-start and compact rows.
Acceptance criteria
The maintainer's ruling is recorded on this issue before any code lands: show the label or not, and the exact visible words.
A message with metadata.via === 'connected_app' shows the label in the footer indicators, beside EditedBadge.
The label shows on desktop and on phone, on a group-start row and on a compact row.
A screen reader reads "Posted through a connected app". The visible text stays short.
A message without the key shows no label. An edited connected-app post shows both "via connected app" and "edited".
The label uses text-base-content/60 text-xs. Light and dark themes both meet the design-system contrast floor (4.5:1).
Chat code does not import History code. The words are copied, not shared.
Type: HITL — the maintainer, as chat owner, must rule whether connected-app posts show a visible label, and give the exact words. The answer goes in a comment on this issue. If the ruling is no, close this issue; the stored key from #336 stays.
Category: enhancement
Current behavior:
The footer indicators render on every row, group-start and compact. Desktop: apps/webapp/src/components/chatroom/components/ChatList/DesktopMessageBody.tsx:13-16. Phone: apps/webapp/src/components/chatroom/components/ChatList/MobileMessageBody.tsx:76-81.
The header meta row is absent on a compact row. An MCP post carries the owner's user_id, so a connected-app post right after the owner's own post is compact (samePrev in apps/webapp/src/components/chatroom/components/ChatList/ItemContent.tsx). That is why the label goes in the footer.
EditedBadge is the model for shape: it reads message from useMessageCardContext() and returns null when it has nothing to show (.../MessageFooter/components/MessageIndicators/components/EditedBadge.tsx:8-16). Its class text-opacity-50 is a Tailwind 3 class. The repo is on Tailwind 4 (root package.json), so do not copy that class.
ReplyCount already reads a metadata key in the footer with getMetadataProperty from @utils/metadata (.../MessageIndicators/components/ReplyCount.tsx:12).
MessageIndicators.tsx attaches each badge as a static property, for example MessageIndicators.EditedBadge = EditedBadge.
History shows mcp: 'Connected app' (apps/webapp/src/components/pages/history/components/HistorySidebarRowParts.tsx:91).
Desired behavior:
New ConnectedAppBadge.tsx beside EditedBadge.tsx. It returns null unless getMetadataProperty<string>(message.metadata, 'via') === 'connected_app'.
Visible text: the ruled words, "via connected app" by default. Add sr-only text "Posted through a connected app", and hide the short visible text from screen readers so it is read once.
Use text-base-content/60 text-xs: the design-system tier for muted informational text. Use no colour or icon alone to carry the meaning. Leave EditedBadge as it is.
Export it from MessageIndicators/components/index.ts. In MessageIndicators.tsx, attach it as MessageIndicators.ConnectedAppBadge.
Render it next to EditedBadge in DesktopMessageBody.tsx and MobileMessageBody.tsx. Leave samePrev and the header meta row alone.
Where to start:EditedBadge, ReplyCount and MessageIndicators under apps/webapp/src/components/chatroom/components/MessageCard/components/MessageFooter/components/MessageIndicators/; DesktopMessageBody and MobileMessageBody in apps/webapp/src/components/chatroom/components/ChatList/. Line numbers are hints as of 2026-09-28; the agent searches by symbol.
.cursor/docs/design-system.md §Ink ladder (/60 is the floor for text a person must read) and .cursor/rules/design-system.mdc.
AGENTS.md §UI And Theme and §Test Policy: no unit test. Check the real path in a browser.
CONTEXT.md names this source Connected app.
Verify:
bun run --filter @docs.plus/webapp typecheck exits 0. bun run lint, bun run lint:styles and bun run format pass at the repo root.
Start the local stack with make dev-local. Sign in as the owner of a test pad and open a heading chat.
Make posts with the key. After Mark MCP chat posts with a fixed connected-app metadata key #336 lands, post through the post_chat_message MCP tool on the local stack. Or, in local Supabase Studio only, set metadata to {"via":"connected_app"} on a test message in public.messages. Reload the pad after a Studio edit.
Desktop browser, light and dark:
The owner sends two messages in a row. Give the second one the key. It renders as a compact row, and its footer shows "via connected app".
Give the key to a message that starts a group, such as the first one after another person's message. Its footer shows the label too.
Edit the connected-app post. The footer shows both labels.
A plain message shows no label.
Phone: use a mobile user agent (the mobile shell is user-agent gated on the server). Repeat steps 1 to 4, light and dark.
Screen reader (VoiceOver on macOS): the row reads "Posted through a connected app" once.
Parent
#328. Related: #230, #228
What to build
Heading chat on a public pad is public, and a connected app posts there as the document owner. Visitors read its summary as the owner's own words. History already labels an MCP version "Connected app", but chat has no label.
After this change, a post that carries
metadata.via = 'connected_app'shows a muted "via connected app" in its message footer, beside "edited". It shows on desktop and phone, on group-start and compact rows.Acceptance criteria
metadata.via === 'connected_app'shows the label in the footer indicators, besideEditedBadge.text-base-content/60 text-xs. Light and dark themes both meet the design-system contrast floor (4.5:1).Blocked by
Agent brief
Type: HITL — the maintainer, as chat owner, must rule whether connected-app posts show a visible label, and give the exact words. The answer goes in a comment on this issue. If the ruling is no, close this issue; the stored key from #336 stays.
Category: enhancement
Current behavior:
apps/webapp/src/components/chatroom/components/ChatList/DesktopMessageBody.tsx:13-16. Phone:apps/webapp/src/components/chatroom/components/ChatList/MobileMessageBody.tsx:76-81.user_id, so a connected-app post right after the owner's own post is compact (samePrevinapps/webapp/src/components/chatroom/components/ChatList/ItemContent.tsx). That is why the label goes in the footer.EditedBadgeis the model for shape: it readsmessagefromuseMessageCardContext()and returns null when it has nothing to show (.../MessageFooter/components/MessageIndicators/components/EditedBadge.tsx:8-16). Its classtext-opacity-50is a Tailwind 3 class. The repo is on Tailwind 4 (rootpackage.json), so do not copy that class.ReplyCountalready reads ametadatakey in the footer withgetMetadataPropertyfrom@utils/metadata(.../MessageIndicators/components/ReplyCount.tsx:12).MessageIndicators.tsxattaches each badge as a static property, for exampleMessageIndicators.EditedBadge = EditedBadge.mcp: 'Connected app'(apps/webapp/src/components/pages/history/components/HistorySidebarRowParts.tsx:91).Desired behavior:
ConnectedAppBadge.tsxbesideEditedBadge.tsx. It returns null unlessgetMetadataProperty<string>(message.metadata, 'via') === 'connected_app'.sr-onlytext "Posted through a connected app", and hide the short visible text from screen readers so it is read once.text-base-content/60 text-xs: the design-system tier for muted informational text. Use no colour or icon alone to carry the meaning. LeaveEditedBadgeas it is.MessageIndicators/components/index.ts. InMessageIndicators.tsx, attach it asMessageIndicators.ConnectedAppBadge.EditedBadgeinDesktopMessageBody.tsxandMobileMessageBody.tsx. LeavesamePrevand the header meta row alone.Where to start:
EditedBadge,ReplyCountandMessageIndicatorsunderapps/webapp/src/components/chatroom/components/MessageCard/components/MessageFooter/components/MessageIndicators/;DesktopMessageBodyandMobileMessageBodyinapps/webapp/src/components/chatroom/components/ChatList/. Line numbers are hints as of 2026-09-28; the agent searches by symbol.Rules that apply:
apps/webapp/src/components/chatroom/CLAUDE.md§Message Grouping Projection (never persist grouping flags; compact rows keep the rail)..cursor/docs/design-system.md§Ink ladder (/60is the floor for text a person must read) and.cursor/rules/design-system.mdc.AGENTS.md§UI And Theme and §Test Policy: no unit test. Check the real path in a browser.CONTEXT.mdnames this source Connected app.Verify:
bun run --filter @docs.plus/webapp typecheckexits 0.bun run lint,bun run lint:stylesandbun run formatpass at the repo root.make dev-local. Sign in as the owner of a test pad and open a heading chat.post_chat_messageMCP tool on the local stack. Or, in local Supabase Studio only, setmetadatato{"via":"connected_app"}on a test message inpublic.messages. Reload the pad after a Studio edit.Out of scope
messages.