import {Button, Card, CardContent, CardDescription, CardHeader, CardTitle} from '@plunk/ui';
import {BookOpen, CheckCircle2, Mail, MessageCircle, Shield, Users, Zap} from 'lucide-react';
import Link from 'next/link';
import {useMemo} from 'react';
import {LANDING_URI, WIKI_URI} from '../lib/constants';
import type {ProjectSetupState} from '../lib/hooks/useProjectSetupState';
import {useConfig} from '../lib/hooks/useConfig';
interface QuickStartStep {
id: string;
icon: React.ElementType;
title: string;
description: string;
link: string;
linkText: string;
isCompleted: boolean;
}
interface QuickStartProps {
setupState: ProjectSetupState | undefined;
isLoading: boolean;
}
// Help resources that always appear
function HelpResources() {
return (
Need help?
);
}
export function QuickStart({setupState, isLoading}: QuickStartProps) {
// Calculate days since last campaign using useMemo to avoid impure function during render
// Must be called before any early returns to follow Rules of Hooks
const daysSinceLastCampaign = useMemo(() => {
if (!setupState || !setupState.lastCampaignSentAt) return null;
const now = new Date();
const lastSent = new Date(setupState.lastCampaignSentAt);
return Math.floor((now.getTime() - lastSent.getTime()) / (1000 * 60 * 60 * 24));
}, [setupState]);
const {data: config} = useConfig();
const billingEnabled = config?.features.billing.enabled ?? false;
if (isLoading || !setupState) {
return (
Quick StartGet started with Plunk in minutes
{[1, 2, 3].map(i => (
))}
);
}
const hasContacts = setupState.contactCount > 0;
const hasSentCampaign = setupState.lastCampaignSentAt !== null;
const hasRecentCampaign = daysSinceLastCampaign !== null && daysSinceLastCampaign <= 30;
// Build dynamic steps based on setup state with proper prioritization
// Priority order: Domain → Contacts → Campaign → Workflow → Subscription
const allSteps: QuickStartStep[] = [];
// Priority 1: Domain verification (critical for deliverability)
if (!setupState.hasVerifiedDomain) {
allSteps.push({
id: 'domain',
icon: Shield,
title: 'Verify Your Domain',
description: 'Essential for email deliverability and avoiding spam',
link: '/settings?tab=domains',
linkText: 'Add Domain',
isCompleted: false,
});
}
// Priority 2: Add contacts (can't send without contacts)
if (!hasContacts) {
allSteps.push({
id: 'contacts',
icon: Users,
title: 'Add Your First Contacts',
description: 'Import your subscriber list to start sending emails',
link: '/contacts',
linkText: 'Add Contacts',
isCompleted: false,
});
}
// Priority 3: Send campaign (core functionality, show if they have contacts but never sent)
if (hasContacts && !hasSentCampaign) {
allSteps.push({
id: 'campaign',
icon: Mail,
title: 'Send Your First Campaign',
description: 'Create and send your first email campaign',
link: '/campaigns',
linkText: 'Create Campaign',
isCompleted: false,
});
}
// Priority 4: Set up automation (advanced feature, only show if no workflow and have contacts)
if (hasContacts && !setupState.hasEnabledWorkflow) {
allSteps.push({
id: 'workflows',
icon: Zap,
title: 'Set Up Automation',
description: 'Create automated workflows to engage your audience',
link: '/workflows',
linkText: 'Create Workflow',
isCompleted: false,
});
}
// Priority 5: Subscription (nice to have, lower priority)
if (billingEnabled && !setupState.hasSubscription) {
allSteps.push({
id: 'subscription',
icon: Shield,
title: 'Upgrade Your Plan',
description: 'Remove Plunk branding and unlock more features',
link: '/settings?tab=billing',
linkText: 'Upgrade',
isCompleted: false,
});
}
// Priority 6: Re-engagement (show if they've been inactive)
if (hasSentCampaign && !hasRecentCampaign && daysSinceLastCampaign !== null && daysSinceLastCampaign > 30) {
allSteps.push({
id: 'campaign-reengagement',
icon: Mail,
title: 'Re-engage Your Audience',
description: `It's been ${daysSinceLastCampaign} days since your last campaign`,
link: '/campaigns',
linkText: 'Create Campaign',
isCompleted: false,
});
}
// If core setup is complete and they're actively sending, show success message
if (setupState.hasVerifiedDomain && hasContacts && hasSentCampaign && hasRecentCampaign) {
return (
Quick StartYour project is fully set up
All set!
Your project is fully configured and you're actively engaging your audience. Keep up the great
work!
);
}
// Show only the first 3 most important steps
const visibleSteps = allSteps.slice(0, 3);
return (
Quick Start
{visibleSteps.length === 0 ? 'Your project is set up' : 'Get started with Plunk in minutes'}