OPEN SOURCE · CONVEX COMPONENT

Invitations without the security footguns.

A small, transactional invitation primitive for Convex. Single-use links, exact audience binding, atomic grants, and safe resends.

$bun add convex-invite
THE COMPONENT BOUNDARY

One hard problem, solved once.

The component owns invitation state and concurrency. Your application owns identity and the access it grants.

Hash-only by design

Generate 256-bit tokens server-side. Persist only their versioned SHA-256 digest.

Serializable lifecycle

Accept, decline, revoke, expire, and resend race safely inside Convex transactions.

Your app keeps authority

Authentication, delivery, memberships, and product policy remain in host code.

ATOMIC ACCEPTANCE

The invitation and your grant commit together.

If membership creation fails, acceptance rolls back. Retrying as the same subject returns the original result.

const grant = await invites.accept(ctx, {
  token,
  acceptedBy: identity.subject,
  audienceRef: verifiedEmail,
});

const membershipId = await ctx.db.insert(
  "memberships",
  toMembership(grant),
);

await invites.setAcceptanceResult(ctx, {
  ...grant,
  result: { membershipId },
});

Ship the invite flow. Keep the invariants.

Read the documentation