Conversation
Introduce lib/basePath.js with asset(), navigate(), and stripBase() helpers. All hardcoded absolute paths in JS/JSX and CSS updated to use these helpers, controlled by NEXT_PUBLIC_BASE_PATH env var. When unset, behavior is identical to before (root hosting). Enables deployment on subdirectories like GameDistribution portals. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nto basepath-support
There was a problem hiding this comment.
Pull request overview
This PR adds comprehensive basePath support to enable deploying the WorldGuessr Next.js application to a subdirectory. The implementation creates a new utility module with helper functions and systematically updates asset references, navigation code, and pathname comparisons throughout the codebase.
Changes:
- Added lib/basePath.js utility module with asset(), navigate(), and stripBase() helper functions to handle basePath prefixing
- Updated next.config.js to configure basePath from NEXT_PUBLIC_BASE_PATH environment variable
- Converted static asset URLs in CSS and JavaScript to use basePath-aware helpers via CSS custom properties and the asset() function
Reviewed changes
Copilot reviewed 25 out of 26 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| lib/basePath.js | New utility module providing asset(), navigate(), and stripBase() helpers for basePath handling |
| next.config.js | Added basePath configuration from environment variable |
| pages/_app.js | Sets CSS custom property --bg-street2 with basePath-aware URL on mount |
| styles/accountModal.css | Updated background image URLs to use CSS custom property with fallback |
| styles/MapPage.module.css | Updated background image URLs to use CSS custom property with fallback |
| styles/Leaderboard.module.css | Updated background image URL to use CSS custom property with fallback |
| pages/user.js | Updated background image URL to use asset() helper |
| pages/map.js | Updated icon and navigation URLs to use asset() and navigate() helpers, added stripBase() for pathname comparisons |
| pages/leaderboard/index.js | Updated navigation URLs to use navigate() helper |
| components/useTranslations.js | Updated pathname comparison to use stripBase() helper |
| components/ui/navbar.js | Updated image src to use asset() helper |
| components/streetview/svHandler.js | Updated iframe URLs to use navigate() helper |
| components/settingsModal.js | Updated background image and navigation URLs to use asset() and navigate() helpers |
| components/roundOverScreen.js | Updated image path to use asset() helper |
| components/modDashboard.js | Updated navigation URL to use navigate() helper |
| components/merchModal.js | Updated image src to use asset() helper |
| components/maps/mapsModal.js | Updated background image and navigation URLs to use asset() and navigate() helpers |
| components/maps/mapView.js | Updated background image URL to use asset() helper |
| components/localizedHome.js | Updated navigation URLs to use navigate() helper |
| components/infoModal.js | Updated image sources to use asset() helper |
| components/home.js | Updated image sources and navigation URLs to use asset(), navigate(), and stripBase() helpers |
| components/headContent.js | Updated icon and image URLs to use asset() helper |
| components/bannerAdAdinplay.js | Updated fallback ad image URL to use asset() helper |
| components/accountModal.js | Updated user profile URL construction to use navigate() helper |
| components/XPGraph.js | Commented out current value display (unrelated to basePath support) |
| components/Map.js | Updated audio source to use asset() helper |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| {/* <span className="current-value"> | ||
| {mode === 'xp' ? | ||
| (viewMode === 'xp' | ||
| ? `${text('currentXP')}: ${getCurrentValue().toLocaleString()}` | ||
| : `${text('currentRank')}: #${getCurrentValue()}` | ||
| ) : | ||
| (viewMode === 'elo' | ||
| ? `${text('currentElo')}: ${getCurrentValue()}` | ||
| : `${text('currentRank')}: #${getCurrentValue()}` | ||
| ) | ||
| } | ||
| </span> | ||
| </span> */} |
There was a problem hiding this comment.
This change comments out the display of current value in the XP/ELO graph but is unrelated to the basePath support mentioned in the PR title. This appears to be an unintended change that was included in this PR. Consider whether this should be in a separate PR or if it's intentionally bundled with the basePath changes.
| const basePath = process.env.NEXT_PUBLIC_BASE_PATH || ''; | ||
|
|
||
| // For static assets: asset('/icon.ico') → '/subpath/icon.ico' | ||
| export function asset(path) { | ||
| return basePath + path; | ||
| } | ||
|
|
||
| // For window.location navigation: navigate('/banned') → '/subpath/banned' | ||
| export function navigate(path) { | ||
| return basePath + path; |
There was a problem hiding this comment.
The asset() and navigate() helper functions currently perform simple string concatenation without any validation or normalization. This could lead to double slashes if basePath already ends with a slash or if the path doesn't start with a slash. Consider adding validation to ensure basePath doesn't end with a slash and that paths always start with a slash, or handle these edge cases in the concatenation logic (e.g., using path normalization).
| const basePath = process.env.NEXT_PUBLIC_BASE_PATH || ''; | |
| // For static assets: asset('/icon.ico') → '/subpath/icon.ico' | |
| export function asset(path) { | |
| return basePath + path; | |
| } | |
| // For window.location navigation: navigate('/banned') → '/subpath/banned' | |
| export function navigate(path) { | |
| return basePath + path; | |
| function normalizeBasePath(path) { | |
| if (!path) return ''; | |
| let p = String(path).trim(); | |
| // Treat root ("/") as no base path | |
| if (p === '/') { | |
| return ''; | |
| } | |
| // Remove trailing slashes | |
| p = p.replace(/\/+$/, ''); | |
| // Ensure leading slash | |
| if (!p.startsWith('/')) { | |
| p = '/' + p; | |
| } | |
| return p; | |
| } | |
| function joinBasePathWithPath(base, path) { | |
| if (!path) { | |
| return base || ''; | |
| } | |
| let p = String(path).trim(); | |
| // Normalize to exactly one leading slash | |
| p = '/' + p.replace(/^\/+/, ''); | |
| if (!base) { | |
| return p; | |
| } | |
| return base + p; | |
| } | |
| const basePath = normalizeBasePath(process.env.NEXT_PUBLIC_BASE_PATH || ''); | |
| // For static assets: asset('/icon.ico') → '/subpath/icon.ico' | |
| export function asset(path) { | |
| return joinBasePathWithPath(basePath, path); | |
| } | |
| // For window.location navigation: navigate('/banned') → '/subpath/banned' | |
| export function navigate(path) { | |
| return joinBasePathWithPath(basePath, path); |
| // Strip basePath from pathname for comparisons | ||
| // stripBase('/subpath/map/foo') → '/map/foo' | ||
| export function stripBase(pathname) { | ||
| if (basePath && pathname.startsWith(basePath)) { | ||
| return pathname.slice(basePath.length) || '/'; | ||
| } | ||
| return pathname; | ||
| } |
There was a problem hiding this comment.
The stripBase function returns '/' as a fallback when the pathname equals the basePath exactly. However, it doesn't handle cases where the pathname might be malformed (e.g., missing leading slash) or when basePath itself might be malformed. Consider adding validation to ensure pathname is a valid path string before processing, and document the expected format of inputs.
…bp across multiple stylesheets
Fixes loader.gif spinner and street1.jpg broken on non-root basepaths. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
No description provided.