Docs
Free Trial CTA

Free Trial CTA

A stunning call-to-action section for free trial signups. Features beautiful design with trust indicators and feature highlights.

No credit card required

Start your 14-day free trial

Experience the full power of our platform. No credit card required.

Full access to all features
Unlimited team members
Enterprise-grade security
Setup in 5 minutes
10,000+ users
4.9 rating

Features

  • Eye-catching design - Emerald green theme with modern styling
  • Trust indicators - Credit card not required badge
  • Feature highlights - Key benefits with icons
  • Social proof - User count and rating display
  • Success animation - Celebratory confirmation state
  • Loading states - Visual feedback during submission
  • Email validation - Built-in form validation
  • Responsive layout - Perfect on all devices
  • Clean form - Single email input for quick signup
  • TypeScript support - Full type safety

Installation

Copy and paste the following code into your project.

"use client";
 
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Check,
  Loader2,
  Mail,
  Shield,
  Star,
  Users,
  X,
  Zap,
} from "lucide-react";
import { useState } from "react";
 
interface Feature {
  icon: "check" | "users" | "shield" | "zap" | "x";
  text: string;
}
 
interface CTAFreeTrialProps {
  headline: string;
  description?: string;
  features?: Feature[];
  showSocialProof?: boolean;
  userCount?: string;
  rating?: number;
  buttonText?: string;
  placeholder?: string;
  onSubmit?: (email: string) => Promise<void> | void;
}
 
const iconMap = {
  check: Check,
  users: Users,
  shield: Shield,
  zap: Zap,
  x: X,
};
 
export function CTAFreeTrial({
  headline,
  description,
  features,
  showSocialProof = true,
  userCount = "10,000+",
  rating = 4.9,
  buttonText = "Start Free Trial",
  placeholder = "Enter your email",
  onSubmit,
}: CTAFreeTrialProps) {
  const [email, setEmail] = useState("");
  const [isLoading, setIsLoading] = useState(false);
  const [isSuccess, setIsSuccess] = useState(false);
 
  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (email && onSubmit) {
      setIsLoading(true);
      try {
        await onSubmit(email);
        setIsSuccess(true);
        setEmail("");
      } catch (error) {
        console.error("Trial signup error:", error);
      } finally {
        setIsLoading(false);
      }
    }
  };
 
  return (
    <section className="relative overflow-hidden bg-emerald-600 rounded py-20 sm:py-24">
      <div className="absolute inset-0 bg-[linear-gradient(to_right,#ffffff08_1px,transparent_1px),linear-gradient(to_bottom,#ffffff08_1px,transparent_1px)] bg-[size:32px_32px]" />
      <div className="absolute right-0 top-0 h-[600px] w-[600px] rounded-full bg-emerald-500/20 blur-3xl" />
      <div className="absolute bottom-0 left-0 h-[600px] w-[600px] rounded-full bg-emerald-700/20 blur-3xl" />
 
      <div className="container relative mx-auto px-6">
        <div className="mx-auto max-w-6xl text-center">
          <div className="mb-6 inline-flex items-center gap-2 rounded-full bg-white/10 px-4 py-1.5 backdrop-blur-sm">
            <X className="h-4 w-4 text-white" />
            <span className="text-sm font-semibold text-white">
              No credit card required
            </span>
          </div>
 
          <h2 className="mb-4 text-4xl font-bold tracking-tight text-white sm:text-5xl lg:text-6xl">
            {headline}
          </h2>
 
          {description && (
            <p className="mb-8 text-lg text-emerald-100 sm:text-xl">
              {description}
            </p>
          )}
 
          {isSuccess ? (
            <div className="animate-in fade-in zoom-in mx-auto max-w-md rounded-2xl bg-white p-8 text-center shadow-2xl duration-500">
              <div className="mx-auto mb-4 flex h-20 w-20 items-center justify-center rounded-full bg-emerald-100">
                <Check className="h-10 w-10 text-emerald-600" strokeWidth={3} />
              </div>
              <h3 className="mb-2 text-2xl font-bold text-gray-900">
                Welcome aboard! 🎉
              </h3>
              <p className="text-gray-600">
                Check your email to get started with your free trial.
              </p>
            </div>
          ) : (
            <div className="mx-auto max-w-md">
              <form onSubmit={handleSubmit} className="mb-6">
                <div className="flex flex-col gap-3 sm:flex-row">
                  <div className="relative flex-1">
                    <Mail className="absolute left-3 top-1/2 h-5 w-5 -translate-y-1/2 text-gray-400" />
                    <Input
                      type="email"
                      placeholder={placeholder}
                      value={email}
                      onChange={(e) => setEmail(e.target.value)}
                      required
                      disabled={isLoading}
                      className="h-14 rounded-xl border-2 border-white/20 bg-white pl-10 text-base shadow-lg focus:border-white focus:ring-2 focus:ring-white/50"
                    />
                  </div>
                  <Button
                    type="submit"
                    disabled={isLoading}
                    className="h-14 rounded-xl bg-gray-900 px-8 text-base font-semibold text-white shadow-lg transition-all hover:bg-gray-800 hover:shadow-xl sm:w-auto"
                  >
                    {isLoading ? (
                      <>
                        <Loader2 className="mr-2 h-5 w-5 animate-spin" />
                        Starting...
                      </>
                    ) : (
                      buttonText
                    )}
                  </Button>
                </div>
              </form>
 
              {features && features.length > 0 && (
                <div className="mb-6 grid gap-3 sm:grid-cols-2">
                  {features.map((feature, index) => {
                    const Icon = iconMap[feature.icon];
                    return (
                      <div
                        key={index}
                        className="flex items-center gap-2 rounded-lg bg-white/10 px-4 py-3 backdrop-blur-sm"
                      >
                        <Icon className="h-5 w-5 flex-shrink-0 text-white" />
                        <span className="text-sm font-medium text-white">
                          {feature.text}
                        </span>
                      </div>
                    );
                  })}
                </div>
              )}
 
              {showSocialProof && (
                <div className="flex items-center justify-center gap-6 text-white/90">
                  <div className="flex items-center gap-2">
                    <Users className="h-5 w-5" />
                    <span className="text-sm font-medium">
                      {userCount} users
                    </span>
                  </div>
                  <div className="h-4 w-px bg-white/20" />
                  <div className="flex items-center gap-1">
                    <Star className="h-5 w-5 fill-yellow-400 text-yellow-400" />
                    <span className="text-sm font-medium">{rating} rating</span>
                  </div>
                </div>
              )}
            </div>
          )}
        </div>
      </div>
    </section>
  );
}

