Files
claudemesh/apps/web
Alejandro Gutiérrez c8ae6462e3 feat(web): email invite mode + ic:// removal in invite generator (wave 3)
Completes the v2 invite user experience. The generator now ships two
delivery modes behind a simple Link | Email toggle, and the vestigial
ic:// scheme is gone from every user-visible surface.

Modes
- Link (default, existing flow): mints a v2 invite, displays short URL
  + QR + CLI command. No behavioral change vs wave 2.
- Email (new): admin types a recipient email, submit dispatches through
  the POST /api/my/meshes/:id/invites/email endpoint (wave 2), which
  mints a normal v2 invite, records a pending_invite row, and stubs the
  Postmark send with a TODO. Result card shows a "✓ Invite sent to X"
  banner plus the same QR card so the admin can also share manually.

Honest UX copy on the stub:
"Email delivery is stubbed in v0.1.x — the invite is valid. Share the
link directly if needed." Avoids pretending something shipped that
hasn't.

ic:// cleanup
- inviteLink field no longer rendered or stored (still returned by the
  API for backward compatibility; just not surfaced)
- CLI command now copies `claudemesh join <code>` (falls back to
  shortUrl when code is null), matching the new v2 entry point
- Zero remaining `ic://` references in the UI

Implementation notes
- Two separate useForm instances (linkForm, emailForm) with dedicated
  resolvers and submit handlers — clearer state boundaries than
  conditional validation on a merged schema
- Mode toggle uses role="group" + aria-pressed, focus-visible ring,
  keyboard-navigable
- Email result banner is role="status" for screen readers
- RPC client has one `as any` on `(api.my.meshes[":id"].invites as any)
  .email.$post` — the endpoint IS registered server-side (wave 2) but
  the monorepo's Hono type regen is out-of-band; TODO comment marks the
  cast for removal when the RPC types catch up
- No new deps
- Component export signature unchanged

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 19:57:25 +01:00
..