Security Setup

Step 3 of 4

Security

Secure your account

We recommend completing these steps to keep your account safe. You can always do this later.

Security score: 50%

Verify recovery email

Add a backup email for account recovery

Done

Two-factor authentication

Add an extra layer of security with 2FA

Backup codes

Generate one-time recovery codes

Strong password

Ensure your password meets security requirements

Done
About this block

Security SetupPRO

Onboarding screen for configuring account security including two-factor authentication, recovery email, and backup codes. Perfect for apps that prioritize security during onboarding.

Onboarding23: Security Setup

Onboarding screen for account security tasks (recovery email, two-factor authentication, backup codes, password strength), each rendered as a row with a live security score derived from how many are marked done.

Upgrade to Pro

Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.

Upgrade Now

Installation

Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.

Radix flavor

bash
npx shadcn add "https://ui.beste.co/r/onboarding23?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
npx shadcn add "https://ui.beste.co/r-base/onboarding23?email=YOUR_EMAIL&license_key=YOUR_KEY"

This installs the block to components/beste/block/onboarding23.tsx and the badge and button shadcn/ui primitives listed in its dependencies.

Quick start

The installed file exports onboarding23Demo alongside the block: the exact props behind the preview above. Spread it to get a working security setup step in one line.

tsx
import { Onboarding23, onboarding23Demo } from "@/components/beste/block/onboarding23";

export default function OnboardingPage() {
  return <Onboarding23 {...onboarding23Demo} />;
}

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsx
import { KeyRound, Mail, Smartphone } from "lucide-react";
import { Onboarding23 } from "@/components/beste/block/onboarding23";

export default function OnboardingPage() {
  return (
    <Onboarding23
      badge={{ label: "Security", variant: "secondary" }}
      heading="Secure your account"
      description="We recommend completing these steps to keep your account safe."
      steps={[
        { id: "email", icon: <Mail className="size-5" />, title: "Verify recovery email", description: "Add a backup email", status: "completed", actionLabel: "Verified" },
        { id: "2fa", icon: <Smartphone className="size-5" />, title: "Two-factor authentication", description: "Add an extra layer of security", status: "pending", actionLabel: "Enable" },
        { id: "backup", icon: <KeyRound className="size-5" />, title: "Backup codes", description: "Generate recovery codes", status: "pending", actionLabel: "Generate" },
      ]}
      primaryButton={{ label: "Continue", href: "/onboarding/finish" }}
      secondaryButton={{ label: "I'll do this later", href: "/dashboard" }}
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string; variant?: "default" | "secondary" | "outline" }–Small badge above the heading
headingstring–Main headline
descriptionstring–Supporting copy below the heading
stepsSecurityStep[][]List of security tasks
primaryButton{ label: string; href: string }–Primary CTA link
secondaryButton{ label: string; href: string }–Secondary CTA link
labels{ stepOf?: string; completed?: string; recommended?: string; optional?: string; securityScore?: string }–Template strings for the step counter, completion state, and score line
currentStepnumber1Current step number, used only to fill the step-of label
totalStepsnumber4Total step count, used only to fill the step-of label
classNamestring–Extra classes for the outer <section>
ts
type SecurityStatus = "completed" | "pending" | "optional";

type SecurityStep = {
  id: string;
  icon: React.ReactNode;
  title: string;
  description: string;
  status: SecurityStatus;
  actionLabel: string;
};

Behavior notes

  • Completed state is seeded via useState<Set<string>> from steps where status === "completed"; clicking a step's action button (its own actionLabel, e.g. "Enable", "Generate") only toggles local membership, it doesn't perform any real 2FA enrollment or code generation.
  • SecurityStep.status accepts "completed" | "pending" | "optional", but the component only ever branches on a binary isDone derived from the local completed set, so "optional" steps render identically to "pending" ones with no distinct visual treatment.
  • labels.recommended and labels.optional are declared in the labels prop type but never referenced anywhere in the render; they're currently inert.
  • The score line ("Security score: %") only switches to text-primary once every step is completed (score === 100); otherwise it stays text-accent-foreground.

More Onboarding blocks

View all Onboarding
PRO

onboarding19

Profile Setup Card

PRO

onboarding29

Company Info Form

PRO

onboarding11

Side Navigation Wizard

Get Pro access