From 10eaa29b93cd69b3545d6071eb4e37a5c703ae75 Mon Sep 17 00:00:00 2001 From: Sejal Batra Date: Thu, 27 Aug 2026 18:19:50 +0530 Subject: [PATCH 1/2] Add /launch squeeze page Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_011o5vpPXd6NvFFj43ZGRUbS --- website/astro.config.mjs | 4 + website/src/api/client.ts | 9 + .../features/launch/AsciiFrame.astro | 225 +++++++++++++ .../features/launch/FactsSection.astro | 93 ++++++ .../features/launch/HeroSection.astro | 49 +++ .../features/launch/SignupForm.astro | 309 ++++++++++++++++++ website/src/components/layout/Layout.astro | 8 +- website/src/constants/waitlist.ts | 16 + website/src/i18n/de-DE.json | 30 ++ website/src/i18n/en-US.json | 30 ++ website/src/i18n/es-ES.json | 30 ++ website/src/i18n/hi-IN.json | 30 ++ website/src/i18n/id-ID.json | 30 ++ website/src/i18n/ja-JP.json | 30 ++ website/src/i18n/ko-KR.json | 30 ++ website/src/i18n/ru-RU.json | 30 ++ website/src/i18n/zh-CN.json | 30 ++ website/src/pages/[lang]/launch.astro | 85 +++++ website/src/pages/launch.astro | 77 +++++ website/src/styles/fonts.css | 2 +- 20 files changed, 1143 insertions(+), 4 deletions(-) create mode 100644 website/src/components/features/launch/AsciiFrame.astro create mode 100644 website/src/components/features/launch/FactsSection.astro create mode 100644 website/src/components/features/launch/HeroSection.astro create mode 100644 website/src/components/features/launch/SignupForm.astro create mode 100644 website/src/constants/waitlist.ts create mode 100644 website/src/pages/[lang]/launch.astro create mode 100644 website/src/pages/launch.astro diff --git a/website/astro.config.mjs b/website/astro.config.mjs index 643583c2..509198a7 100644 --- a/website/astro.config.mjs +++ b/website/astro.config.mjs @@ -70,8 +70,12 @@ export default defineConfig({ const path = new URL(page).pathname.replace(/\/$/, "") || "/"; const isTeamIndex = path === "/team" || /\/[a-z]{2}-[A-Z]{2}\/team$/.test(path); + // Squeeze page: indexable and shareable, but kept out of the sitemap. + const isLaunch = + path === "/launch" || /\/[a-z]{2}-[A-Z]{2}\/launch$/.test(path); return ( !isTeamIndex && + !isLaunch && !page.includes("/tags/") && !page.includes("/account/") && !page.includes("/oauth/") && diff --git a/website/src/api/client.ts b/website/src/api/client.ts index ae6d1c21..d383e8b8 100644 --- a/website/src/api/client.ts +++ b/website/src/api/client.ts @@ -35,6 +35,10 @@ interface ContactData { interface SubscribeData { email: string; + firstName: string; + lastName: string; + /** Which list this signup belongs to. Omitted by the site newsletter. */ + source?: string; } export interface Entrant { @@ -106,11 +110,15 @@ const createApiClient = () => { /** * Subscribe to waitlist + * + * `source` identifies which list the signup belongs to. Omitting it + * produces the original payload, so existing callers are unaffected. */ subscribe: ( email: string, firstName: string, lastName: string, + source?: string, ): ApiResponse => { return fetch(`${env.API_URL}/waitlist`, { headers: { @@ -121,6 +129,7 @@ const createApiClient = () => { email, firstName, lastName, + ...(source ? { source } : {}), } as SubscribeData), }); }, diff --git a/website/src/components/features/launch/AsciiFrame.astro b/website/src/components/features/launch/AsciiFrame.astro new file mode 100644 index 00000000..d4b1de7b --- /dev/null +++ b/website/src/components/features/launch/AsciiFrame.astro @@ -0,0 +1,225 @@ +--- +/** + * ASCII edge framing for /launch. + * + * Uses the home hero's generator unchanged — renderASCIIRect over the + * chladniRect field, same RAMP (" .,·:;|+x#"), same node-threshold density + * gradient. One continuous field is generated for the whole section, then + * sliced into four edge strips, so the pattern is the same one Home draws, + * just framing the content instead of running full-bleed behind it. + * + * Character advance and line height are measured from a live probe rather + * than estimated, so the strip geometry lands exactly and the left/right + * insets stay symmetrical. + */ +--- + + + + + + diff --git a/website/src/components/features/launch/FactsSection.astro b/website/src/components/features/launch/FactsSection.astro new file mode 100644 index 00000000..8a688f37 --- /dev/null +++ b/website/src/components/features/launch/FactsSection.astro @@ -0,0 +1,93 @@ +--- +import Button from "@/components/ui/Button.astro"; +import { createTranslator, getLocaleFromUrl } from "@/utils/i18n"; + +const locale = getLocaleFromUrl(Astro.url.pathname); +const t = await createTranslator(locale); +--- + +
+
+ {t("launch.facts.supply.label")} + {t("launch.facts.supply.value")} +
+ +
+ {t("launch.facts.consensus.label")} + + +
+
+ + diff --git a/website/src/components/features/launch/HeroSection.astro b/website/src/components/features/launch/HeroSection.astro new file mode 100644 index 00000000..7d1e6ab1 --- /dev/null +++ b/website/src/components/features/launch/HeroSection.astro @@ -0,0 +1,49 @@ +--- +import LogoLong from "@/assets/brand/logo-long.svg"; +import { createTranslator, getLocaleFromUrl } from "@/utils/i18n"; + +const locale = getLocaleFromUrl(Astro.url.pathname); +const t = await createTranslator(locale); +--- + +
+
+ + diff --git a/website/src/components/features/launch/SignupForm.astro b/website/src/components/features/launch/SignupForm.astro new file mode 100644 index 00000000..07e1a0ee --- /dev/null +++ b/website/src/components/features/launch/SignupForm.astro @@ -0,0 +1,309 @@ +--- +import Button from "@/components/ui/Button.astro"; +import { createTranslator, getLocaleFromUrl } from "@/utils/i18n"; +import { WAITLIST_SOURCE, type WaitlistSource } from "@/constants/waitlist"; + +interface Props { + /** Which waitlist these signups belong to. */ + source?: WaitlistSource; +} + +const { source = WAITLIST_SOURCE.LAUNCH } = Astro.props; + +const locale = getLocaleFromUrl(Astro.url.pathname); +const t = await createTranslator(locale); +--- + + + + + + diff --git a/website/src/components/layout/Layout.astro b/website/src/components/layout/Layout.astro index c761ad42..f3a581ee 100644 --- a/website/src/components/layout/Layout.astro +++ b/website/src/components/layout/Layout.astro @@ -39,9 +39,11 @@ import env from "@/config"; interface Props extends SEOProps { jsonLd?: WithContext | Graph; + /** Render the navbar and footer. Off for standalone pages like /launch. */ + showChrome?: boolean; } -const { jsonLd, ...metadata } = Astro.props; +const { jsonLd, showChrome = true, ...metadata } = Astro.props; const currentLocale = getLocaleFromUrl(Astro.url.pathname); const t = await createTranslator(currentLocale); @@ -115,11 +117,11 @@ const breadcrumbs = generateBreadcrumbs({ ) } - + {showChrome && }
-