Update the import paths to match your project setup.

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";

Usage

Basic Usage

import CTAFreeTrial from "@/components/ui/cta-free-trial";
 
export default function Page() {
    return (
        <CTAFreeTrial
            headline="Start your free trial"
            description="No credit card required. Cancel anytime."
            onSubmit={(email) => console.log("Trial signup:", email)}
        />
    );
}

With Features

<CTAFreeTrial
    headline="Start your free trial"
    description="Get full access to all features for 14 days."
    features={[
        { icon: "check", text: "Full access to all features" },
        { icon: "users", text: "Unlimited team members" },
        { icon: "shield", text: "Enterprise-grade security" },
    ]}
    onSubmit={(email) => console.log(email)}
/>

With Social Proof

<CTAFreeTrial
    headline="Join 10,000+ teams"
    description="Start your 14-day free trial today."
    showSocialProof={true}
    userCount="10,000+"
    rating={4.9}
    onSubmit={(email) => console.log(email)}
/>

With API Integration

"use client";
 
import CTAFreeTrial from "@/components/ui/cta-free-trial";
 
export default function Page() {
    const handleSubmit = async (email: string) => {
        try {
            const response = await fetch("/api/trial-signup", {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({ email }),
            });
 
            if (response.ok) {
                // Success handled by component
            }
        } catch (error) {
            console.error("Trial signup failed:", error);
        }
    };
 
    return (
        <CTAFreeTrial
            headline="Start your free trial"
            description="No credit card required."
            features={[
                { icon: "check", text: "14-day free trial" },
                { icon: "x", text: "No credit card required" },
                { icon: "zap", text: "Setup in 5 minutes" },
            ]}
            onSubmit={handleSubmit}
        />
    );
}

Props

PropTypeDefaultDescription
headlinestringRequiredMain headline text
descriptionstringundefinedSupporting description
featuresFeature[]undefinedList of features with icons
showSocialProofbooleantrueShow user count and rating
userCountstring"10,000+"Number of users
ratingnumber4.9Star rating (out of 5)
buttonTextstring"Start Free Trial"Button text
placeholderstring"Enter your email"Input placeholder
onSubmit(email: string) => voidundefinedForm submission handler

TypeScript Interface

interface CTAFreeTrialProps {
    headline: string;
    description?: string;
    features?: Feature[];
    showSocialProof?: boolean;
    userCount?: string;
    rating?: number;
    buttonText?: string;
    placeholder?: string;
    onSubmit?: (email: string) => Promise<void> | void;
}
 
interface Feature {
    icon: "check" | "users" | "shield" | "zap" | "x";
    text: string;
}

Use Cases

Perfect for:

  • SaaS free trials
  • Product launches
  • Lead generation
  • Conversion optimization
  • Landing pages
  • Marketing campaigns
  • User acquisition
  • Growth initiatives