···11NEXT_PUBLIC_APP_URL=http://localhost:3000
2233+# Prelaunch feature flag.
44+# When `true`, hide elements intended to ship only after launch.
55+NEXT_PUBLIC_PRELAUNCH=false
66+77+38# Stripe keys
49# https://dashboard.stripe.com/apikeys
510NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_12345
+7
app/components/pricing/pricing-section.tsx
···77import { ButtonLink } from "@/components/button-link";
88import { Heading } from "@/components/heading";
99import { Paragraph } from "@/components/paragraph";
1010+import { prelaunch } from "@/lib/prelaunch";
10111112type PricingPlan = {
1213 key: string;
···1819 highlight?: boolean;
1920 pdsDiskSizeGb: number;
2021 features: string[];
2222+ launchOnly?: boolean;
2123};
22242325const PLANS: PricingPlan[] = [
···5860 period: "per month",
5961 description: "Enterprise‑level performance.",
6062 pdsDiskSizeGb: 200,
6363+ launchOnly: true,
6164 features: [
6265 "Unlimited storage",
6366 "Custom domain support",
···6972];
70737174export function PricingSection() {
7575+ // Hide the pricing block entirely during prelaunch mode.
7676+ // This keeps the "prelaunch vs launch" behavior controlled by one global flag.
7777+ if (prelaunch) return null;
7878+7279 return (
7380 <section
7481 id="pricing"
+9
lib/prelaunch.ts
···11+/**
22+ * Feature flag for “prelaunch” mode.
33+ *
44+ * Set `NEXT_PUBLIC_PRELAUNCH=true` to enable prelaunch gating that hides
55+ * elements meant to ship only after launch.
66+ */
77+export const prelaunch =
88+ process.env.NEXT_PUBLIC_PRELAUNCH?.toLowerCase() === "true";
99+