All templates
authentication
Magic Link Login Template
Passwordless authentication via email link
Preview
import {
Body,
Button,
Container,
Head,
Heading,
Hr,
Html,
Preview,
Section,
Text,
} from "@react-email/components";
type MagicLinkProps = {
loginUrl: string;
expiryTime: string;
companyName: string;
};
export function MagicLinkEmail({ loginUrl, expiryTime, companyName }: MagicLinkProps) {
return (
<Html>
<Head />
<Preview>Your login link for {companyName}</Preview>
<Body style={main}>
<Container style={container}>
<Heading style={h1}>Sign in to {companyName}</Heading>
<Text style={text}>
Click the button below to sign in. No password required!
</Text>
<Section style={buttonContainer}>
<Button style={button} href={loginUrl}>
Sign In
</Button>
</Section>
<Text style={muted}>
This link expires in {expiryTime} and can only be used once.
</Text>
<Hr style={hr} />
<Text style={footer}>
If you didn't request this link, you can safely ignore this email.
</Text>
</Container>
</Body>
</Html>
);
}
const main = {
backgroundColor: "#f6f9fc",
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
};
const container = {
backgroundColor: "#ffffff",
margin: "0 auto",
padding: "40px 20px",
maxWidth: "480px",
};
const h1 = {
color: "#1f2937",
fontSize: "24px",
fontWeight: "600",
margin: "0 0 20px",
};
const text = {
color: "#374151",
fontSize: "16px",
lineHeight: "24px",
margin: "0 0 16px",
};
const muted = {
color: "#6b7280",
fontSize: "14px",
lineHeight: "20px",
};
const buttonContainer = {
textAlign: "center" as const,
margin: "32px 0",
};
const button = {
backgroundColor: "#8b5cf6",
borderRadius: "8px",
color: "#fff",
fontSize: "16px",
fontWeight: "600",
padding: "12px 24px",
textDecoration: "none",
};
const hr = {
borderColor: "#e5e7eb",
margin: "24px 0",
};
const footer = {
color: "#9ca3af",
fontSize: "12px",
lineHeight: "18px",
};Install: npm install @react-email/components
Template Variables
Pass these props to your email component:
| Variable | Description |
|---|---|
loginUrl | Unique one-time login link |
expiryTime | Link expiration time (e.g., '15 minutes') |
companyName | Your company or product name |
Best Practices
Security
- •Set short expiration (10-15 minutes)
- •Invalidate token after single use
- •Bind token to the requesting device/browser when possible
- •Rate limit requests (e.g., 5 per hour per email)
User Experience
- •Open the app in the same browser session
- •Show clear feedback if link is expired or used
- •Provide fallback to password login
When to Use
- •Great for low-frequency apps (users forget passwords)
- •Ideal for mobile where password entry is painful
- •Consider WebAuthn/passkeys as a modern alternative
Ready to send emails?
Get started with 1,000 free emails per month.
Start for free