diff --git a/apps/marketing-app/next.config.ts b/apps/marketing-app/next.config.ts index 06a43953..b19a5160 100644 --- a/apps/marketing-app/next.config.ts +++ b/apps/marketing-app/next.config.ts @@ -4,6 +4,64 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { reactStrictMode: true, transpilePackages: ["@asyncstatus/ui"], + + // Performance optimizations + compress: true, + poweredByHeader: false, + + // Image optimization + images: { + formats: ["image/avif", "image/webp"], + minimumCacheTTL: 31536000, // 1 year + dangerouslyAllowSVG: true, + contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;", + }, + + // Headers for SEO and security + async headers() { + return [ + { + source: "/(.*)", + headers: [ + { + key: "X-Content-Type-Options", + value: "nosniff", + }, + { + key: "X-Frame-Options", + value: "DENY", + }, + { + key: "X-XSS-Protection", + value: "1; mode=block", + }, + { + key: "Referrer-Policy", + value: "strict-origin-when-cross-origin", + }, + ], + }, + // Cache static assets + { + source: "/favicon.ico", + headers: [ + { + key: "Cache-Control", + value: "public, max-age=31536000, immutable", + }, + ], + }, + { + source: "/(.*\\.(?:ico|png|jpg|jpeg|gif|svg|webp|avif))", + headers: [ + { + key: "Cache-Control", + value: "public, max-age=31536000, immutable", + }, + ], + }, + ]; + }, }; export default nextConfig; diff --git a/apps/marketing-app/src/app/(app)/page.tsx b/apps/marketing-app/src/app/(app)/page.tsx index 8ed67021..a80d6fd3 100644 --- a/apps/marketing-app/src/app/(app)/page.tsx +++ b/apps/marketing-app/src/app/(app)/page.tsx @@ -1,6 +1,33 @@ import { AsyncStatusLogo } from "@asyncstatus/ui/components/async-status-logo"; import { Button } from "@asyncstatus/ui/components/button"; import Link from "next/link"; +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: "Home", + description: "Replace daily standup meetings with automated status updates. AsyncStatus saves your team 2-3 hours per week by generating updates from Git, Jira, and Slack activity automatically.", + openGraph: { + title: "AsyncStatus - Automated Status Updates for Remote Teams", + description: "Replace daily standup meetings with automated status updates. Save 2-3 hours per developer per week.", + url: "https://asyncstatus.com", + images: [ + { + url: "/opengraph-image.jpg", + width: 1200, + height: 630, + alt: "AsyncStatus - No more daily standups, just automated status updates", + }, + ], + }, + twitter: { + card: "summary_large_image", + title: "AsyncStatus - Automated Status Updates for Remote Teams", + description: "Replace daily standup meetings with automated status updates. Save 2-3 hours per developer per week.", + }, + alternates: { + canonical: "https://asyncstatus.com", + }, +}; import { BetaMessage } from "../components/beta-message"; import { ConnectCard } from "../components/connect-card"; import { CtaSection } from "../components/cta-section"; @@ -16,6 +43,7 @@ import { TrackCard } from "../components/track-card"; import { UseItYourWay } from "../components/use-it-your-way"; import { peopleSummary } from "./people-summary"; import { PersonSelect } from "./person-select"; +import { StructuredData, organizationSchema, productSchema, websiteSchema, faqSchema } from "../structured-data"; export default async function Page(props: { searchParams: Promise<{ [key: string]: string | string[] | undefined }>; @@ -48,7 +76,7 @@ export default async function Page(props: {
-

AsyncStatus

+ AsyncStatus
@@ -137,21 +165,21 @@ export default async function Page(props: { -

+

Standup meetings suck -

-

+

+

Standup meetings suck -

+ -

+

Your team already pushed code, closed tickets, replied in threads, fixed small things no one asked them to. We turn it into an update. Or you can write it yourself. Either way, no one has to talk about it at 9:30 a.m. -

+

-

+

How it works -

+
@@ -301,13 +329,13 @@ export default async function Page(props: {
-

+

Calculate your savings -

-

+

+

See how much time and money your team can save by replacing synchronous standups with AsyncStatus. - +

@@ -345,6 +373,12 @@ export default async function Page(props: {