feat: secure and validate environment configuration - #160
Conversation
- Rewrite .env.example with only the variables the code reads; remove NEXT_PUBLIC_CLOUDINARY_API_SECRET, _API_KEY, _URL, DNB_API_URL, NEXT_PUBLIC_SOCKET_URL - Add lib/config/env.js with Zod schema that validates URLs, constrains STELLAR_NETWORK to testnet|mainnet, rejects NEXT_PUBLIC_*SECRET vars, and fails build with aggregated error messages - Source Firebase config from env vars with current values as defaults - Route all process.env reads through the validated config object - Update README configuration table with all variables and required column
|
@IamOluwatoyin is attempting to deploy a commit to the Deen Bridge Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughThe change introduces centralized Zod-validated environment configuration, documents expanded variables, removes exposed Cloudinary credential examples, and updates API, Firebase, Jitsi, Stellar, and Cloudinary code to consume the shared configuration. ChangesEnvironment configuration
Estimated code review effort: 3 (Moderate) | ~25 minutes π₯ Pre-merge checks | β 3 | β 2β Failed checks (2 warnings)
β Passed checks (3 passed)
β¨ Finishing Touches π‘ 1π οΈ Fix failing CI checks π‘
π§ͺ Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and canβt be posted inline due to platform limitations.
β οΈ Outside diff range comments (1)
app/api/books/[bookId]/preview/route.js (1)
9-10: π©Ί Stability & Availability | π Major | β‘ Quick winAwait Next.js 15 request APIs.
paramsandcookies()are still read synchronously here; switch toawait paramsandawait cookies()so this route stays compatible with the App Router APIs in Next.js 15.π€ Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/api/books/`[bookId]/preview/route.js around lines 9 - 10, Update the GET route handler to await the Next.js 15 request APIs: resolve params asynchronously before extracting bookId, and await the cookies() call wherever it is used in the handler. Preserve the existing route behavior and cookie/parameter handling after these asynchronous reads.Source: Path instructions
π§Ή Nitpick comments (1)
lib/config/env.js (1)
45-61: π― Functional Correctness | π΅ Trivial | β‘ Quick winRequired-field error message won't surface as intended.
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAMEis required, but the custom message"Cloudinary cloud name is required"is only attached to.min(1, ...). When the variable is entirely unset (undefined), zod fails on the type check first and reports the generic"Expected string, received undefined"instead of your intended message β weakening the "clearly list missing... variables" goal from the PR.π©Ή Proposed fix
- NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME: z - .string() - .min(1, "Cloudinary cloud name is required"), + NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME: z + .string({ required_error: "Cloudinary cloud name is required" }) + .min(1, "Cloudinary cloud name is required"),π€ Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/config/env.js` around lines 45 - 61, Update the NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME schema in envSchema so the custom βCloudinary cloud name is requiredβ message applies when the variable is undefined as well as when it is empty. Preserve the field as required and keep the existing validation behavior for non-empty values.
π€ Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.env.example:
- Around line 17-18: Update the NEXT_PUBLIC_JITSI_DOMAIN example value to the
bare domain meet.jit.si without the https:// protocol, matching the jitsiDomain
getter default and README documentation.
In `@app/api/ai/chat/route.js`:
- Around line 7-8: Remove the raw console logs for message, chat_id, and user_id
in the chat handler, and apply the same production-safe redaction or removal to
full AI response and error payload logging in the surrounding handler. Do not
emit sensitive prompt content or user identifiers; use the existing structured
logger only with explicitly safe, retention-compliant fields.
- Line 10: Make configuration fallbacks development-only: in
app/api/ai/chat/route.js:10, app/api/ai/stream/route.js:14,
components/organisms/dashboard/ai/Ai-Sidebar.jsx:14,
lib/actions/ai/load-chat-history.js:12 and :36,
app/api/books/[bookId]/preview/route.js:5-6, lib/actions/cached-api.js:9, and
lib/config/axios.config.js:4 require the respective AI/API URL in production
instead of falling back to localhost; in
components/stellar/StellarProvider.jsx:19-21 require NEXT_PUBLIC_STELLAR_NETWORK
in production instead of defaulting to testnet. Preserve the existing
development fallbacks.
In `@components/organisms/dashboard/JaasMeetingClientSection.jsx`:
- Around line 54-55: Update the Jitsi domain configuration flow used by
JaasMeetingClientSection so blank or whitespace-only NEXT_PUBLIC_JITSI_DOMAIN
values are treated as unset before normalizeDomain receives them. Use the
existing default-domain fallback (such as meet.jit.si) or trim and reject blank
values in the configuration module, covering both referenced domain usages.
In `@lib/config/env.js`:
- Around line 110-131: Remove the live Firebase values from the firebase
configuration getter in lib/config/env.js, require every NEXT_PUBLIC_FIREBASE_*
variable explicitly, and raise a clear startup error when any is missing.
Replace the real Firebase values with generic placeholders in .env.example lines
24-30; rotating or restricting the previously committed key is a separate
follow-up.
- Around line 78-131: Update the configuration getters stellarNetwork,
jitsiDomain, jitsiRequireJwt, and firebase so every hardcoded fallback invokes
the existing warn helper with its environment key and fallback value before
returning that value. Preserve the current defaults and boolean behavior, while
replacing the repeated comma-operator pattern with the shared fallback approach
if available.
---
Outside diff comments:
In `@app/api/books/`[bookId]/preview/route.js:
- Around line 9-10: Update the GET route handler to await the Next.js 15 request
APIs: resolve params asynchronously before extracting bookId, and await the
cookies() call wherever it is used in the handler. Preserve the existing route
behavior and cookie/parameter handling after these asynchronous reads.
---
Nitpick comments:
In `@lib/config/env.js`:
- Around line 45-61: Update the NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME schema in
envSchema so the custom βCloudinary cloud name is requiredβ message applies when
the variable is undefined as well as when it is empty. Preserve the field as
required and keep the existing validation behavior for non-empty values.
πͺ 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 Plus
Run ID: 28b356b4-a274-4cf3-88a5-d7be275e5372
π Files selected for processing (14)
.env.exampleREADME.mdapp/api/ai/chat/route.jsapp/api/ai/stream/route.jsapp/api/books/[bookId]/preview/route.jscomponents/organisms/dashboard/JaasMeetingClientSection.jsxcomponents/organisms/dashboard/ai/Ai-Sidebar.jsxcomponents/stellar/StellarProvider.jsxlib/actions/ai/load-chat-history.jslib/actions/cached-api.jslib/config/axios.config.jslib/config/env.jslib/config/firebase.config.jslib/utils/cloudinaryUpload.js
| NEXT_PUBLIC_JITSI_DOMAIN=https://meet.jit.si | ||
| # NODE_ENV=production | ||
| DNB_API_URL=https://dnb-backend-api.onrender.com | ||
| NEXT_PUBLIC_API_URL=https://dnb-backend-api.onrender.com | ||
| NEXT_PUBLIC_STELLAR_NETWORK=testnet | ||
| # Jitsi Meet domain for video spaces |
There was a problem hiding this comment.
ποΈ Data Integrity & Integration | π‘ Minor | β‘ Quick win
Example value includes a protocol prefix that the code doesn't expect.
lib/config/env.js's jitsiDomain getter falls back to the bare domain "meet.jit.si" (no protocol), and the README documents the same bare-domain default. This example uses https://meet.jit.si. If a contributor copies this literally and downstream code builds a URL like https://${jitsiDomain}/... (or passes it to the Jitsi Meet External API, which expects a bare domain), the protocol gets duplicated.
π©Ή Proposed fix
-NEXT_PUBLIC_JITSI_DOMAIN=https://meet.jit.si
+NEXT_PUBLIC_JITSI_DOMAIN=meet.jit.siπ 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.
| NEXT_PUBLIC_JITSI_DOMAIN=https://meet.jit.si | |
| # NODE_ENV=production | |
| DNB_API_URL=https://dnb-backend-api.onrender.com | |
| NEXT_PUBLIC_API_URL=https://dnb-backend-api.onrender.com | |
| NEXT_PUBLIC_STELLAR_NETWORK=testnet | |
| # Jitsi Meet domain for video spaces | |
| NEXT_PUBLIC_JITSI_DOMAIN=meet.jit.si | |
| # Jitsi Meet domain for video spaces |
π€ Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.env.example around lines 17 - 18, Update the NEXT_PUBLIC_JITSI_DOMAIN
example value to the bare domain meet.jit.si without the https:// protocol,
matching the jitsiDomain getter default and README documentation.
| console.log("Sending message to AI:", message); | ||
| console.log("Chat ID:", chat_id, "User ID:", user_id); |
There was a problem hiding this comment.
π Security & Privacy | π Major | β‘ Quick win
Do not log raw AI prompts or user identifiers.
message, chat_id, and user_id may contain sensitive content or user identifiers. Remove these logs, or redact them through a production-safe structured logger with an explicit retention policy; the full response and error payload logs in this handler should be treated the same way.
π€ Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@app/api/ai/chat/route.js` around lines 7 - 8, Remove the raw console logs for
message, chat_id, and user_id in the chat handler, and apply the same
production-safe redaction or removal to full AI response and error payload
logging in the surrounding handler. Do not emit sensitive prompt content or user
identifiers; use the existing structured logger only with explicitly safe,
retention-compliant fields.
| // Use environment variable or fallback to localhost | ||
| const AI_API_URL = | ||
| process.env.NEXT_PUBLIC_AI_API_URL || "http://localhost:8000"; | ||
| const AI_API_URL = config.aiApiUrl; |
There was a problem hiding this comment.
π©Ί Stability & Availability | π Major | β‘ Quick win
Make environment fallbacks development-only. The centralized configuration currently allows missing production values to resolve to localhost or testnet, silently targeting the wrong service or Stellar network instead of failing startup.
app/api/ai/chat/route.js#L10-L10: requireNEXT_PUBLIC_AI_API_URLin production.app/api/ai/stream/route.js#L14-L14: apply the same production requirement to streaming requests.components/organisms/dashboard/ai/Ai-Sidebar.jsx#L14-L14: prevent browser requests from falling back to the userβs localhost.lib/actions/ai/load-chat-history.js#L12-L12: require the AI URL for chat-history loading.lib/actions/ai/load-chat-history.js#L36-L36: require the AI URL for message-history loading.app/api/books/[bookId]/preview/route.js#L5-L6: requireNEXT_PUBLIC_API_URLbefore constructing the proxy URL.lib/actions/cached-api.js#L9-L9: prevent cached API calls from using localhost in production.lib/config/axios.config.js#L4-L4: prevent Axios from initializing against localhost in production.components/stellar/StellarProvider.jsx#L19-L21: requireNEXT_PUBLIC_STELLAR_NETWORKin production instead of defaulting to testnet.
π Affects 8 files
app/api/ai/chat/route.js#L10-L10(this comment)app/api/ai/stream/route.js#L14-L14components/organisms/dashboard/ai/Ai-Sidebar.jsx#L14-L14lib/actions/ai/load-chat-history.js#L12-L12lib/actions/ai/load-chat-history.js#L36-L36app/api/books/[bookId]/preview/route.js#L5-L6lib/actions/cached-api.js#L9-L9lib/config/axios.config.js#L4-L4components/stellar/StellarProvider.jsx#L19-L21
π€ Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@app/api/ai/chat/route.js` at line 10, Make configuration fallbacks
development-only: in app/api/ai/chat/route.js:10, app/api/ai/stream/route.js:14,
components/organisms/dashboard/ai/Ai-Sidebar.jsx:14,
lib/actions/ai/load-chat-history.js:12 and :36,
app/api/books/[bookId]/preview/route.js:5-6, lib/actions/cached-api.js:9, and
lib/config/axios.config.js:4 require the respective AI/API URL in production
instead of falling back to localhost; in
components/stellar/StellarProvider.jsx:19-21 require NEXT_PUBLIC_STELLAR_NETWORK
in production instead of defaulting to testnet. Preserve the existing
development fallbacks.
| const domain = config.jitsiDomain; | ||
| const normalizedDomain = normalizeDomain(domain); |
There was a problem hiding this comment.
π― Functional Correctness | π‘ Minor | β‘ Quick win
Treat a blank Jitsi domain as unset.
The shared schema accepts "", and config.jitsiDomain uses a nullish fallback, so an empty NEXT_PUBLIC_JITSI_DOMAIN reaches normalizeDomain(""). That can produce https:///... meeting URLs. Trim/reject blank values or preserve the previous || "meet.jit.si" fallback in the configuration module.
Also applies to: 82-84
π€ Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@components/organisms/dashboard/JaasMeetingClientSection.jsx` around lines 54
- 55, Update the Jitsi domain configuration flow used by
JaasMeetingClientSection so blank or whitespace-only NEXT_PUBLIC_JITSI_DOMAIN
values are treated as unset before normalizeDomain receives them. Use the
existing default-domain fallback (such as meet.jit.si) or trim and reject blank
values in the configuration module, covering both referenced domain usages.
| get apiUrl() { | ||
| return ( | ||
| env.NEXT_PUBLIC_API_URL ?? | ||
| (warn("NEXT_PUBLIC_API_URL", "http://localhost:5000"), | ||
| "http://localhost:5000") | ||
| ); | ||
| }, | ||
|
|
||
| get aiApiUrl() { | ||
| return ( | ||
| env.NEXT_PUBLIC_AI_API_URL ?? | ||
| (warn("NEXT_PUBLIC_AI_API_URL", "http://localhost:8000"), | ||
| "http://localhost:8000") | ||
| ); | ||
| }, | ||
|
|
||
| get stellarNetwork() { | ||
| return env.NEXT_PUBLIC_STELLAR_NETWORK ?? "testnet"; | ||
| }, | ||
|
|
||
| get cloudinaryCloudName() { | ||
| return env.NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME; | ||
| }, | ||
|
|
||
| get jitsiDomain() { | ||
| return env.NEXT_PUBLIC_JITSI_DOMAIN ?? "meet.jit.si"; | ||
| }, | ||
|
|
||
| get jitsiRequireJwt() { | ||
| return env.NEXT_PUBLIC_JITSI_REQUIRE_JWT === "true"; | ||
| }, | ||
|
|
||
| get firebase() { | ||
| return { | ||
| apiKey: | ||
| env.NEXT_PUBLIC_FIREBASE_API_KEY ?? | ||
| "AIzaSyC8LlmtlWXvbcbyVbdyv4r-tDsGhhukdag", | ||
| authDomain: | ||
| env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN ?? | ||
| "deen-bridge-22195.firebaseapp.com", | ||
| projectId: | ||
| env.NEXT_PUBLIC_FIREBASE_PROJECT_ID ?? "deen-bridge-22195", | ||
| storageBucket: | ||
| env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET ?? | ||
| "deen-bridge-22195.firebasestorage.app", | ||
| messagingSenderId: | ||
| env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID ?? "368531944242", | ||
| appId: | ||
| env.NEXT_PUBLIC_FIREBASE_APP_ID ?? | ||
| "1:368531944242:web:7994b11820741a69d35d2b", | ||
| measurementId: | ||
| env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID ?? "G-ZZ81THLVCC", | ||
| }; | ||
| }, |
There was a problem hiding this comment.
π― Functional Correctness | π Major | β‘ Quick win
Fallback warnings are inconsistent across getters.
Only apiUrl/aiApiUrl call warn() when falling back to a default (lines 80-83, 88-91). stellarNetwork (95), jitsiDomain (103), jitsiRequireJwt (107), and every field in firebase (112-129) silently use hardcoded defaults with no warning. This directly conflicts with the stated goal to "preserve sensible development fallbacks while warning when they are used" β a dev could unknowingly run against the wrong Stellar network or a stale Firebase project with zero console signal.
β»οΈ Suggested refactor: unify via a shared helper
+function withFallback(field, value, fallback) {
+ if (value === undefined) {
+ warn(field, fallback);
+ return fallback;
+ }
+ return value;
+}
+
export const config = Object.freeze({
get apiUrl() {
- return (
- env.NEXT_PUBLIC_API_URL ??
- (warn("NEXT_PUBLIC_API_URL", "http://localhost:5000"),
- "http://localhost:5000")
- );
+ return withFallback("NEXT_PUBLIC_API_URL", env.NEXT_PUBLIC_API_URL, "http://localhost:5000");
},
get aiApiUrl() {
- return (
- env.NEXT_PUBLIC_AI_API_URL ??
- (warn("NEXT_PUBLIC_AI_API_URL", "http://localhost:8000"),
- "http://localhost:8000")
- );
+ return withFallback("NEXT_PUBLIC_AI_API_URL", env.NEXT_PUBLIC_AI_API_URL, "http://localhost:8000");
},
get stellarNetwork() {
- return env.NEXT_PUBLIC_STELLAR_NETWORK ?? "testnet";
+ return withFallback("NEXT_PUBLIC_STELLAR_NETWORK", env.NEXT_PUBLIC_STELLAR_NETWORK, "testnet");
},
get jitsiDomain() {
- return env.NEXT_PUBLIC_JITSI_DOMAIN ?? "meet.jit.si";
+ return withFallback("NEXT_PUBLIC_JITSI_DOMAIN", env.NEXT_PUBLIC_JITSI_DOMAIN, "meet.jit.si");
},
get jitsiRequireJwt() {
- return env.NEXT_PUBLIC_JITSI_REQUIRE_JWT === "true";
+ return withFallback("NEXT_PUBLIC_JITSI_REQUIRE_JWT", env.NEXT_PUBLIC_JITSI_REQUIRE_JWT, "false") === "true";
},
get firebase() {
return {
apiKey:
- env.NEXT_PUBLIC_FIREBASE_API_KEY ??
- "AIzaSyC8LlmtlWXvbcbyVbdyv4r-tDsGhhukdag",
+ withFallback("NEXT_PUBLIC_FIREBASE_API_KEY", env.NEXT_PUBLIC_FIREBASE_API_KEY, "AIzaSyC8LlmtlWXvbcbyVbdyv4r-tDsGhhukdag"),
// ...apply the same pattern to authDomain, projectId, storageBucket,
// messagingSenderId, appId, measurementId
};
},
});This also removes the repeated comma-operator idiom, which is easy to misread.
π§° Tools
πͺ Betterleaks (1.7.0)
[high] 114-114: Uncovered a GCP API key, which could lead to unauthorized access to Google Cloud services and data breaches.
(gcp-api-key)
π€ Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@lib/config/env.js` around lines 78 - 131, Update the configuration getters
stellarNetwork, jitsiDomain, jitsiRequireJwt, and firebase so every hardcoded
fallback invokes the existing warn helper with its environment key and fallback
value before returning that value. Preserve the current defaults and boolean
behavior, while replacing the repeated comma-operator pattern with the shared
fallback approach if available.
| get firebase() { | ||
| return { | ||
| apiKey: | ||
| env.NEXT_PUBLIC_FIREBASE_API_KEY ?? | ||
| "AIzaSyC8LlmtlWXvbcbyVbdyv4r-tDsGhhukdag", | ||
| authDomain: | ||
| env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN ?? | ||
| "deen-bridge-22195.firebaseapp.com", | ||
| projectId: | ||
| env.NEXT_PUBLIC_FIREBASE_PROJECT_ID ?? "deen-bridge-22195", | ||
| storageBucket: | ||
| env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET ?? | ||
| "deen-bridge-22195.firebasestorage.app", | ||
| messagingSenderId: | ||
| env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID ?? "368531944242", | ||
| appId: | ||
| env.NEXT_PUBLIC_FIREBASE_APP_ID ?? | ||
| "1:368531944242:web:7994b11820741a69d35d2b", | ||
| measurementId: | ||
| env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID ?? "G-ZZ81THLVCC", | ||
| }; | ||
| }, |
There was a problem hiding this comment.
π Security & Privacy | π Major | β‘ Quick win
Real Firebase Web API key/project identifiers hardcoded and duplicated across two files. The same live Firebase credentials appear both as source-code fallback defaults and as ".env.example" values, and Betterleaks independently flags both sites as a leaked GCP API key. As per path instructions, **/*.{js,jsx} files must "Flag hardcoded secrets, API keys, or wallet secret keys," so even though Firebase Web API keys aren't traditionally treated as high-secrecy secrets by Google, baking the actual project's live values into shipped code (rather than a placeholder) increases exposure surface and makes rotation/tracking harder.
lib/config/env.js#L110-L131: don't hardcode the real key/IDs as JS fallback defaults β requireNEXT_PUBLIC_FIREBASE_*to be explicitly set (with a clear startup error if missing) instead of silently defaulting to production-identifying values baked into the bundle..env.example#L24-L30: replace the real project values with generic placeholders (e.g.your_firebase_api_key), consistent with howNEXT_PUBLIC_CLOUDINARY_CLOUD_NAMEalready uses a placeholder in this file.
Since these values are already committed to git history, also consider rotating/restricting the Firebase Web API key (HTTP referrer + API restrictions in Google Cloud Console) as a follow-up, independent of this code change.
π§° Tools
πͺ Betterleaks (1.7.0)
[high] 114-114: Uncovered a GCP API key, which could lead to unauthorized access to Google Cloud services and data breaches.
(gcp-api-key)
π Affects 2 files
lib/config/env.js#L110-L131(this comment).env.example#L24-L30
π€ Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@lib/config/env.js` around lines 110 - 131, Remove the live Firebase values
from the firebase configuration getter in lib/config/env.js, require every
NEXT_PUBLIC_FIREBASE_* variable explicitly, and raise a clear startup error when
any is missing. Replace the real Firebase values with generic placeholders in
.env.example lines 24-30; rotating or restricting the previously committed key
is a separate follow-up.
Sources: Path instructions, Linters/SAST tools
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and canβt be posted inline due to platform limitations.
β οΈ Outside diff range comments (2)
README.md (1)
89-99: π Maintainability & Code Quality | π‘ Minor | β‘ Quick winList each Firebase environment variable explicitly.
NEXT_PUBLIC_FIREBASE_*is a wildcard rather than a usable variable name, so contributors cannot tell which keys are required or verify that their configuration is complete. Add one table row per exact Firebase key from.env.example, including its optional/default status.π€ Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@README.md` around lines 89 - 99, Update the environment-variable table in README.md by replacing the wildcard NEXT_PUBLIC_FIREBASE_* row with one row for each exact Firebase variable defined in .env.example. Include every keyβs required or optional/default status and retain the existing descriptions and table structure..env.example (1)
33-35: ποΈ Data Integrity & Integration | π‘ Minor | β‘ Quick winRemove duplicate environment assignments.
NEXT_PUBLIC_API_URLandNEXT_PUBLIC_STELLAR_NETWORKare already defined elsewhere in.env.example. Keep each key in one location; duplicate assignments make the copied configuration ambiguous and may cause later values to override earlier ones.π€ Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.env.example around lines 33 - 35, Remove the duplicate NEXT_PUBLIC_API_URL and NEXT_PUBLIC_STELLAR_NETWORK assignments from this section of .env.example, retaining each key only in its existing canonical location. Keep the DNB_API_URL assignment unchanged.Source: Linters/SAST tools
π€ Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.env.example:
- Line 34: Update the NEXT_PUBLIC_API_URL example value to http://localhost:5000
so it matches the documented development default and setup behavior.
- Line 33: Remove the unused DNB_API_URL entry from the environment example,
keeping NEXT_PUBLIC_API_URL as the documented frontend API variable. Do not
retain the variable unless it is also added to the environment schema and
README.
---
Outside diff comments:
In @.env.example:
- Around line 33-35: Remove the duplicate NEXT_PUBLIC_API_URL and
NEXT_PUBLIC_STELLAR_NETWORK assignments from this section of .env.example,
retaining each key only in its existing canonical location. Keep the DNB_API_URL
assignment unchanged.
In `@README.md`:
- Around line 89-99: Update the environment-variable table in README.md by
replacing the wildcard NEXT_PUBLIC_FIREBASE_* row with one row for each exact
Firebase variable defined in .env.example. Include every keyβs required or
optional/default status and retain the existing descriptions and table
structure.
πͺ 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 Plus
Run ID: f0f65378-c41c-452f-9dc8-5d521c66565b
π Files selected for processing (4)
.env.exampleREADME.mdapp/api/books/[bookId]/preview/route.jslib/config/axios.config.js
π§ Files skipped from review as they are similar to previous changes (2)
- app/api/books/[bookId]/preview/route.js
- lib/config/axios.config.js
| NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=G-ZZ81THLVCC | ||
| # Firebase Web SDK config values (not secrets, but environment-specific) | ||
| # NODE_ENV=production | ||
| DNB_API_URL=https://dnb-backend-api.onrender.com |
There was a problem hiding this comment.
ποΈ Data Integrity & Integration | π‘ Minor | β‘ Quick win
π§© Analysis chain
π Script executed:
#!/bin/bash
rg -n '\bDNB_API_URL\b|\bNEXT_PUBLIC_API_URL\b' .Repository: Deen-Bridge/dnb-frontend
Length of output: 817
Remove the unused DNB_API_URL entry from .env.example. The frontend reads NEXT_PUBLIC_API_URL; keeping DNB_API_URL here drifts from the validated env surface and can confuse contributors. If this variable is still needed, add it to the schema and README instead.
π§° Tools
πͺ dotenv-linter (4.0.0)
[warning] 33-33: [UnorderedKey] The DNB_API_URL key should go before the NEXT_PUBLIC_FIREBASE_API_KEY key
(UnorderedKey)
π€ Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.env.example at line 33, Remove the unused DNB_API_URL entry from the
environment example, keeping NEXT_PUBLIC_API_URL as the documented frontend API
variable. Do not retain the variable unless it is also added to the environment
schema and README.
| # Firebase Web SDK config values (not secrets, but environment-specific) | ||
| # NODE_ENV=production | ||
| DNB_API_URL=https://dnb-backend-api.onrender.com | ||
| NEXT_PUBLIC_API_URL=https://dnb-backend-api.onrender.com |
There was a problem hiding this comment.
ποΈ Data Integrity & Integration | π‘ Minor | β‘ Quick win
Align the example API URL with the documented development default.
.env.example points to the deployed backend, while README.md documents http://localhost:5000 as the default and setup copies this file directly. Use the local default here, or explicitly document why this example intentionally targets production.
π§° Tools
πͺ dotenv-linter (4.0.0)
[warning] 34-34: [DuplicatedKey] The NEXT_PUBLIC_API_URL key is duplicated
(DuplicatedKey)
[warning] 34-34: [UnorderedKey] The NEXT_PUBLIC_API_URL key should go before the NEXT_PUBLIC_FIREBASE_API_KEY key
(UnorderedKey)
π€ Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.env.example at line 34, Update the NEXT_PUBLIC_API_URL example value to
http://localhost:5000 so it matches the documented development default and setup
behavior.
The Zod schema required NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME, causing the build to fail when the variable is not set in CI. The runtime code in cloudinaryUpload.js already validates the cloud name and throws a clear error, so the schema should allow undefined and warn at access time.
There was a problem hiding this comment.
Actionable comments posted: 1
π€ Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@lib/config/env.js`:
- Line 49: Update the NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME configuration handling
to reject blank values rather than accepting explicit empty strings. When the
setting is absent, either disable/gate Cloudinary or return the documented
β(none)β fallback consistently with the warning. Ensure the Cloudinary uploader
cannot receive an unusable empty cloud name.
πͺ 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 Plus
Run ID: f114cec8-3451-4b22-a1fc-9a00a73ff4ac
π Files selected for processing (1)
lib/config/env.js
| NEXT_PUBLIC_API_URL: z.string().url().optional(), | ||
| NEXT_PUBLIC_AI_API_URL: z.string().url().optional(), | ||
| NEXT_PUBLIC_STELLAR_NETWORK: z.enum(["testnet", "mainnet"]).optional(), | ||
| NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME: z.string().optional(), |
There was a problem hiding this comment.
π― Functional Correctness | π Major | β‘ Quick win
Reject unusable Cloudinary configuration instead of deferring failure.
z.string().optional() accepts an explicit empty value, and the getter returns that empty value unchanged. Since the Cloudinary uploader consumes this setting, invalid configuration can pass startup and fail only when an upload is attempted. Reject blank values or explicitly disable/gate Cloudinary when the setting is absent. Also, the warning says "(none)" is used, but no such fallback is returned.
Also applies to: 97-100
π€ Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@lib/config/env.js` at line 49, Update the NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME
configuration handling to reject blank values rather than accepting explicit
empty strings. When the setting is absent, either disable/gate Cloudinary or
return the documented β(none)β fallback consistently with the warning. Ensure
the Cloudinary uploader cannot receive an unusable empty cloud name.
Close #85
Summary by CodeRabbit
.env.exampleto switch the public backend endpoint to local, add AI FastAPI and Firebase variables, simplify Cloudinary config, add Jitsi JWT requirement, and remove the old backend URL entry..env.example.