Two-Factor Setup
Add a second authentication factor to an account, balancing the security it buys against the friction it adds.
Scan the QR code with your authenticator app, then enter the 6-digit code it shows.
Example result — your output may vary with your context and the prompt you pass.
# Two-Factor Setup: Authenticator App
## Context
Flexnative UI intent — a reference solution from the shadcn/ui registry (@flx). The intent frames the problem; the decision is one approach to it.
## Problem
Add a second authentication factor to an account, balancing the security it buys against the friction it adds.
## Decision
- Best for: The default recommendation for most accounts. TOTP via an authenticator app is free, offline, and far stronger than SMS.
- Trade-off: Requires the user to install an app and rescan if they switch phones; pair it with backup codes for recovery.
## Registry Item
@flx/two-factor-setup-1
## Stack
- UI: shadcn/ui
- Styling: Tailwind CSS
- shadcn components: Button, Card, Input Otp
- npm: lucide-react, input-otp
## Registry Source
https://ui.flexnative.com/r/two-factor-setup-1.json
## Preview
https://ui.flexnative.com/intents/two-factor-setup#1
## Reference Implementation
```tsx
'use client'
import { useState } from 'react'
import { ShieldCheckIcon } from 'lucide-react'
import { Button } from '@/components/ui/button'
import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card'
import {
InputOTP,
InputOTPGroup,
InputOTPSlot,
} from '@/components/ui/input-otp'
export function TwoFactorSetup1() {
const [code, setCode] = useState('')
return (
<Card size="sm">
<CardHeader>
<div className="bg-primary/10 mb-1 flex size-10 items-center justify-center rounded-full">
<ShieldCheckIcon className="text-primary size-5" />
</div>
<CardTitle>Set up authenticator</CardTitle>
<p className="text-muted-foreground text-xs">
Scan the QR code with your authenticator app, then enter the 6-digit
code it shows.
</p>
</CardHeader>
<CardContent className="flex flex-col gap-4">
<div className="flex justify-center">
<div className="border-border grid size-28 grid-cols-7 grid-rows-7 gap-px rounded-md border p-2">
{Array.from({ length: 49 }).map((_, i) => (
<span
key={i}
className={
(i * 7 + 3) % 5 < 2 || i % 3 === 0
? 'bg-foreground rounded-[1px]'
: 'bg-transparent'
}
/>
))}
</div>
</div>
<div className="flex justify-center">
<InputOTP maxLength={6} value={code} onChange={setCode}>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>
</div>
</CardContent>
<CardFooter>
<Button className="w-full" disabled={code.length < 6}>
Verify & enable
</Button>
</CardFooter>
</Card>
)
}
```Paste into your AI tool and adapt it to your context.
Other ways
Reach for these when the context shifts. Each is copyable too.
We'll text a code to your phone each time you sign in. Add the number to protect.
Carrier rates may apply. SMS is less secure than an app.
Use Face ID, a fingerprint, or a security key. Nothing to type, and nothing phishable.
- Works across your synced devices
- Resistant to phishing and credential theft
Requires a device with biometrics or a hardware key.
Use one of these if you lose your device. Each code works once. Store them somewhere safe.