feat(settings): site id and token copy on the CMS section

Draft
TL
4d ago
+314-152

What

The site id and the site token get copy buttons, and the site id lives in one place: Settings → CMS (settings?section=site), in the Site tokens section.

  • Site id (CMS section): read-only field with a copy button inside its right end. It shows on row hover and on keyboard focus (group-focus-within / focus-visible), always on touch screens (pointer-coarse:), and turns into a green check for 2s after copying, with a polite aria-live announcement. Labels: "Copy site ID" / "Copiar ID do site"; "Site ID copied to the clipboard" / "ID do site copiado para a área de transferência".
  • Site token: the one-time "Copy your site token" dialog uses the same button: "Copy site token" / "Copiar token do site", same check feedback. The token goes only to the clipboard. It is never logged or stored.
  • DRY: one CopyValueButton / CopyableField (settings/copy-value-button.tsx) built on useCopy from @decocms/ui/hooks/use-copy.ts, extracted from the old ProjectSiteId row. Both copies use it.
  • Removed: the Site id row in Settings → General (ProjectSiteId, the projectSiteId helper, its test, and the virtualMcp.settings.identity.siteId* / copySiteId i18n keys).

v7 projects: the Site tokens section only shows for Blocks v8 hosted-CMS projects with a repository. v7 projects now show no site id anywhere, which is how main behaves (main never had the row).

Why

The PO asked for the site id on the CMS section, a copy button for the token too, and the id shown in that one place only.

Test evidence

  • site-token-section.test.tsx (new, 2 pass): mocks navigator.clipboard.writeText and fetch. (1) The site id field is read-only, its copy button is hidden until hover/focus (classes asserted), and clicking it writes exactly acme-store, announces the copy and shows the green check. (2) Issuing a token opens the dialog, and "Copy site token" writes exactly the issued token and announces the copy.
  • project-identity.test.tsx (new, 1 pass): General renders name and description, and no site id label, text, copy button or value.
  • apps/web tsc --noEmit: clean. oxlint: clean. biome format: clean. knip: clean.
  • Manual run on the spike (headless Playwright, settings?section=site): the copy button has opacity 0 until hover and 1 on hover. Clicking it put exactly demo-store on the real clipboard. General shows 0 "site id" matches. After issuing a token, "Copy site token" put on the clipboard exactly the token shown in the dialog (length 216, value not logged), and the button swapped to the green check. The token was masked in the screenshot.

Stack

v8 Fast Preview track: previous: #7875 · next: #7878. Base: split/49-v8-localhost-item. Part of the v8 stack in #7796. The top of the stack is now #7878.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WNwbSEePYNcY5YCgqZURig