Add OG/Twitter sharing metadata and screenshot for all marketing pages

- Update root layout with full Open Graph, Twitter Card, and SEO metadata
- Add OG image screenshot (1200x630) of the landing page hero
- Create layout.tsx with page-specific metadata for each marketing page
  (welcome, features index, 8 feature detail pages, pricing)
- Use Next.js title template ("%s | Echo") for consistent page titles
- Add NEXT_PUBLIC_SITE_URL to .env.example for metadataBase config

Made-with: Cursor
This commit is contained in:
Randall Stillwell 2026-04-16 20:34:26 -05:00
parent 7c4ec7bb9d
commit c9f5b1e2ee
15 changed files with 244 additions and 2 deletions

View file

@ -34,5 +34,8 @@ EMAIL_FROM_ADDRESS="mars@noreply.stillwell.cloud"
# Vercel auto-sets this on Pro. Used to authenticate cron job requests.
CRON_SECRET=""
# ─── Public site URL (used for OG metadata, canonical links) ─
NEXT_PUBLIC_SITE_URL="https://echoocr.com"
# ─── Environment indicator ────────────────────────────────────
NEXT_PUBLIC_ENV=""

BIN
public/og-image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 KiB

View file

@ -0,0 +1,17 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "AI-Powered OCR",
description:
"Echo's vision AI reads handwriting, checkboxes, and printed text — extracting 20+ fields per card including names, contact info, prayer requests, and spiritual decisions with over 95% accuracy.",
openGraph: {
title: "AI-Powered OCR | Echo",
description:
"Vision AI that reads handwriting, checkboxes, and printed text — 20+ fields per card with 95%+ accuracy.",
images: ["/og-image.png"],
},
};
export default function AiOcrLayout({ children }: { children: React.ReactNode }) {
return <>{children}</>;
}

View file

@ -0,0 +1,17 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Dashboard & Analytics",
description:
"See first-time guests, salvations, prayer requests, and follow-up status at a glance. Filter, sort, and export your data — powerful card tables with actionable guest insights.",
openGraph: {
title: "Dashboard & Analytics | Echo",
description:
"Real-time stats, powerful filtering, status tracking, and CSV export for your guest services data.",
images: ["/og-image.png"],
},
};
export default function AnalyticsLayout({ children }: { children: React.ReactNode }) {
return <>{children}</>;
}

View file

@ -0,0 +1,17 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Collection Days & Events",
description:
"Define recurring Sunday services and special events with flexible RFC 5545 scheduling. Echo auto-assigns scanned cards to the right event, keeping everything organized.",
openGraph: {
title: "Collection Days & Events | Echo",
description:
"Recurring services, special events, and automatic card-to-event assignment — keep everything organized.",
images: ["/og-image.png"],
},
};
export default function CollectionDaysLayout({ children }: { children: React.ReactNode }) {
return <>{children}</>;
}

View file

@ -0,0 +1,17 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Integrations",
description:
"Sync scanned card data to Planning Center, Google Sheets, Monday.com, Airtable, or any system via webhooks. Echo fits into the tools your church already uses.",
openGraph: {
title: "Integrations | Echo",
description:
"Planning Center, Google Sheets, Monday.com, Airtable, webhooks, and CSV export — Echo fits into your existing workflow.",
images: ["/og-image.png"],
},
};
export default function IntegrationsLayout({ children }: { children: React.ReactNode }) {
return <>{children}</>;
}

View file

@ -0,0 +1,17 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Features",
description:
"Explore Echo's full feature set — AI-powered OCR, scanner integration, team collaboration, multi-site management, analytics, and integrations with Planning Center, Google Sheets, and more.",
openGraph: {
title: "Features | Echo",
description:
"Everything your guest services team needs — from AI scanning to Planning Center sync.",
images: ["/og-image.png"],
},
};
export default function FeaturesLayout({ children }: { children: React.ReactNode }) {
return <>{children}</>;
}

View file

@ -0,0 +1,17 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Multi-Site Management",
description:
"Manage multiple campuses under one organization. Each location gets its own collection days, scanner setup, and team assignments — with unified reporting across all sites.",
openGraph: {
title: "Multi-Site Management | Echo",
description:
"Independent schedules per campus, unified processing pipeline, and organization-wide reporting.",
images: ["/og-image.png"],
},
};
export default function MultiSiteLayout({ children }: { children: React.ReactNode }) {
return <>{children}</>;
}

View file

