Skip to content

(SP: 1) [FIX] Add netlify-plugin-bundle-env for Netlify SSR env var delivery#426

Merged
ViktorSvertoka merged 8 commits intodevelopfrom
sl/feat/db-optimization
Mar 28, 2026
Merged

(SP: 1) [FIX] Add netlify-plugin-bundle-env for Netlify SSR env var delivery#426
ViktorSvertoka merged 8 commits intodevelopfrom
sl/feat/db-optimization

Conversation

@LesiaUKR
Copy link
Copy Markdown
Collaborator

@LesiaUKR LesiaUKR commented Mar 28, 2026

Goal

Fix all SSR page crashes on Netlify develop deploy caused by environment variables not reaching serverless function runtime.

Scope

  • Add netlify-plugin-bundle-env plugin to netlify.toml — embeds env vars into serverless functions during build, as recommended by Netlify docs
  • Remove unsafe env block from next.config.ts that inlined server secrets into client-side bundles
  • Keep diagnostic runtime env log in db/index.ts until fix is confirmed

Context

Netlify does not deliver dashboard env vars to Next.js SSR runtime — this is a known platform limitation (opennextjs/opennextjs-netlify#2754). The official workaround is netlify-plugin-bundle-env, which injects env vars into function bundles at build time.

Expected impact

All 28 SSR pages (blog, quizzes, leaderboard, dashboard, shop, auth, admin) should work on Netlify develop deploy.

Out of scope

  • Blog categories hardcode in header — separate follow-up after SSR stability confirmed
  • Removing diagnostic log from db/index.ts — after env vars confirmed in runtime logs

Summary by CodeRabbit

  • Refactor
    • Blog categories are now dynamically fetched during application initialization instead of remaining empty.
  • Chore
    • Runtime environment variable handling updated to expose additional variables.
    • Deployment config updated to include an additional Netlify plugin.
    • Internal local-database guard behavior adjusted (no user-facing API changes).

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
devlovers-net Ignored Ignored Preview Mar 28, 2026 3:00pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 28, 2026

📝 Walkthrough

Walkthrough

Layout now concurrently fetches blog categories via getCachedBlogCategories(locale) alongside getMessages({ locale }). next.config.ts no longer restricts exported env keys to APP_ENV/DATABASE_URL. netlify.toml gains the netlify-plugin-bundle-env plugin. A local DB guard line in frontend/db/index.ts was altered.

Changes

Cohort / File(s) Summary
Layout / Data Fetching
frontend/app/[locale]/layout.tsx
Reintroduced getCachedBlogCategories(locale) and fetches messages and blogCategories concurrently with Promise.all, replacing the prior hardcoded empty categories.
Next.js Env Config
frontend/next.config.ts
Removed explicit nextConfig.env mapping for APP_ENV and DATABASE_URL; config now derives environment variables dynamically from process.env.
Database guard
frontend/db/index.ts
Modified the STRICT_LOCAL_DB_GUARD line (text changed to include a leading 0 before const), affecting the local-only DB guard expression/parse.
Netlify config
netlify.toml
Added a second [[plugins]] entry for netlify-plugin-bundle-env, alongside the existing Next.js plugin.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • AM1007
  • ViktorSvertoka
  • liudmylasovetovs

Poem

🐇 I hopped through code at break of day,
Fetching categories along the way,
Env keys stretched wide, plugins in tow,
A tiny guard line changed its flow —
Hooray, the rabbit gives a grateful sway! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Add netlify-plugin-bundle-env for Netlify SSR env var delivery' accurately describes the primary change (adding a Netlify plugin), which is one of the four file changes. However, it does not convey that the broader objective is fixing SSR 500 errors across all DB-dependent pages by enabling dynamic filtering of all server environment variables at build time—the main point of the PR. The title is partially related but narrows focus to just the plugin addition rather than the core fix.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sl/feat/db-optimization

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/app/`[locale]/layout.tsx:
- Around line 28-31: The parallel fetch currently uses Promise.all so a
rejection from getCachedBlogCategories aborts the whole layout; change the logic
to treat blogCategories as optional by catching errors from
getCachedBlogCategories (or using Promise.allSettled) and defaulting
blogCategories to [] on failure while still throwing or propagating errors from
getMessages, and log the error; update the code around the Promise.all call that
assigns [messages, blogCategories] so AppChrome always receives an array
(possibly empty) for blogCategories instead of letting a DB rejection bubble up.

In `@frontend/next.config.ts`:
- Around line 8-12: The current next.config.ts mirrors process.env into
nextConfig.env using Object.fromEntries(process.env), which both causes Next.js
build errors for reserved keys (e.g., NODE_ENV, NEXT_RUNTIME) and leaks
server-only secrets to the client; remove this env mirroring entirely (delete
the env: Object.fromEntries(...) block) and instead rely on server-side
process.env access in App Router/server components for secrets, and only expose
client-safe values via NEXT_PUBLIC_* (if any) by referencing
process.env.NEXT_PUBLIC_* at build/runtime rather than injecting a blanket env
object; ensure code paths that used nextConfig.env are updated to read
process.env directly (e.g., code in frontend/proxy.ts,
frontend/lib/security/csrf.ts, frontend/lib/shop/status-token.ts,
frontend/lib/email/transporter.ts) so secrets remain server-only.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d96bba41-c318-4699-853b-6579bf1a317e

📥 Commits

Reviewing files that changed from the base of the PR and between 6e021de and 10dbd14.

📒 Files selected for processing (2)
  • frontend/app/[locale]/layout.tsx
  • frontend/next.config.ts

Comment on lines +28 to +31
const [messages, blogCategories] = await Promise.all([
getMessages({ locale }),
getCachedBlogCategories(locale),
]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don't let blog-category lookup reintroduce global 500s.

getCachedBlogCategories() is just a cached DB wrapper with no fallback, so one rejection here aborts the entire locale layout again. Since blogCategories is optional in AppChrome, this should degrade to [] instead of taking down dashboard/auth/leaderboard pages that don't need blog nav data to render.

💡 Suggested fix
-  const [messages, blogCategories] = await Promise.all([
-    getMessages({ locale }),
-    getCachedBlogCategories(locale),
-  ]);
+  const [messagesResult, blogCategoriesResult] = await Promise.allSettled([
+    getMessages({ locale }),
+    getCachedBlogCategories(locale),
+  ]);
+
+  if (messagesResult.status === 'rejected') throw messagesResult.reason;
+
+  const messages = messagesResult.value;
+  const blogCategories =
+    blogCategoriesResult.status === 'fulfilled'
+      ? blogCategoriesResult.value
+      : [];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/`[locale]/layout.tsx around lines 28 - 31, The parallel fetch
currently uses Promise.all so a rejection from getCachedBlogCategories aborts
the whole layout; change the logic to treat blogCategories as optional by
catching errors from getCachedBlogCategories (or using Promise.allSettled) and
defaulting blogCategories to [] on failure while still throwing or propagating
errors from getMessages, and log the error; update the code around the
Promise.all call that assigns [messages, blogCategories] so AppChrome always
receives an array (possibly empty) for blogCategories instead of letting a DB
rejection bubble up.

@LesiaUKR LesiaUKR changed the title Fix all SSR page 500 errors on Netlify develop deploy — not just layout, but leaderboard, dashboard, auth, and all 28 DB-dependent pages. (SP: 1) [FIX] Add netlify-plugin-bundle-env for Netlify SSR env var delivery Mar 28, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/db/index.ts`:
- Line 29: Remove the stray leading character before the declaration: change the
malformed token "0const STRICT_LOCAL_DB_GUARD = process.env.SHOP_STRICT_LOCAL_DB
=== '1';" to a valid const declaration "const STRICT_LOCAL_DB_GUARD =
process.env.SHOP_STRICT_LOCAL_DB === '1';" so the module parses and the
SHOP_STRICT_LOCAL_DB guard (STRICT_LOCAL_DB_GUARD) can run; after fixing, run
TypeScript/ESLint or a quick build to confirm no other syntax errors remain.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dbee9dbb-bb15-46a9-b5b2-4299abc4f561

📥 Commits

Reviewing files that changed from the base of the PR and between 10dbd14 and 12d4439.

📒 Files selected for processing (3)
  • frontend/db/index.ts
  • frontend/next.config.ts
  • netlify.toml
💤 Files with no reviewable changes (1)
  • frontend/next.config.ts
✅ Files skipped from review due to trivial changes (1)
  • netlify.toml

const IS_LOCAL_ENV = APP_ENV === 'local';

const STRICT_LOCAL_DB_GUARD = process.env.SHOP_STRICT_LOCAL_DB === '1';
0const STRICT_LOCAL_DB_GUARD = process.env.SHOP_STRICT_LOCAL_DB === '1';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Show the malformed declaration in context and scan for similar accidental prefixes.
sed -n '24,32p' frontend/db/index.ts
rg -nP '^\s*\d+const\b' --type ts

Repository: DevLoversTeam/devlovers.net

Length of output: 398


Remove the stray 0 before const.

Line 29 is a hard syntax error (0const), so frontend/db/index.ts will not parse. This prevents the DB module from loading before the Netlify env fallback or the SHOP_STRICT_LOCAL_DB guard can run, which can bring back SSR 500s across DB-backed pages and also bypass the local-test safety check used by frontend/playwright.config.ts:27 and frontend/lib/tests/shop/setup.ts:39.

Suggested fix
-0const STRICT_LOCAL_DB_GUARD = process.env.SHOP_STRICT_LOCAL_DB === '1';
+const STRICT_LOCAL_DB_GUARD = process.env.SHOP_STRICT_LOCAL_DB === '1';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
0const STRICT_LOCAL_DB_GUARD = process.env.SHOP_STRICT_LOCAL_DB === '1';
const STRICT_LOCAL_DB_GUARD = process.env.SHOP_STRICT_LOCAL_DB === '1';
🧰 Tools
🪛 Biome (2.4.9)

[error] 29-29: Expected a statement but instead found '0const STRICT_LOCAL_DB_GUARD = process.env.SHOP_STRICT_LOCAL_DB === '1''.

(parse)


[error] 29-29: numbers cannot be followed by identifiers directly after

(parse)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/db/index.ts` at line 29, Remove the stray leading character before
the declaration: change the malformed token "0const STRICT_LOCAL_DB_GUARD =
process.env.SHOP_STRICT_LOCAL_DB === '1';" to a valid const declaration "const
STRICT_LOCAL_DB_GUARD = process.env.SHOP_STRICT_LOCAL_DB === '1';" so the module
parses and the SHOP_STRICT_LOCAL_DB guard (STRICT_LOCAL_DB_GUARD) can run; after
fixing, run TypeScript/ESLint or a quick build to confirm no other syntax errors
remain.

@ViktorSvertoka ViktorSvertoka merged commit b969fbf into develop Mar 28, 2026
7 checks passed
@ViktorSvertoka ViktorSvertoka deleted the sl/feat/db-optimization branch March 28, 2026 14:55
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.

2 participants