Skip to content

Finish the config seam: supabase, turnstile and Google Drive - #25

Open
playforge-coding wants to merge 1 commit into
core-api-clientsfrom
core-auth-config
Open

Finish the config seam: supabase, turnstile and Google Drive#25
playforge-coding wants to merge 1 commit into
core-api-clientsfrom
core-auth-config

Conversation

@playforge-coding

@playforge-coding playforge-coding commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Stacked on #24. The last three modules reading import.meta.env at module scope.

main.jsx is now the only place in the app that touches it.

supabase.js was the awkward one

It built its client at module scope:

export const supabase = supabaseEnabled ? createClient(SUPABASE_URL, ...) : null;

A straight substitution would have constructed it from an unconfigured seam — ES imports are hoisted, so configureCore runs after every module in the graph is evaluated. It now builds inside getSupabase(), memoised, because the SDK owns the session and its auto-refresh timer and there must be exactly one. STORAGE_KEY became storageKey() for the same reason.

Blast radius turned out to be one file: auth.jsx was the only consumer.

Two more module-scope flags

supabaseEnabled and googleDriveEnabled go the way of the four in #24 — both were module-scope Boolean(env), both would have read false under a lazy config. Now hasSupabase() and hasGoogleDrive().

All three are browser tier

localStorage for the session, window.open for the OAuth popup, the Turnstile widget — the lint rule places them correctly without being told.

Also

  • collab.js keeps its React hook and stays in apps/web, but reads apiUrl() now, so nothing outside main.jsx reaches for the bundler.
  • @supabase/supabase-js and docx move to core's dependencies; apps/web imports neither directly any more.
  • 3 new config tests (41 in core now), including that supabaseConfig() needs both halves.

Where phase 1 actually stands

I said this would leave apps/web/src/lib containing nothing but React. It doesn't, quite — 11 React-free files remain:

Genuinely stuck Why
i18n.js, languages.js bound to react-i18next
git/engine.js, git/load.js the dynamic-import boundary and Buffer polyfill — bundler concerns, must stay in the app
utils.js cn(), the shadcn/Tailwind helper — UI layer
Movable, not yet moved Lines
richText.js (DOMPurify pass), wikimedia.js (browser adapter), presence.js, summarizer.js, git/fs.js, git/sync.js ~1,400

That last group is a part C. Nothing blocks it now that the seam is complete — it just wasn't in scope here.

Verification

pnpm lint, pnpm test (core 41, api 27, mcp 14), pnpm build, pnpm build:docs all pass. Verified by grep that no import.meta.env survives outside main.jsx, and that no config accessor is called at module scope in either package.

The last three modules reading import.meta.env at module scope. main.jsx is now
the only place in the app that touches it.

supabase.js was the awkward one: it built its client at module scope, so a
straight substitution would have constructed it from an unconfigured seam (ES
imports are hoisted, so configureCore runs after every module is evaluated). It
now builds inside getSupabase(), memoised — the SDK owns the session and its
refresh timer, so there must be exactly one. STORAGE_KEY became storageKey() for
the same reason. Only auth.jsx consumed any of this, so the blast radius was one
file.

supabaseEnabled and googleDriveEnabled go the way of the four flags in the
previous PR: both were module-scope Boolean(env), both would have read false.
They are hasSupabase() and hasGoogleDrive() on the config.

All three land in the browser tier rather than the neutral one — localStorage,
window.open for the OAuth popup, and the Turnstile widget are all browser
things. The lint rule places them correctly without being told.

collab.js keeps its React hook and stays in apps/web, but reads apiUrl() now
too, so no module outside main.jsx reaches for the bundler.

@supabase/supabase-js and docx move to core's dependencies; nothing in apps/web
imports either directly any more.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e65c61ce-3883-4038-9884-357d3e14f9d5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant