Skip to content
Groundmail

Free email template

Team invite email template

Invites someone to a team or workspace, naming who sent it and the role they get. Free and MIT-licensed, in React Email, MJML, HTML and plain text, with light and dark mode built in.

  • MIT license
  • Works with any email provider
  • Light and dark mode

What every team invite email needs.

The template covers the first five. The sixth is about your invite form.

  1. Who invited them, by name

    An invite from a product they've never heard of is spam. An invite from a colleague is expected. The template's subject leads with the inviter's name.

  2. What they're joining

    The team or workspace name and the role they'll have, so they know what accepting means before they click.

  3. One accept button

    Accept is the only action. The page behind it should handle both new people and people who already have an account.

  4. An expiry

    Invites sit in inboxes for days. The template's example is 7 days. After that, the inviter can send a fresh one.

  5. A "not expecting this" line

    Wrong addresses happen. Tell people that if they weren't expecting the invite, they can ignore it and nothing is created.

  6. Limits on what inviters control

    Invites let anyone with an account make you email any address. Rate-limit invites per account, cap the length of team names, and keep free text from the inviter out of the email.

The code. Copy the format your stack uses.

Change the brand name, logo and colors once in theme.ts and every template follows.

import * as React from 'react'
import { Button, Divider, Layout, LinkFallback, P, Small, Title } from '../../components'
import type { TemplateMeta } from '../../components/meta'
import { plainText } from '../../components/text'

export type TeamInviteProps = {
  inviterName: string
  teamName: string
  role: string
  inviteUrl: string
  expiresIn: string
}

export const meta: TemplateMeta = {
  name: 'Team invite',
  description: 'Invites someone to a team or workspace, naming who sent it and the role they get.',
  group: 'Account',
  subject: '{{inviter_name}} invited you to join {{team_name}}',
}

export default function TeamInvite({ inviterName, teamName, role, inviteUrl, expiresIn }: TeamInviteProps) {
  return (
    <Layout
      preview={`${inviterName} invited you to join ${teamName}.`}
      footerNote="You're receiving this because someone invited this email address to their team."
    >
      <Title>Join {teamName}</Title>
      <P>
        <strong>{inviterName}</strong> invited you to join the <strong>{teamName}</strong> team with the{' '}
        {role} role.
      </P>
      <Button href={inviteUrl}>Accept invitation</Button>
      <Small>
        This invitation expires in {expiresIn}. If you weren't expecting it, you can ignore this email.
      </Small>
      <Divider />
      <LinkFallback href={inviteUrl} />
    </Layout>
  )
}

TeamInvite.PreviewProps = {
  inviterName: 'Grace Hopper',
  teamName: 'Analytical Engines',
  role: 'Editor',
  inviteUrl: 'https://example.com/invites/accept?token=9e33a0',
  expiresIn: '7 days',
} satisfies TeamInviteProps

export function text({ inviterName, teamName, role, inviteUrl, expiresIn }: TeamInviteProps) {
  return plainText(
    `Join ${teamName}`,
    `${inviterName} invited you to join the ${teamName} team with the ${role} role.`,
    `Accept the invitation: ${inviteUrl}`,
    `This invitation expires in ${expiresIn}. If you weren't expecting it, you can ignore this email.`,
  )
}

team-invite.tsx, 57 lines, shown in full (scroll inside the panel). Typed props. Copy it with theme.ts and components/ from the repo. View on GitHub

Send it with Groundmail

Create the template in your account once, then send it by alias from your app.

1Terminal
npx -y --package=groundmail-cli -- groundmail templates push templates/team-invite/team-invite.html \
  --alias team-invite \
  --name "Team invite" \
  --subject "{{inviter_name}} invited you to join {{team_name}}" \
  --text templates/team-invite/team-invite.txt \
  --publish
2Node.js
import { Groundmail } from 'groundmail'

const groundmail = new Groundmail(process.env.GROUNDMAIL_API_KEY!)

await groundmail.emails.send({
  from: 'Acme <noreply@yourdomain.com>',
  to: 'ada@example.com',
  template: {
    id: 'team-invite',
    variables: {
      inviter_name: 'Grace Hopper',
      team_name: 'Analytical Engines',
      role: 'Editor',
      invite_url: 'https://example.com/invites/accept?token=9e33a0',
      expires_in: '7 days',
    },
  },
})

The CLI command and the Node.js send from the template's README, which also has Python, PHP and cURL. View on GitHub

Subject lines

People decide whether to open an invite based on who sent it. Put the inviter and the team in the subject, and add your product if the team name alone could be anything.

  • {{inviter_name}} invited you to join {{team_name}}DefaultA person and a place. The two things people check before opening.
  • {{inviter_name}} invited you to {{team_name}} on AcmeGoodAdds the product, for people who haven't heard of it yet.
  • Join {{team_name}} on AcmeGoodShorter, when the sender name already carries the inviter.
  • You've been invited!AvoidNo who and no what. People ignore invites from someone they can't identify.

Invites go to people who have never heard of you

The recipient didn't sign up, so their mailbox has no history with your domain. Authentication and a clean sending record do the work a past relationship would.

Google, Yahoo and Microsoft sender rules →
  • Send from your own domain with SPF, DKIM and DMARC set up.
  • Suppress addresses that bounce, and show the inviter which invites didn't arrive.
  • Watch for accounts sending invites in bulk to addresses outside their company: that's how spammers use invite forms.
  • Groundmail sends this template by alias from your own domain, on our own mail servers. Send it with Groundmail

Questions

Is it free to use?

Yes. The templates are MIT-licensed: use them in commercial products and change them however you like.

Do I need Groundmail to use it?

No. The HTML and text files use plain placeholders that work with most providers' template engines and with Handlebars or Mustache. Sending through Groundmail just saves a step.

Does it work in dark mode and Outlook?

Yes. The full HTML file carries dark-mode styles for Apple Mail and Outlook.com, and the extra markup desktop Outlook needs to draw the button.

How do I change the colors and logo?

Edit theme.ts once (name, logo, address and colors for light and dark) and rebuild. Every template in the set picks it up.