diff --git a/.gitignore b/.gitignore
index 355a1f06..ee49134f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,4 @@ pnpm-debug.log*
.DS_Store
.superpowers/
+.env.local
diff --git a/astro.config.mjs b/astro.config.mjs
index 26fbd2c1..8323703a 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -92,6 +92,7 @@ export default defineConfig({
"/home-new/",
"/endorsements-new/",
"/e4p/pledge-new/",
+ "/growthbook-test/",
];
return !exclude.some((path) => page.endsWith(path));
},
diff --git a/package.json b/package.json
index 79d2b982..104a39b0 100644
--- a/package.json
+++ b/package.json
@@ -29,6 +29,7 @@
"@emotion/styled": "^11.14.1",
"@fontsource/fraunces": "^5.2.9",
"@fontsource/outfit": "^5.2.8",
+ "@growthbook/growthbook-react": "^1.7.0",
"@iconify-json/simple-icons": "^1.2.54",
"@mui/icons-material": "^6.5.0",
"@mui/material": "^6.5.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 28df680b..2deddead 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -63,6 +63,9 @@ importers:
'@fontsource/outfit':
specifier: ^5.2.8
version: 5.2.8
+ '@growthbook/growthbook-react':
+ specifier: ^1.7.0
+ version: 1.7.0(react@19.2.0)
'@iconify-json/simple-icons':
specifier: ^1.2.54
version: 1.2.54
@@ -975,6 +978,16 @@ packages:
'@fontsource/outfit@5.2.8':
resolution: {integrity: sha512-rXC6g0MqD7cOBjht0bMqc43qM6lRqDLML9KXsmg9uykz0wLQhy8Z/ajrMG6iyoT3NJR+MYgU+OEHp7uHoTb+Yw==}
+ '@growthbook/growthbook-react@1.7.0':
+ resolution: {integrity: sha512-7TU0Yjmkl2Me8LKpG5cjqIsLSK+sz9T/1vocJAm49KsBeTvse6QwR9544KB9sU7eJF9qYVGr4GekW/r9bqmaWg==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ react: ^16.8.0-0 || ^17.0.0-0 || ^18.0.0-0 || ^19.0.0-0
+
+ '@growthbook/growthbook@1.7.0':
+ resolution: {integrity: sha512-Vmad3fWRh1XaFH4q+AS62ofX6Q3IxSTD7sBGuhEHCaad8VyZerxrVdojucjzlnJDUocfrnZFUSpEkR6R/wCV+A==}
+ engines: {node: '>=10'}
+
'@iconify-json/bi@1.2.6':
resolution: {integrity: sha512-fWfLr1/+DJDe8+rIUXxMwvmWBZFlxRtM59sYnrezJ2xX87QKyXVw3QuforJ4kF2Orrz85J+JTRG6305vaJ7flA==}
@@ -2335,6 +2348,10 @@ packages:
dom-helpers@5.2.1:
resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==}
+ dom-mutator@0.6.0:
+ resolution: {integrity: sha512-iCt9o0aYfXMUkz/43ZOAUFQYotjGB+GNbYJiJdz4TgXkyToXbbRy5S6FbTp72lRBtfpUMwEc1KmpFEU4CZeoNg==}
+ engines: {node: '>=10'}
+
dom-serializer@2.0.0:
resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
@@ -4956,6 +4973,15 @@ snapshots:
'@fontsource/outfit@5.2.8': {}
+ '@growthbook/growthbook-react@1.7.0(react@19.2.0)':
+ dependencies:
+ '@growthbook/growthbook': 1.7.0
+ react: 19.2.0
+
+ '@growthbook/growthbook@1.7.0':
+ dependencies:
+ dom-mutator: 0.6.0
+
'@iconify-json/bi@1.2.6':
dependencies:
'@iconify/types': 2.0.0
@@ -6494,6 +6520,8 @@ snapshots:
'@babel/runtime': 7.28.4
csstype: 3.1.3
+ dom-mutator@0.6.0: {}
+
dom-serializer@2.0.0:
dependencies:
domelementtype: 2.3.0
diff --git a/src/components/GrowthBookProvider.tsx b/src/components/GrowthBookProvider.tsx
new file mode 100644
index 00000000..dd73d8d3
--- /dev/null
+++ b/src/components/GrowthBookProvider.tsx
@@ -0,0 +1,14 @@
+import { GrowthBookProvider as GBProvider } from "@growthbook/growthbook-react";
+import type { ReactNode } from "react";
+import { growthbook } from "../growthbook";
+
+interface Props {
+ children: ReactNode;
+}
+
+// Wrap a client:only="react" island in this to read GrowthBook flags with
+// useFeatureIsOn / useFeatureValue. Each island mounts its own React root, so
+// there's no single app entry point to wrap once — use this per island instead.
+export default function GrowthBookProvider({ children }: Props) {
+ return