import Link from "next/link"; import { publicInviteResponseSchema, type PublicInviteResponse, } from "@turbostarter/api/schema"; import { handle } from "@turbostarter/api/utils"; import { api } from "~/lib/api/server"; import { getMetadata } from "~/lib/metadata"; import { InstallToggle } from "~/modules/join/install-toggle"; export const generateMetadata = getMetadata({ title: "Join a mesh", description: "You've been invited to a claudemesh mesh.", }); const ERROR_COPY: Record< Extract["reason"], { title: string; body: (inviter: string | null) => string } > = { expired: { title: "This invite expired", body: (inviter) => `The invite is no longer valid. Ask ${inviter ?? "the person who sent it"} for a fresh link.`, }, revoked: { title: "This invite was revoked", body: (inviter) => `${inviter ?? "The mesh owner"} revoked this invite. Ask for a new one if you still need access.`, }, exhausted: { title: "This invite has no uses left", body: (inviter) => `Every allowed use has been redeemed. Ask ${inviter ?? "the person who sent it"} for a new link.`, }, mesh_archived: { title: "This mesh is no longer active", body: () => "The mesh was archived. There is nothing to join.", }, bad_signature: { title: "This invite is invalid", body: () => "The signature does not verify. The link was modified or forged — ask for a fresh one through a trusted channel.", }, malformed: { title: "This invite is unreadable", body: () => "The token could not be decoded. Check the link you received — it may be truncated.", }, not_found: { title: "This invite does not exist", body: () => "Nothing matches this token. It may have been deleted, or the link was mis-pasted.", }, }; export default async function JoinPage({ params, }: { params: Promise<{ token: string }>; }) { const { token } = await params; const invite = await handle(api.public.invite[":token"].$get, { schema: publicInviteResponseSchema, })({ param: { token } }).catch( () => ({ valid: false, reason: "malformed", meshName: null, inviterName: null, expiresAt: null, }) as const, ); return (
claudemesh
{invite.valid ? ( <>
— invitation

You're invited to{" "} {invite.meshName}

{invite.inviterName ? `${invite.inviterName} added you as a ${invite.role}.` : `You've been added as a ${invite.role}.`}{" "} {invite.memberCount} other{" "} {invite.memberCount === 1 ? "peer is" : "peers are"} already on the mesh.

By joining, you'll be known as a peer with an ed25519 keypair generated locally. You keep your keys. claudemesh sees ciphertext only. Leave anytime with{" "} claudemesh leave {invite.meshSlug} .

expires {new Date(invite.expiresAt).toLocaleDateString()} ·{" "} {invite.maxUses - invite.usedCount} of {invite.maxUses} uses remaining

) : ( <>
— invitation unavailable

{ERROR_COPY[invite.reason].title}

{ERROR_COPY[invite.reason].body(invite.inviterName)}

{invite.meshName && (

mesh: {invite.meshName} {invite.expiresAt && ` · expired ${new Date(invite.expiresAt).toLocaleDateString()}`}

)}
← claudemesh.com
)}
); }