Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/(auth)/sign-up/[[...sign-up]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function getIntentCopy(intent: string | undefined) {
}

return {
label: 'Create Account',
label: 'Create account',
title: 'Create your CallbackCloser account',
detail:
'Create a new owner account here. CallbackCloser handles setup for you, then unlocks your workspace when everything is ready.',
Expand Down
6 changes: 3 additions & 3 deletions app/contact/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { PublicSiteFooter } from '@/components/public-site-footer';
import { PublicSiteNav } from '@/components/public-site-nav';
import { buttonVariants } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { PUBLIC_CREATE_ACCOUNT_PATH, PUBLIC_START_FREE_PILOT_PATH } from '@/lib/public-auth-routing';
import { PUBLIC_SIGN_IN_PATH, PUBLIC_START_FREE_PILOT_PATH } from '@/lib/public-auth-routing';

const outreachInputs = [
'Business name and service type',
Expand Down Expand Up @@ -51,8 +51,8 @@ export default function ContactPage() {
<Link className={buttonVariants()} href={PUBLIC_START_FREE_PILOT_PATH}>
Start 14-day pilot
</Link>
<Link className={buttonVariants({ variant: 'outline' })} href={PUBLIC_CREATE_ACCOUNT_PATH}>
Create account
<Link className={buttonVariants({ variant: 'outline' })} href={PUBLIC_SIGN_IN_PATH}>
Sign in
</Link>
<Link className={buttonVariants({ variant: 'ghost' })} href="/pricing">
View pricing
Expand Down
7 changes: 2 additions & 5 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { PublicSiteNav } from '@/components/public-site-nav';
import { Badge } from '@/components/ui/badge';
import { buttonVariants } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { PUBLIC_CREATE_ACCOUNT_PATH, PUBLIC_START_FREE_PILOT_PATH } from '@/lib/public-auth-routing';
import { PUBLIC_START_FREE_PILOT_PATH } from '@/lib/public-auth-routing';

const flowSteps = [
{
Expand Down Expand Up @@ -183,13 +183,10 @@ export default function LandingPage() {
{pilotIncludes.map((item) => (
<p key={item}>- {item}</p>
))}
<div className="flex flex-wrap gap-3 pt-4">
<div className="pt-4">
<Link className={buttonVariants()} href={PUBLIC_START_FREE_PILOT_PATH}>
Start 14-day pilot
</Link>
<Link className={buttonVariants({ variant: 'outline' })} href={PUBLIC_CREATE_ACCOUNT_PATH}>
Create account
</Link>
</div>
</CardContent>
</Card>
Expand Down
6 changes: 3 additions & 3 deletions app/pricing/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { PublicSiteNav } from '@/components/public-site-nav';
import { Badge } from '@/components/ui/badge';
import { buttonVariants } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { PUBLIC_CREATE_ACCOUNT_PATH, PUBLIC_START_FREE_PILOT_PATH } from '@/lib/public-auth-routing';
import { PUBLIC_START_FREE_PILOT_PATH } from '@/lib/public-auth-routing';

const pilotFeatures = [
'14-day pilot',
Expand Down Expand Up @@ -82,8 +82,8 @@ export default function PricingPage() {
If you need multi-location rollout help or a custom setup path, contact us before activation so the pilot matches your operating model.
</div>
<div className="flex flex-wrap gap-3 pt-2">
<Link className={buttonVariants({ size: 'sm' })} href={PUBLIC_CREATE_ACCOUNT_PATH}>
Create account
<Link className={buttonVariants({ size: 'sm' })} href={PUBLIC_START_FREE_PILOT_PATH}>
Start 14-day pilot
</Link>
<Link className={buttonVariants({ size: 'sm', variant: 'outline' })} href="/contact">
Talk to us
Expand Down
16 changes: 7 additions & 9 deletions components/public-site-footer.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import Link from 'next/link';

import { PUBLIC_CREATE_ACCOUNT_PATH, PUBLIC_SIGN_IN_PATH, PUBLIC_START_FREE_PILOT_PATH } from '@/lib/public-auth-routing';
import { PUBLIC_SIGN_IN_PATH, PUBLIC_START_FREE_PILOT_PATH } from '@/lib/public-auth-routing';

const footerLinks = [
{ href: PUBLIC_CREATE_ACCOUNT_PATH, label: 'Create account' },
{ href: PUBLIC_START_FREE_PILOT_PATH, label: 'Start 14-day pilot' },
{ href: PUBLIC_SIGN_IN_PATH, label: 'Sign in' },
{ href: '/pricing', label: 'Pricing' },
{ href: '/demo', label: 'Missed-Call Demo' },
{ href: '/contact', label: 'Contact' },
{ href: '/privacy', label: 'Privacy Policy' },
{ href: '/terms', label: 'Terms & Conditions' },
{ href: '/refund', label: 'Refund' },
{ href: '/sms-consent', label: 'SMS Consent' },
{ href: '/privacy', label: 'Privacy' },
{ href: '/terms', label: 'Terms' },
{ href: '/refund', label: 'Refund' },
{ href: PUBLIC_SIGN_IN_PATH, label: 'Sign in' },
{ href: PUBLIC_START_FREE_PILOT_PATH, label: 'Start 14-day pilot' },
];

export function PublicSiteFooter() {
Expand All @@ -22,7 +20,7 @@ export function PublicSiteFooter() {
<div className="space-y-1">
<p className="font-medium text-foreground">CallbackCloser</p>
<p>Stop missed calls from turning into lost jobs with fast follow-up and clearer owner handoff.</p>
<p>Try the simulator, start a 14-day pilot, and let CallbackCloser handle the setup before your workspace goes live.</p>
<p>Try the simulator, start a 14-day pilot, and review pricing, contact, refund, privacy, terms, and SMS consent before your workspace goes live.</p>
<p>
Contact:{' '}
<a className="underline underline-offset-4" href="mailto:support@callbackcloser.com">
Expand Down
59 changes: 27 additions & 32 deletions components/public-site-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,45 @@ import Link from 'next/link';

import { Badge } from '@/components/ui/badge';
import { buttonVariants } from '@/components/ui/button';
import { PUBLIC_CREATE_ACCOUNT_PATH, PUBLIC_SIGN_IN_PATH, PUBLIC_START_FREE_PILOT_PATH } from '@/lib/public-auth-routing';
import { PUBLIC_SIGN_IN_PATH, PUBLIC_START_FREE_PILOT_PATH } from '@/lib/public-auth-routing';

const primaryLinks = [
{ href: '/demo', label: 'Demo' },
{ href: '/simulator', label: 'Simulator' },
{ href: '/pricing', label: 'Pricing' },
{ href: '/contact', label: 'Contact' },
{ href: '/sms-consent', label: 'SMS Consent' },
{ href: '/privacy', label: 'Privacy' },
{ href: '/terms', label: 'Terms' },
];

export function PublicSiteNav() {
return (
<header className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80">
<div className="container flex flex-col gap-4 py-4 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link className="text-lg font-semibold tracking-tight" href="/">
CallbackCloser
</Link>
<Badge className="hidden sm:inline-flex" variant="outline">
Built for local service businesses
</Badge>
</div>
<div className="container py-4">
<div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3">
<Link className="text-lg font-semibold tracking-tight" href="/">
CallbackCloser
</Link>
<Badge className="w-fit" variant="outline">
Built for local service businesses
</Badge>
</div>

<div className="flex flex-col gap-3 sm:flex-row sm:items-center">
<nav className="flex flex-wrap items-center gap-4 text-sm text-muted-foreground">
{primaryLinks.map((link) => (
<Link key={link.href} className="transition-colors hover:text-foreground" href={link.href}>
{link.label}
</Link>
))}
</nav>
<div className="flex flex-col gap-3 lg:flex-row lg:items-center">
<nav className="flex flex-wrap items-center gap-x-4 gap-y-2 text-sm text-muted-foreground">
{primaryLinks.map((link) => (
<Link key={link.href} className="transition-colors hover:text-foreground" href={link.href}>
{link.label}
</Link>
))}
</nav>

<div className="flex items-center gap-2">
<Link className={buttonVariants({ size: 'sm', variant: 'ghost' })} href={PUBLIC_SIGN_IN_PATH}>
Sign in
</Link>
<Link className={buttonVariants({ size: 'sm', variant: 'outline' })} href={PUBLIC_CREATE_ACCOUNT_PATH}>
Create account
</Link>
<Link className={buttonVariants({ size: 'sm' })} href={PUBLIC_START_FREE_PILOT_PATH}>
Start 14-day pilot
</Link>
<div className="flex flex-wrap items-center gap-2">
<Link className={buttonVariants({ size: 'sm', variant: 'ghost' })} href={PUBLIC_SIGN_IN_PATH}>
Sign in
</Link>
<Link className={buttonVariants({ size: 'sm' })} href={PUBLIC_START_FREE_PILOT_PATH}>
Start 14-day pilot
</Link>
</div>
</div>
</div>
</div>
Expand Down
14 changes: 7 additions & 7 deletions tests/legal-pages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,25 +74,25 @@ test('public-facing surfaces link to trust and contact routes', () => {

assert.match(home, /href: '\/pricing'|href="\/pricing"/);
assert.match(home, /href: '\/sms-consent'|href="\/sms-consent"/);
assert.match(home, /PUBLIC_CREATE_ACCOUNT_PATH/);
assert.match(home, /PUBLIC_START_FREE_PILOT_PATH/);
assert.match(nav, /href: '\/demo'/);
assert.match(nav, /href: '\/pricing'/);
assert.match(nav, /href: '\/contact'/);
assert.match(nav, /href: '\/sms-consent'/);
assert.match(nav, /href: '\/privacy'/);
assert.match(nav, /href: '\/terms'/);
assert.match(nav, /href: '\/simulator'/);
assert.doesNotMatch(nav, /href: '\/demo'/);
assert.doesNotMatch(nav, /href: '\/sms-consent'/);
assert.doesNotMatch(nav, /href: '\/privacy'/);
assert.doesNotMatch(nav, /href: '\/terms'/);
assert.match(nav, /PUBLIC_SIGN_IN_PATH/);
assert.match(nav, /PUBLIC_CREATE_ACCOUNT_PATH/);
assert.match(nav, /PUBLIC_START_FREE_PILOT_PATH/);
assert.match(footer, /href: '\/privacy'/);
assert.match(footer, /href: '\/terms'/);
assert.match(footer, /href: '\/refund'/);
assert.match(footer, /href: '\/contact'/);
assert.match(footer, /href: '\/sms-consent'/);
assert.match(footer, /PUBLIC_CREATE_ACCOUNT_PATH/);
assert.match(footer, /PUBLIC_START_FREE_PILOT_PATH/);
assert.match(footer, /PUBLIC_SIGN_IN_PATH/);
assert.doesNotMatch(footer, /PUBLIC_CREATE_ACCOUNT_PATH/);
assert.doesNotMatch(footer, /href: '\/demo'/);

assert.match(billing, /href="\/pricing"/);
assert.match(billing, /href="\/refund"/);
Expand Down
1 change: 1 addition & 0 deletions tests/public-auth-routing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ test('clerk auth surfaces use explicit path routing and fallback redirects', ()
assert.match(signUpPage, /hasRequiredValidClerkEnv/);
assert.match(signUpPage, /Authentication is temporarily unavailable\./);
assert.match(signUpPage, /resolveSignedInAppDestination/);
assert.match(signUpPage, /Start 14-day pilot/);
assert.match(signUpPage, /we create your workspace, handle the setup for you/i);
assert.match(signUpPage, /do not need to configure the phone or messaging system yourself/i);
assert.match(pilotEntryPage, /resolvePublicPilotDestination/);
Expand Down
5 changes: 3 additions & 2 deletions tests/simulator-route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ function read(relativePath: string) {
return readFileSync(path.join(process.cwd(), relativePath), 'utf8');
}

test('homepage and nav point visitors to both the demo and simulator routes', () => {
test('homepage keeps demo access while the top nav stays focused on the simulator route', () => {
const home = read('app/page.tsx');
const nav = read('components/public-site-nav.tsx');

assert.match(home, /href="\/demo"/);
assert.match(nav, /href: '\/demo'/);
assert.match(home, /href="\/simulator"/);
assert.doesNotMatch(nav, /href: '\/demo'/);
assert.match(nav, /href: '\/simulator'/);
});

Expand Down
Loading