Hi,
This is how I personnaly implemented it:
1. Create an edge function that handles the form’s user data (name, email, etc.)
Use something like:
//Create invitation record
const includesEditor = frontUrl.toLowerCase().includes('editor');
const redirectUrl = includesEditor
? `${frontUrl}?invitation_id=${invitation.id}`
: `${frontUrl}/sign-up?invitation_id=${invitation.id}`;
const { data: inviteData, error: inviteError } = await supabaseAdmin.auth.admin.inviteUserByEmail(normalizedEmail, {
redirectTo: redirectUrl
});
//then create the associated profile
I have an invitation table to manage expiration, and my frontend URL is a record from a metadata table in Supabase.
2. Customize the invite user email template
In my invite user email template, I’ve included:
<div style="text-align: center; margin: 32px 0;">
<a href="{{ .ConfirmationURL }}" style="display: inline-block; background-color: #111827; color: white; text-decoration: none; padding: 12px 24px; border-radius: 12px; font-weight: 500; font-size: 14px; font-family: Arial, sans-serif; border: 1px solid #111827;">
Accepter l'invitation
</a>
</div>
3. Handle the redirect
When the user clicks the link, they’re redirected to the URL with a token (they are now logged in).
4. Create a sign-up page
I’ve created a sign-up page where, on load, I query the invitation from the query parameter:
On this page, I ask for the user’s information (including password):
5. Update user data on submission
When the user submits, I call another edge function to update the password, invitation, etc.:
// Update user password
const { error: updateError } = await supabase.auth.admin.updateUserById(invitation.profiles.id, {
password: password
});
Then redirect the user to the index page.