From 947ecf6b8afa452d10f304b63c298dc8885befaa Mon Sep 17 00:00:00 2001 From: Marc-Antoine Parent Date: Thu, 5 Feb 2026 20:55:07 -0500 Subject: [PATCH 1/3] ENG-1395 Add a route to get the anonymous key, and use it in roam build script --- apps/roam/build.sh | 1 + apps/website/app/api/supabase/env/route.ts | 22 ++++++++++++++++++++++ packages/database/scripts/createEnv.mts | 18 ++++++++++++++++-- 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 apps/website/app/api/supabase/env/route.ts diff --git a/apps/roam/build.sh b/apps/roam/build.sh index aab8d8f09..d859641c7 100755 --- a/apps/roam/build.sh +++ b/apps/roam/build.sh @@ -1,5 +1,6 @@ #!/bin/bash set -e +export ROAM_BUILD_SCRIPT=1 npm install -g corepack@latest corepack enable pnpm pnpm install diff --git a/apps/website/app/api/supabase/env/route.ts b/apps/website/app/api/supabase/env/route.ts new file mode 100644 index 000000000..91f20aee9 --- /dev/null +++ b/apps/website/app/api/supabase/env/route.ts @@ -0,0 +1,22 @@ +import { NextResponse, NextRequest } from "next/server"; +import { + handleRouteError, + defaultOptionsHandler, +} from "~/utils/supabase/apiUtils"; + +export const GET = async (request: NextRequest): Promise => { + try { + const { SUPABASE_URL, SUPABASE_ANON_KEY } = process.env; + if (!SUPABASE_URL || !SUPABASE_ANON_KEY) + return new NextResponse("Missing variables", { status: 500 }); + return NextResponse.json( + // eslint-disable-next-line @typescript-eslint/naming-convention + { SUPABASE_URL, SUPABASE_ANON_KEY }, + { status: 200 }, + ); + } catch (e: unknown) { + return handleRouteError(request, e, "/api/supabase/space"); + } +}; + +export const OPTIONS = defaultOptionsHandler; diff --git a/packages/database/scripts/createEnv.mts b/packages/database/scripts/createEnv.mts index d7142cfb0..469a1c02d 100644 --- a/packages/database/scripts/createEnv.mts +++ b/packages/database/scripts/createEnv.mts @@ -106,11 +106,25 @@ const makeProductionEnv = async (vercel: Vercel, vercelToken: string) => { }; const main = async (variant: Variant) => { - // Do not execute in deployment or github action. - if ( + if (process.env.ROAM_BUILD_SCRIPT) { + // special case: production build + try { + const response = execSync('curl https://discoursegraphs.com/api/supabase/env'); + const asJson = JSON.parse(response.toString()) as Record; + writeFileSync( + join(projectRoot, ".env"), + Object.entries(asJson).map(([k,v])=>`${k}=${v}`).join('\n') + ); + return; + } catch (e) { + console.error("Could not get environment from site") + } + } + else if ( process.env.HOME === "/vercel" || process.env.GITHUB_ACTIONS !== undefined ) + // Do not execute in deployment or github action. return; if (variant === Variant.none) return; From 27af10883576999ff1eed15fbf4bc3afafa11594 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Parent Date: Thu, 5 Feb 2026 20:59:51 -0500 Subject: [PATCH 2/3] correct route --- apps/website/app/api/supabase/env/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/website/app/api/supabase/env/route.ts b/apps/website/app/api/supabase/env/route.ts index 91f20aee9..e5a59a1dd 100644 --- a/apps/website/app/api/supabase/env/route.ts +++ b/apps/website/app/api/supabase/env/route.ts @@ -15,7 +15,7 @@ export const GET = async (request: NextRequest): Promise => { { status: 200 }, ); } catch (e: unknown) { - return handleRouteError(request, e, "/api/supabase/space"); + return handleRouteError(request, e, "/api/supabase/env"); } }; From a59b352731feaebde12d8b187b1d45cfccb58e70 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Parent Date: Fri, 6 Feb 2026 09:08:02 -0500 Subject: [PATCH 3/3] respond to comments --- apps/website/app/api/supabase/env/route.ts | 2 +- packages/database/scripts/createEnv.mts | 5 ++++- turbo.json | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/website/app/api/supabase/env/route.ts b/apps/website/app/api/supabase/env/route.ts index e5a59a1dd..d89572b7a 100644 --- a/apps/website/app/api/supabase/env/route.ts +++ b/apps/website/app/api/supabase/env/route.ts @@ -4,7 +4,7 @@ import { defaultOptionsHandler, } from "~/utils/supabase/apiUtils"; -export const GET = async (request: NextRequest): Promise => { +export const GET = (request: NextRequest): NextResponse => { try { const { SUPABASE_URL, SUPABASE_ANON_KEY } = process.env; if (!SUPABASE_URL || !SUPABASE_ANON_KEY) diff --git a/packages/database/scripts/createEnv.mts b/packages/database/scripts/createEnv.mts index 469a1c02d..15aa5f690 100644 --- a/packages/database/scripts/createEnv.mts +++ b/packages/database/scripts/createEnv.mts @@ -5,6 +5,7 @@ import { fileURLToPath } from "node:url"; import dotenv from "dotenv"; import { Vercel } from "@vercel/sdk"; +// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = dirname(fileURLToPath(import.meta.url)); const projectRoot = join(__dirname, ".."); const baseParams: Record = {}; @@ -117,7 +118,9 @@ const main = async (variant: Variant) => { ); return; } catch (e) { - console.error("Could not get environment from site") + if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY) + return; + throw new Error("Could not get environment from site"); } } else if ( diff --git a/turbo.json b/turbo.json index 83bbe601f..8aadd5604 100644 --- a/turbo.json +++ b/turbo.json @@ -30,6 +30,7 @@ "GEMINI_API_KEY", "GH_CLIENT_SECRET_PROD", "GITHUB_ACTIONS", + "HOME", "OPENAI_API_KEY", "POSTGRES_PASSWORD", "POSTGRES_USER", @@ -42,6 +43,7 @@ ], "tasks": { "build": { + "env": ["ROAM_BUILD_SCRIPT"], "dependsOn": ["@repo/database#genenv"], "inputs": ["$TURBO_DEFAULT$", ".env*"], "outputs": [".next/**", "!.next/cache/**", "dist/**", "src/dbTypes.ts"] @@ -69,7 +71,7 @@ "with": ["@repo/database#dev"] }, "genenv": { - "env": ["SUPABASE_USE_DB"], + "env": ["SUPABASE_USE_DB", "ROAM_BUILD_SCRIPT"], "cache": false, "outputs": [".env*"] },