fix: improve onboarding and unify environment variables#242
fix: improve onboarding and unify environment variables#242Benbenzhouz wants to merge 9 commits intomainfrom
Conversation
- Replace || with ?? in AuthCallbackContent.tsx - Replace || with ?? in UserInputArea.tsx - Replace || with ?? in GoogleOAuthButton.tsx - Replace || with ?? in AddressAutocomplete.tsx - Replace || with ?? in publicApiSlice.ts - Replace || with ?? in axiosBaseQuery.ts - Fix useEffect dependency in AddressAutocomplete.tsx - Remove console.log statements in AuthCallbackContent.tsx
- Create unified getApiBaseUrl() utility function - Remove hardcoded localhost fallbacks from all files - Production environment now requires API URL to be configured - Development environment allows localhost fallback with warning - Improves code quality and prevents production misconfigurations Files updated: - src/utils/api-config.ts (new) - src/services/places.ts - src/lib/axiosBaseQuery.ts - src/features/public/publicApiSlice.ts - src/components/GoogleOAuthButton.tsx - src/app/(public)/blogs/page.tsx - src/app/(public)/blogs/components/BlogList.tsx - src/app/(public)/blogs/[id]/page.tsx
- Remove unnecessary NEXT_PUBLIC_API_BASE_URL fallback - Use only NEXT_PUBLIC_API_URL as it's the actual configured variable - Simplify code and error messages
- Change from NEXT_PUBLIC_API_URL to NEXT_PUBLIC_API_BASE_URL - This matches the actual configured environment variable name
There was a problem hiding this comment.
Pull request overview
This PR unifies environment variable handling by centralizing API URL configuration and improves the onboarding experience by fixing undefined value handling in address and input components. The changes introduce a new getApiBaseUrl() utility function to replace scattered environment variable references throughout the codebase.
Key Changes
- Created centralized
api-config.tsutility with development fallback for API URL configuration - Updated 9 files to use the new
getApiBaseUrl()function instead of direct environment variable access - Enhanced type safety in onboarding components by properly handling
undefinedvalues inAddressAutocompleteandUserInputArea
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/utils/api-config.ts | New utility function providing centralized API URL configuration with development fallback |
| src/services/places.ts | Replaced direct env var access with getApiBaseUrl() |
| src/lib/axiosBaseQuery.ts | Updated to use getApiBaseUrl() and fixed ESLint nullish coalescing preference |
| src/features/public/publicApiSlice.ts | Replaced direct env var access with getApiBaseUrl() |
| src/components/ui/AddressAutocomplete.tsx | Enhanced undefined handling and improved address formatting with backend validation |
| src/components/GoogleOAuthButton.tsx | Replaced hardcoded localhost fallback with getApiBaseUrl() |
| src/app/onboarding/components/UserInputArea.tsx | Added proper undefined handling for user input prop |
| src/app/auth/callback/AuthCallbackContent.tsx | Added validation for parsed user data with fallback values |
| src/app/(public)/blogs/page.tsx | Replaced hardcoded localhost with getApiBaseUrl() |
| src/app/(public)/blogs/components/BlogList.tsx | Replaced hardcoded localhost with getApiBaseUrl() |
| src/app/(public)/blogs/[id]/page.tsx | Replaced hardcoded localhost with getApiBaseUrl() in server component |
| package.json | Added explicit port specification to dev script |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const state = components.administrativeAreaLevel1 | ||
| .toUpperCase() | ||
| .substring(0, 3); | ||
| statePostcode.push(state); |
There was a problem hiding this comment.
The comment states "Ensure state is uppercase and 2-3 characters", but the code uses substring(0, 3) which always limits to a maximum of 3 characters. This doesn't enforce a minimum of 2 characters. If the state abbreviation is less than 2 characters, it should be validated or handled appropriately. Consider adding validation to ensure the state code meets the expected format (e.g., 2-3 uppercase letters).
| const state = components.administrativeAreaLevel1 | |
| .toUpperCase() | |
| .substring(0, 3); | |
| statePostcode.push(state); | |
| const rawState = components.administrativeAreaLevel1.toUpperCase(); | |
| if (rawState.length >= 2) { | |
| const state = rawState.substring(0, 3); | |
| statePostcode.push(state); | |
| } |
| const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL ?? ''; | ||
| import { getApiBaseUrl } from '@/utils/api-config'; | ||
|
|
||
| const API_BASE = getApiBaseUrl(); |
There was a problem hiding this comment.
Calling getApiBaseUrl() at module initialization (top-level) can cause issues in Next.js. If this module is imported by a server component during build time, it will execute before environment variables are properly set up, and the NODE_ENV check in getApiBaseUrl() may not work as expected. Consider making API_BASE a function that calls getApiBaseUrl() lazily when needed, or ensure this module is only imported in client components.
| reducerPath: 'publicApi', | ||
| baseQuery: fetchBaseQuery({ | ||
| baseUrl: process.env.NEXT_PUBLIC_API_BASE_URL, | ||
| baseUrl: getApiBaseUrl(), |
There was a problem hiding this comment.
Calling getApiBaseUrl() at module initialization can cause issues if this module is imported during server-side rendering or build time. The baseUrl for fetchBaseQuery is evaluated when the module loads, not when the query runs. This means the NODE_ENV check in getApiBaseUrl() may execute in an unexpected context. Consider using a dynamic baseQuery that calls getApiBaseUrl() at query time, or ensure this slice is only used in client-side contexts.
src/utils/api-config.ts
Outdated
| if (process.env.NODE_ENV === 'development') { | ||
| // eslint-disable-next-line no-console | ||
| console.warn( | ||
| '⚠️ API base URL not set. Using localhost fallback for development.', | ||
| ); | ||
| return 'http://localhost:4000/api'; | ||
| } |
There was a problem hiding this comment.
The use of process.env.NODE_ENV in this function can cause issues when used in server components during build time. In Next.js, server components are pre-rendered at build time, where NODE_ENV is always 'production'. This means the localhost fallback won't be available during development builds for server-side rendered pages. Consider using NEXT_PUBLIC_NODE_ENV if this needs to work in both client and server contexts, or document that this function should only be used in client components and API routes.
| const { id } = await params; | ||
| const baseUrl = | ||
| process.env.NEXT_PUBLIC_API_BASE_URL ?? 'http://localhost:4000/api'; | ||
| const baseUrl = getApiBaseUrl(); |
There was a problem hiding this comment.
This server component is calling getApiBaseUrl() which relies on process.env.NODE_ENV at runtime. In Next.js server components, this will always be 'production' during the build process, even in development mode. This means the localhost fallback in getApiBaseUrl() won't work, and the function will throw an error if NEXT_PUBLIC_API_BASE_URL is not set during development builds. For server components, you should directly access process.env.NEXT_PUBLIC_API_BASE_URL or use a different approach that doesn't rely on NODE_ENV.
| if (value !== undefined && value !== inputValue) { | ||
| setInputValue(value ?? ''); | ||
| } | ||
| }, [value, inputValue]); |
There was a problem hiding this comment.
This useEffect has a dependency on 'inputValue' which is also being updated inside the effect (via setInputValue). This creates an infinite loop: when 'value' changes, inputValue is set, which triggers this effect again, which sets inputValue again, and so on. The dependency array should only include 'value', not 'inputValue', since you only want to sync when the external prop changes.
| }, [value, inputValue]); | |
| }, [value]); |
| email: parsedUser.email ?? '', | ||
| firstName: parsedUser.firstName ?? '', | ||
| lastName: parsedUser.lastName ?? '', | ||
| role: parsedUser.role ?? 'user', | ||
| status: parsedUser.status ?? 'active', |
There was a problem hiding this comment.
The validation check on line 53 ensures that _id and email exist before using them. However, lines 65-69 still use the nullish coalescing operator (??) for these fields even though they're guaranteed to be defined at this point. This is redundant and could mask issues. Since the validation already ensures these fields exist, you can use them directly without the fallback operators for _id and email.
- Keep same behavior as before: NEXT_PUBLIC_API_BASE_URL ?? localhost fallback - Remove production environment check to match original usage - Environment variable name unchanged: NEXT_PUBLIC_API_BASE_URL - Function only provides centralized management, no behavior change
|
Closing to restore original environment variable names |
Changes
Onboarding Improvements
Environment Variables Unification
Other Fixes
Environment Variables