@ -0,0 +1,17 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Scanner Integration",
description:
"Connect your office scanner via email or FTP and Echo picks up batches automatically. Or upload photos and PDFs from your phone — supports duplex scanning with front/back pairing.",
openGraph: {
title: "Scanner Integration | Echo",
description:
"Email, FTP, or drag-and-drop — get scanned cards into Echo however works best for your team.",
images: ["/og-image.png"],
},
};
export default function ScannerIntegrationLayout({ children }: { children: React.ReactNode }) {
return <>{children}</>;
}

View file

@ -0,0 +1,17 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Security & Privacy",
description:
"Role-based permissions, encrypted storage, email verification, invitation-only access, SSO support, and enterprise-grade infrastructure protect your congregation's personal data.",
openGraph: {
title: "Security & Privacy | Echo",
description:
"Encryption, RBAC, SSO, audit trails, and invitation-only access — your congregation's data stays safe.",
images: ["/og-image.png"],
},
};
export default function SecurityLayout({ children }: { children: React.ReactNode }) {
return <>{children}</>;
}

View file

@ -0,0 +1,17 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Team Collaboration",
description:
"Invite your pastoral care team with five role tiers, assign cards for follow-up, track review status, and keep everyone on the same page with in-app notifications.",
openGraph: {
title: "Team Collaboration | Echo",
description:
"Role-based access, card assignment, review workflows, and notifications for your whole team.",
images: ["/og-image.png"],
},
};
export default function TeamCollaborationLayout({ children }: { children: React.ReactNode }) {
return <>{children}</>;
}

View file

@ -1,3 +1,11 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
alternates: {
canonical: "/welcome",
},
};
export default function MarketingLayout({
children,
}: {

View file

@ -0,0 +1,17 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Pricing",
description:
"Simple, transparent pricing for churches of every size. Start free with 50 cards/month, then scale as you grow. All paid plans include a 14-day free trial.",
openGraph: {
title: "Pricing | Echo",
description:
"Start free with 50 cards/month. Upgrade when you're ready — no contract, no commitment.",
images: ["/og-image.png"],
},
};
export default function PricingLayout({ children }: { children: React.ReactNode }) {
return <>{children}</>;
}

View file

@ -0,0 +1,16 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Echo — AI-Powered Response Card Scanning for Churches",
description:
"Stop hand-typing visitor cards. Echo uses AI to scan guest cards, prayer requests, and response forms — then syncs to Planning Center, your CRM, or wherever your team needs it.",
openGraph: {
title: "Echo — AI-Powered Response Card Scanning for Churches",
description:
"Stop hand-typing visitor cards. Scan guest cards with AI and sync to Planning Center in seconds.",
},
};
export default function WelcomeLayout({ children }: { children: React.ReactNode }) {
return <>{children}</>;
}

View file

@ -9,9 +9,54 @@ const quicksand = Quicksand({
weight: ["300", "400", "500", "600", "700"],
});
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://echoocr.com";
export const metadata: Metadata = {
title: "Echo OCR",
description: "Response card scanning and management",
title: {
default: "Echo — AI-Powered Response Card Scanning for Churches",
template: "%s | Echo",
},
description:
"Stop hand-typing visitor cards. Echo uses AI to scan guest cards, prayer requests, and response forms — then syncs to Planning Center, your CRM, or wherever your team needs it.",
metadataBase: new URL(siteUrl),
openGraph: {
type: "website",
siteName: "Echo",
title: "Echo — AI-Powered Response Card Scanning for Churches",
description:
"Stop hand-typing visitor cards. Echo uses AI to scan guest cards, prayer requests, and response forms — then syncs to Planning Center, your CRM, or wherever your team needs it.",
images: [
{
url: "/og-image.png",
width: 1200,
height: 630,
alt: "Echo — Stop hand-typing visitor cards",
},
],
},
twitter: {
card: "summary_large_image",
title: "Echo — AI-Powered Response Card Scanning for Churches",
description:
"Stop hand-typing visitor cards. Echo uses AI to scan guest cards, prayer requests, and response forms — then syncs to Planning Center, your CRM, or wherever your team needs it.",
images: ["/og-image.png"],
},
keywords: [
"church OCR",
"visitor card scanning",
"guest card scanner",
"response card digitization",
"Planning Center integration",
"church management",
"AI OCR",
"prayer request scanning",
"connection card scanner",
"church guest services",
],
robots: {
index: true,
follow: true,
},
};
export default function RootLayout({