Skip to content

Improved#43

Open
amoschanda wants to merge 7 commits intoadrianhajdin:mainfrom
amoschanda:main
Open

Improved#43
amoschanda wants to merge 7 commits intoadrianhajdin:mainfrom
amoschanda:main

Conversation

@amoschanda
Copy link

@amoschanda amoschanda commented Jan 25, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Interactive map feature allowing users to tap and select ride destinations
    • Web application deployment via automated GitHub Actions and Vercel integration
    • Web platform support with polyfills for native modules
  • Style

    • Rebranded app identity to YellowCab throughout the interface
    • Updated primary color scheme from blue to gold/yellow
  • Documentation

    • Added comprehensive deployment guides for web and native builds
    • Added build automation scripts for Android APK generation

✏️ Tip: You can customize this high-level summary in your review settings.

cto-new bot added 7 commits January 3, 2026 13:23
…tination-html

feat(app): adopt yellow/black branding, map destination selection, and HTML-structured screens
Introduce a GitHub repository link in the main landing screen header to provide quick access to the project repo. This change doesn't alter navigation or app behavior.

- Displays a "GitHub Repository" link under the YellowCab header
- Uses React Native Linking to open https://github.com/amoschanda/uber
- Includes accessibility labeling for screen readers
feat(welcome): display GitHub repository link on onboarding screen
…tory

- Create apk-repo with builds/docs and CI/CD workflow
- Add app.json and eas.json configurations for Android
- Add build-apk.sh to automate EAS builds and artifact handling
- Add README, build-metadata.json, and checksum scaffolding
- Prepare for artifact distribution and future releases
…al-android-apk-from-the-uber-taxi-app

feat(apk): initialize Expo EAS Android APK build workflow and repository
@coderabbitai
Copy link

coderabbitai bot commented Jan 25, 2026

📝 Walkthrough

Walkthrough

This PR rebrands the Expo Uber app to YellowCab with a yellow/gold color scheme, adds web deployment infrastructure via GitHub Actions and Vercel, implements map-based destination selection with reverse geocoding, adds comprehensive deployment documentation, and includes build automation scripts for Android APK generation.

Changes

Cohort / File(s) Summary
Deployment & CI/CD Configuration
.github/workflows/deploy-web.yml, vercel.json, eas.json, build-apk.sh
GitHub Actions workflow for automated Vercel deployment on main branch pushes; Vercel config specifying build command (npm run build:web), output directory, and routing; EAS configuration for development, preview, and production builds; Bash script automating Android APK builds with checksums and metadata.
Web Platform Support
app/_layout.tsx, metro.config.js, web-polyfills/*, package.json
Platform detection to conditionally load web polyfills; Metro config mapping react-native to react-native-web and providing custom maps polyfill; central polyfills module mocking expo-location, stripe-payment-sheet, and expo-auth; React Native Maps web polyfill providing MapView and Marker components; added build:web npm script.
Deployment & Configuration Documentation
DEPLOYMENT.md, LIVE_DEMO.md, WEB_DEPLOYMENT.md, WEB_DEPLOYMENT_GUIDE.md
Four documentation files detailing deployment options (EAS, Vercel/Netlify, traditional servers), live demo setup, web deployment architecture, environment configuration, cost estimates, and quick-start guides.
Brand Rebranding: Color Palette & Configuration
tailwind.config.js, app.json, components/CustomButton.tsx, components/DriverCard.tsx, app/(root)/(tabs)/_layout.tsx, components/RideLayout.tsx, app/(root)/book-ride.tsx
Primary color updated from blue (#0286FF range) to gold/yellow (#FFD700 range) throughout Tailwind config and applied to buttons, cards, tabs, and ride details; app.json updated with YellowCab branding, iOS/Android package identifiers, permissions, and EAS configuration.
Branding: UI Headers & Text
app/(auth)/sign-in.tsx, app/(auth)/sign-up.tsx, app/(auth)/welcome.tsx, app/(root)/(tabs)/home.tsx, app/(root)/(tabs)/chat.tsx, app/(root)/(tabs)/profile.tsx, app/(root)/(tabs)/rides.tsx, app/(root)/find-ride.tsx
Added YellowCab header branding blocks to sign-in, sign-up, welcome, home, chat, profile, and rides screens; updated screen titles and welcome messages; added GitHub repository link and map interaction hint text.
Map Interaction & Geocoding Feature
components/Map.tsx, lib/geocoding.ts, store/index.ts, types/type.d.ts
Added map tap handler to set destination via reverse geocoding; new reverseGeocode() utility calling Google Maps Geocoding API; new clearDestination() store method and interface update.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A golden carrot calls the app anew,
YellowCab drives where blue once flew,
Maps now respond to every tap,
Web and mobile seal the gap!
From Uber's shade to yellow's gleam, 🚕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Improved' is vague and generic, failing to convey any meaningful information about the substantial changes in this pull request. Replace 'Improved' with a specific, descriptive title that captures the main focus, such as 'Rebrand Uber to YellowCab with web deployment support' or 'Add web deployment infrastructure and rebrand to YellowCab'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 90.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing touches
  • 📝 Generate docstrings

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

@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: 16

🤖 Fix all issues with AI agents
In @.github/workflows/deploy-web.yml:
- Around line 11-18: Update the GitHub Actions steps titled "Checkout" and
"Setup Node.js" to use the v4 releases: change uses: actions/checkout@v3 to
actions/checkout@v4 and uses: actions/setup-node@v3 to actions/setup-node@v4;
also update the node-version value from "18" to "20" (or add a matrix if you
need multiple versions) to take advantage of Node.js 20 support and v4
improvements in actions/setup-node.
- Around line 28-34: Update the Deploy to Vercel step that currently uses
"amondnet/vercel-action@v25" (the step named "Deploy to Vercel") to reference
the latest stable release tag (e.g., v41.1.4) and optionally replace the mutable
tag with a specific commit SHA for pinning; modify the "uses:
amondnet/vercel-action@v25" value to the new tag or SHA and keep existing inputs
(vercel-token, vercel-org-id, vercel-project-id, vercel-args) unchanged.

In `@app.json`:
- Around line 26-30: Remove the unused background location permission by
deleting "ACCESS_BACKGROUND_LOCATION" from the permissions array in app.json;
the app only uses foreground APIs (Location.requestForegroundPermissionsAsync
and Location.getCurrentPositionAsync in home.tsx) so keep only foreground
location permissions ("ACCESS_FINE_LOCATION" and "ACCESS_COARSE_LOCATION") to
avoid stricter app store review and privacy disclosures.

In `@app/`(auth)/welcome.tsx:
- Line 3: Wrap calls to Linking.openURL in an async handler that first calls
Linking.canOpenURL(url) and only calls Linking.openURL(url) if canOpenURL
returns true; surround both calls with try/catch to handle runtime errors and
log or show a user-friendly error (e.g., via Alert or processLogger). Update the
touchable element (TouchableOpacity or the Text that acts as a link) to include
accessibilityRole="link" and an appropriate accessibilityLabel to improve
screen-reader semantics. Locate usages of Linking.openURL and the
TouchableOpacity in welcome.tsx and update those handlers and props accordingly.

In `@build-apk.sh`:
- Around line 154-165: The buildStatus block is checking hard-coded "debug" and
"release" APK filenames which don't match the actual build profiles
(development|preview|production); update the logic that sets buildStatus to
inspect the correct profile folders (using the buildProfile variable or a list
of supported profiles) under BUILD_DIR and detect any .apk in each profile
folder, then populate keys matching the actual profile names (e.g., development,
preview, production) with "completed" or "not-built"; modify the buildStatus
structure and the file-existence checks that reference BUILD_DIR so they
dynamically derive paths from buildProfile or iterate the supported profiles
rather than using the debug/release filenames.
- Around line 115-136: The update_checksums function currently only scans
${BUILD_DIR} for *.apk so it misses APKs placed in per-profile subdirectories
(${BUILD_DIR}/${profile}); modify update_checksums to recursively find APKs
under ${BUILD_DIR} (or iterate over profile subdirs) and append their checksums
to checksums.md5 and checksums.sha256; update the logic in update_checksums
(referencing update_checksums, BUILD_DIR and profile) to use find or a loop over
"${BUILD_DIR}"/* to locate all *.apk files, handle paths with spaces, and write
results into the existing checksums files before returning to REPO_DIR.

In `@components/Map.tsx`:
- Around line 2-4: The handleMapPress handler can be invoked by rapid taps or
marker presses and its async reverse-geocode results can arrive out of order;
add a useRef-based requestId counter (e.g., mapPressRequestIdRef) incremented on
each handleMapPress call and captured inside the async task to ignore stale
responses, and early-return when the event is a marker press (inspect
MapPressEvent.nativeEvent?.action or a pressed flag) to avoid handling
marker-initiated presses; update the reverse-geocode success/error paths to
check the current requestId before setting state or showing Alert so only the
latest request can modify UI.

In `@DEPLOYMENT.md`:
- Around line 59-62: Update the command in DEPLOYMENT.md to match package.json
by replacing the incorrect script name `npm run web:export` with the actual
script `npm run build:web`; edit the bash code block so it reads `npm install`
followed by `npm run build:web` (ensure the code fence and spacing remain
valid).
- Around line 25-27: Update the outdated Expo command `expo export:web` to the
modern syntax used by our build workflow—replace it with `npx expo export -p
web` (or `expo export -p web`) so docs match the `npm run build:web` behavior
which runs `expo export -p web --no-minify`; ensure the documentation command
and any examples reflect `-p web` platform syntax.
- Around line 66-70: Replace the deprecated command string "expo export:web"
with the modern invocation "npx expo export -p web" and update the subsequent
references to the output folder: change "dist/web" to "dist" in steps that
describe the created folder and the upload instruction so the doc reflects the
new output location.

In `@eas.json`:
- Around line 19-22: Update the "production" profile's Android configuration by
changing the "buildType" value from "apk" to "app-bundle" so production releases
produce an Android App Bundle for Play Store submission; locate the "production"
-> "android" -> "buildType" entry in eas.json and replace "apk" with
"app-bundle".

In `@lib/geocoding.ts`:
- Around line 8-17: Before calling response.json() in the geocoding fetch logic,
check the HTTP status using response.ok and throw a descriptive error including
response.status and response.statusText when the request failed; update the
fetch block that constructs the URL with googlePlacesApiKey (the response
variable and the error throw "No address found for the selected location") to
first do if (!response.ok) throw new Error(`Geocoding API error
${response.status}: ${response.statusText}`) so you only call response.json()
for successful responses and preserve the existing "No address found..." error
path when data.status !== "OK" or results are empty.

In `@metro.config.js`:
- Around line 11-17: The current unconditional aliasing in
config.resolver.extraNodeModules (mapping "react-native" => "react-native-web"
and "react-native-maps" => "./web-polyfills/react-native-maps-web.js") breaks
native builds; update the logic to only set these aliases when
EXPO_USE_WEB_PLATFORM is enabled (mirror the existing conditional used for
sourceExts). Specifically, wrap or gate the assignment to
config.resolver.extraNodeModules behind a check of
process.env.EXPO_USE_WEB_PLATFORM (or the same variable/name used by
sourceExts), leaving resolver behavior untouched for native builds when the flag
is not set.

In `@vercel.json`:
- Around line 1-15: Update the vercel.json settings to follow Expo web
deployment guidance: change the buildCommand value from "npm run build:web" to
"expo export -p web", set devCommand to "expo" instead of "expo start --web",
set framework to null (not "other"), replace the legacy "routes" array with a
modern "rewrites" entry using { "source": "/:path*", "destination": "/" }, and
add cleanUrls: true; adjust the outputDirectory key only if needed but leave
"dist" as-is if correct.

In `@WEB_DEPLOYMENT_GUIDE.md`:
- Around line 84-89: Replace the typo "Turing device sensors, camera, etc." in
the native modules list with a clearer phrase such as "Other/Additional device
sensors, camera, etc."; update the list item that currently reads `Turing device
sensors, camera, etc.` so it reads `Other/Additional device sensors, camera,
etc.` (or similar wording) to fix the wording in the native modules section.

In `@web-polyfills/index.js`:
- Around line 4-27: Replace usage of the legacy global alias and the truthy env
check: change the conditional to check typeof window !== "undefined" &&
process.env.EXPO_USE_WEB_PLATFORM === "true", and assign mocks to globalThis
(e.g. globalThis.expo_location, globalThis.stripe_payment_sheet,
globalThis.expo_auth) instead of global.*; keep the same mock shapes for
getCurrentPositionAsync, requestForegroundPermissionsAsync, initPaymentSheet,
presentPaymentSheet, authenticateAsync and isEnrolledAsync.
🧹 Nitpick comments (2)
lib/geocoding.ts (1)

1-1: Add API key validation.

If EXPO_PUBLIC_PLACES_API_KEY is not set, the API call will fail with a cryptic error. Consider adding a guard or at least logging a warning.

♻️ Suggested improvement
 const googlePlacesApiKey = process.env.EXPO_PUBLIC_PLACES_API_KEY;
+
+if (!googlePlacesApiKey) {
+  console.warn("EXPO_PUBLIC_PLACES_API_KEY is not set. Reverse geocoding will not work.");
+}
app.json (1)

31-34: Avoid hardcoding the Google Maps API key in config.

Consider moving the key to an env-backed app.config.ts to prevent accidental commits and simplify CI injection.

Comment on lines +11 to +18
- name: Checkout
uses: actions/checkout@v3

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "18"
cache: "npm"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Update GitHub Actions to latest versions.

The actions/checkout@v3 and actions/setup-node@v3 are outdated. Update to v4 for better performance, security patches, and Node.js 20 support.

📝 Suggested fix
       - name: Checkout
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4

       - name: Setup Node.js
-        uses: actions/setup-node@v3
+        uses: actions/setup-node@v4
         with:
           node-version: "18"
           cache: "npm"
🧰 Tools
🪛 actionlint (1.7.10)

12-12: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


15-15: the runner of "actions/setup-node@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🤖 Prompt for AI Agents
In @.github/workflows/deploy-web.yml around lines 11 - 18, Update the GitHub
Actions steps titled "Checkout" and "Setup Node.js" to use the v4 releases:
change uses: actions/checkout@v3 to actions/checkout@v4 and uses:
actions/setup-node@v3 to actions/setup-node@v4; also update the node-version
value from "18" to "20" (or add a matrix if you need multiple versions) to take
advantage of Node.js 20 support and v4 improvements in actions/setup-node.

Comment on lines +28 to +34
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: "--prod"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

latest version amondnet/vercel-action GitHub Action 2025

💡 Result:

The latest amondnet/vercel-action release in 2025 (and the newest shown on the repo releases page) is v41.1.4 (released July 15, 2025). [1][2]

Use it like:

- uses: amondnet/vercel-action@v41.1.4

Update the Vercel action to the latest stable version and consider pinning to SHA for security.

The action is using v25, but the latest stable version is v41.1.4 (released July 15, 2025). Update to the latest version to benefit from security patches and improvements. Additionally, consider pinning to a specific commit SHA instead of a mutable tag for better reproducibility and security.

- uses: amondnet/vercel-action@v41.1.4
🤖 Prompt for AI Agents
In @.github/workflows/deploy-web.yml around lines 28 - 34, Update the Deploy to
Vercel step that currently uses "amondnet/vercel-action@v25" (the step named
"Deploy to Vercel") to reference the latest stable release tag (e.g., v41.1.4)
and optionally replace the mutable tag with a specific commit SHA for pinning;
modify the "uses: amondnet/vercel-action@v25" value to the new tag or SHA and
keep existing inputs (vercel-token, vercel-org-id, vercel-project-id,
vercel-args) unchanged.

Comment on lines +26 to +30
"permissions": [
"ACCESS_FINE_LOCATION",
"ACCESS_COARSE_LOCATION",
"ACCESS_BACKGROUND_LOCATION"
],
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether background location is actually used in the codebase.
rg -n -C3 'requestBackgroundPermissionsAsync|startLocationUpdatesAsync|stopLocationUpdatesAsync|TaskManager|allowsBackgroundLocationUpdates' --type=ts --type=tsx

Repository: adrianhajdin/uber

Length of output: 88


🏁 Script executed:

#!/bin/bash
# Search for background location usage with correct file type
rg -n -C3 'requestBackgroundPermissionsAsync|startLocationUpdatesAsync|stopLocationUpdatesAsync|TaskManager|allowsBackgroundLocationUpdates' --type=ts

Repository: adrianhajdin/uber

Length of output: 43


🏁 Script executed:

#!/bin/bash
# Find and examine app.json
find . -name "app.json" -type f | head -5

# Search more broadly for location-related code
rg -n 'location|Location|LOCATION' --type=js | head -20

Repository: adrianhajdin/uber

Length of output: 172


🏁 Script executed:

#!/bin/bash
# Check the app.json permissions section
cat app.json | grep -A 10 '"permissions"'

# Search for expo-location usage
rg -n 'expo-location|useLocation|getCurrentPositionAsync|watchPositionAsync' --type=js

# Search for location-related imports
rg -n "from.*location|import.*location" --type=js

Repository: adrianhajdin/uber

Length of output: 427


🏁 Script executed:

#!/bin/bash
# Search for actual location usage in the codebase
rg -n 'getCurrentPositionAsync|getLastKnownPositionAsync|watchPositionAsync|location\.' --type=js -A 2

# Also check for any background tasks or location tracking
rg -n 'BackgroundLocation|background.*location|location.*background' -i --type=js

# List main source files to understand structure
find . -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" | grep -E '(src/|app/|screens/|components/)' | head -20

Repository: adrianhajdin/uber

Length of output: 776


🏁 Script executed:

#!/bin/bash
# Check key screens for location usage
for file in "./app/(root)/(tabs)/home.tsx" "./app/(root)/find-ride.tsx" "./app/(root)/book-ride.tsx"; do
  if [ -f "$file" ]; then
    echo "=== $file ==="
    rg -n 'location|Location|coordinates|latitude|longitude|position' "$file" | head -10
  fi
done

Repository: adrianhajdin/uber

Length of output: 1216


Remove ACCESS_BACKGROUND_LOCATION permission from app.json.

The codebase only uses foreground location APIs (Location.requestForegroundPermissionsAsync() and Location.getCurrentPositionAsync() in home.tsx). The ACCESS_BACKGROUND_LOCATION permission is not used anywhere and unnecessarily triggers stricter app store review requirements and enhanced privacy disclosures.

🤖 Prompt for AI Agents
In `@app.json` around lines 26 - 30, Remove the unused background location
permission by deleting "ACCESS_BACKGROUND_LOCATION" from the permissions array
in app.json; the app only uses foreground APIs
(Location.requestForegroundPermissionsAsync and Location.getCurrentPositionAsync
in home.tsx) so keep only foreground location permissions
("ACCESS_FINE_LOCATION" and "ACCESS_COARSE_LOCATION") to avoid stricter app
store review and privacy disclosures.

import { router } from "expo-router";
import { useRef, useState } from "react";
import { Image, Text, TouchableOpacity, View } from "react-native";
import { Image, Linking, Text, TouchableOpacity, View } from "react-native";
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cd /repo && git ls-files | grep -E "(welcome|auth)" | head -20

Repository: adrianhajdin/uber

Length of output: 116


🏁 Script executed:

cat -n app/\(auth\)/welcome.tsx | head -50

Repository: adrianhajdin/uber

Length of output: 2143


🏁 Script executed:

cat -n app/\(auth\)/welcome.tsx | sed -n '15,35p'

Repository: adrianhajdin/uber

Length of output: 925


Add error handling for external link and improve link accessibility.

Linking.openURL can fail due to network issues or unsupported schemes. Add a robustness check with canOpenURL() and handle errors gracefully. Also add accessibilityRole="link" for better semantic accessibility.

🔧 Suggested fix
-import { Image, Linking, Text, TouchableOpacity, View } from "react-native";
+import { Alert, Image, Linking, Text, TouchableOpacity, View } from "react-native";
-        <TouchableOpacity
-          onPress={() => Linking.openURL("https://github.com/amoschanda/uber")}
+        <TouchableOpacity
+          onPress={async () => {
+            const url = "https://github.com/amoschanda/uber";
+            try {
+              const supported = await Linking.canOpenURL(url);
+              if (!supported) {
+                Alert.alert("Error", "Unable to open the repository link.");
+                return;
+              }
+              await Linking.openURL(url);
+            } catch {
+              Alert.alert("Error", "Unable to open the repository link.");
+            }
+          }}
           className="mt-2"
           accessible={true}
           accessibilityLabel="GitHub Repository"
+          accessibilityRole="link"
         >
🤖 Prompt for AI Agents
In `@app/`(auth)/welcome.tsx at line 3, Wrap calls to Linking.openURL in an async
handler that first calls Linking.canOpenURL(url) and only calls
Linking.openURL(url) if canOpenURL returns true; surround both calls with
try/catch to handle runtime errors and log or show a user-friendly error (e.g.,
via Alert or processLogger). Update the touchable element (TouchableOpacity or
the Text that acts as a link) to include accessibilityRole="link" and an
appropriate accessibilityLabel to improve screen-reader semantics. Locate usages
of Linking.openURL and the TouchableOpacity in welcome.tsx and update those
handlers and props accordingly.

Comment on lines +115 to +136
# Function to update checksums
update_checksums() {
echo ""
echo -e "${YELLOW}Generating checksums...${NC}"

cd "${BUILD_DIR}"

# Create checksums file
> checksums.md5
> checksums.sha256

for apk in *.apk; do
if [ -f "$apk" ]; then
echo "Generating checksum for $apk..."
md5sum "$apk" >> checksums.md5
sha256sum "$apk" >> checksums.sha256
fi
done

cd "${REPO_DIR}"
echo -e "${GREEN}✓ Checksums generated${NC}"
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Checksums miss APKs stored in per‑profile directories.
update_checksums only scans ${BUILD_DIR} for *.apk, but builds are output to ${BUILD_DIR}/${profile}. This will produce empty checksum files.

🔧 Suggested fix
-    cd "${BUILD_DIR}"
-    
-    # Create checksums file
-    > checksums.md5
-    > checksums.sha256
-    
-    for apk in *.apk; do
-        if [ -f "$apk" ]; then
-            echo "Generating checksum for $apk..."
-            md5sum "$apk" >> checksums.md5
-            sha256sum "$apk" >> checksums.sha256
-        fi
-    done
+    cd "${BUILD_DIR}"
+
+    : > checksums.md5
+    : > checksums.sha256
+
+    find . -name "*.apk" -print0 | while IFS= read -r -d '' apk; do
+        echo "Generating checksum for $apk..."
+        md5sum "$apk" >> checksums.md5
+        sha256sum "$apk" >> checksums.sha256
+    done
🧰 Tools
🪛 Shellcheck (0.11.0)

[warning] 123-123: This redirection doesn't have a command. Move to its command (or use 'true' as no-op).

(SC2188)


[warning] 124-124: This redirection doesn't have a command. Move to its command (or use 'true' as no-op).

(SC2188)

🤖 Prompt for AI Agents
In `@build-apk.sh` around lines 115 - 136, The update_checksums function currently
only scans ${BUILD_DIR} for *.apk so it misses APKs placed in per-profile
subdirectories (${BUILD_DIR}/${profile}); modify update_checksums to recursively
find APKs under ${BUILD_DIR} (or iterate over profile subdirs) and append their
checksums to checksums.md5 and checksums.sha256; update the logic in
update_checksums (referencing update_checksums, BUILD_DIR and profile) to use
find or a loop over "${BUILD_DIR}"/* to locate all *.apk files, handle paths
with spaces, and write results into the existing checksums files before
returning to REPO_DIR.

Comment on lines +8 to +17
const response = await fetch(
`https://maps.googleapis.com/maps/api/geocode/json?latlng=${latitude},${longitude}&key=${googlePlacesApiKey}`
);

const data = await response.json();

if (data.status === "OK" && data.results.length > 0) {
return data.results[0].formatted_address;
} else {
throw new Error("No address found for the selected location");
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add HTTP response status check before parsing JSON.

If the API returns an HTTP error (4xx/5xx), response.json() may fail or return unexpected data. Check response.ok first to provide clearer error messages.

🐛 Suggested fix
     const response = await fetch(
       `https://maps.googleapis.com/maps/api/geocode/json?latlng=${latitude},${longitude}&key=${googlePlacesApiKey}`
     );

+    if (!response.ok) {
+      throw new Error(`Geocoding API request failed with status ${response.status}`);
+    }
+
     const data = await response.json();

     if (data.status === "OK" && data.results.length > 0) {
🤖 Prompt for AI Agents
In `@lib/geocoding.ts` around lines 8 - 17, Before calling response.json() in the
geocoding fetch logic, check the HTTP status using response.ok and throw a
descriptive error including response.status and response.statusText when the
request failed; update the fetch block that constructs the URL with
googlePlacesApiKey (the response variable and the error throw "No address found
for the selected location") to first do if (!response.ok) throw new
Error(`Geocoding API error ${response.status}: ${response.statusText}`) so you
only call response.json() for successful responses and preserve the existing "No
address found..." error path when data.status !== "OK" or results are empty.

Comment on lines +11 to +17
// Resolve react-native imports to react-native-web
config.resolver.extraNodeModules = {
"react-native": require.resolve("react-native-web"),
"react-native-maps": require.resolve(
"./web-polyfills/react-native-maps-web.js",
),
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Unconditional aliasing breaks native builds.

The extraNodeModules configuration unconditionally aliases react-native to react-native-web, which will break iOS and Android builds. This should be conditional on EXPO_USE_WEB_PLATFORM, similar to the sourceExts configuration.

🐛 Proposed fix
-// Resolve react-native imports to react-native-web
-config.resolver.extraNodeModules = {
-  "react-native": require.resolve("react-native-web"),
-  "react-native-maps": require.resolve(
-    "./web-polyfills/react-native-maps-web.js",
-  ),
-};
+// Web-specific module resolution
+if (process.env.EXPO_USE_WEB_PLATFORM) {
+  config.resolver.extraNodeModules = {
+    ...config.resolver.extraNodeModules,
+    "react-native": require.resolve("react-native-web"),
+    "react-native-maps": require.resolve(
+      "./web-polyfills/react-native-maps-web.js",
+    ),
+  };
+}
🤖 Prompt for AI Agents
In `@metro.config.js` around lines 11 - 17, The current unconditional aliasing in
config.resolver.extraNodeModules (mapping "react-native" => "react-native-web"
and "react-native-maps" => "./web-polyfills/react-native-maps-web.js") breaks
native builds; update the logic to only set these aliases when
EXPO_USE_WEB_PLATFORM is enabled (mirror the existing conditional used for
sourceExts). Specifically, wrap or gate the assignment to
config.resolver.extraNodeModules behind a check of
process.env.EXPO_USE_WEB_PLATFORM (or the same variable/name used by
sourceExts), leaving resolver behavior untouched for native builds when the flag
is not set.

Comment on lines +1 to +15
{
"buildCommand": "npm run build:web",
"outputDirectory": "dist",
"devCommand": "expo start --web",
"framework": "other",
"builds": [
{
"src": "package.json",
"use": "vercel/static-build",
"config": {
"outputDirectory": "dist"
}
}
],
"routes": [{ "handle": "filesystem" }, { "src": "/.*", "dest": "/" }]
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Vercel static-build configuration Expo web expo export SPA routing

💡 Result:

For an Expo Web SPA (single index.html) deployed as a static site on Vercel, use Expo’s web export to dist/ and add a catch‑all rewrite so refresh/direct hits on /any/route return your SPA entry file.

1) Ensure you’re exporting an SPA

In app.json / app.config.js, set Expo Router’s web output to SPA mode (single is the SPA mode; static generates per-route HTML). [1]

2) Build output (local + Vercel)

Export for web (outputs to dist/): [2][1]

npx expo export -p web

3) vercel.json for Expo static export + SPA routing

Create vercel.json in the repo root (Expo’s docs example): [1]

{
  "buildCommand": "expo export -p web",
  "outputDirectory": "dist",
  "devCommand": "expo",
  "cleanUrls": true,
  "framework": null,
  "rewrites": [
    { "source": "/:path*", "destination": "/" }
  ]
}

That rewrite is the key fix for Vercel 404s on refresh/deep links in an SPA. [1][3]


🌐 Web query:

Vercel routes fallback SPA single page application configuration

💡 Result:

To make a SPA (client-side router) fallback on Vercel, add a vercel.json that rewrites “unknown” paths to your SPA entry (usually index.html).

Basic SPA fallback (static-only SPA)

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
}

Vercel’s rewrites already prioritize real files in your output (the “filesystem check”), so existing assets like /assets/app.js won’t be rewritten. [1][2]

SPA fallback but don’t catch /api/*

Use a negative lookahead so /api/... is excluded from the fallback:

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "rewrites": [
    { "source": "/((?!api/).*)", "destination": "/index.html" }
  ]
}

This pattern is commonly used to prevent SPA fallbacks from hijacking API routes. [3]

Legacy alternative (routes + filesystem handle)

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [
    { "handle": "filesystem" },
    { "src": "/(.*)", "dest": "/index.html" }
  ]
}

This is the older equivalent approach. [1]

Sources: [1] Vercel project configuration (Legacy SPA Fallback examples) [2] Vercel rewrites docs [3] Vercel discussion showing /((?!api/).*) SPA fallback exclusion pattern


🌐 Web query:

Expo web build output directory dist vercel.json

💡 Result:

Expo’s current web export command outputs to dist/ (not web-build/). Use:

  • Build: npx expo export -p web
  • Output directory: dist (docs.expo.dev)

A working vercel.json (for SPA-style routing) is:

{
  "buildCommand": "expo export -p web",
  "outputDirectory": "dist",
  "devCommand": "expo",
  "cleanUrls": true,
  "framework": null,
  "rewrites": [{ "source": "/:path*", "destination": "/" }]
}
``` ([docs.expo.dev](https://docs.expo.dev/guides/publishing-websites/?utm_source=openai))

Citations:

- 1: https://docs.expo.dev/guides/publishing-websites/?utm_source=openai
- 2: https://docs.expo.dev/guides/publishing-websites/?utm_source=openai

---



</details>

**Update vercel.json to match Expo web deployment guidance—use `expo export -p web`, correct `devCommand`, and switch to modern `rewrites` format.**

The configuration has several deviations from [Expo's official docs](https://docs.expo.dev/guides/publishing-websites/):

- `buildCommand`: Use `"expo export -p web"` instead of `"npm run build:web"`
- `devCommand`: Use `"expo"` instead of `"expo start --web"`
- `framework`: Use `null` instead of `"other"`
- Routing: Use the modern `rewrites` format instead of legacy `routes`; change to `"rewrites": [{ "source": "/:path*", "destination": "/" }]`
- Add `"cleanUrls": true` for cleaner URLs

<details>
<summary>Corrected vercel.json</summary>

```json
{
  "buildCommand": "expo export -p web",
  "outputDirectory": "dist",
  "devCommand": "expo",
  "cleanUrls": true,
  "framework": null,
  "rewrites": [{ "source": "/:path*", "destination": "/" }]
}
🤖 Prompt for AI Agents
In `@vercel.json` around lines 1 - 15, Update the vercel.json settings to follow
Expo web deployment guidance: change the buildCommand value from "npm run
build:web" to "expo export -p web", set devCommand to "expo" instead of "expo
start --web", set framework to null (not "other"), replace the legacy "routes"
array with a modern "rewrites" entry using { "source": "/:path*", "destination":
"/" }, and add cleanUrls: true; adjust the outputDirectory key only if needed
but leave "dist" as-is if correct.

Comment on lines +84 to +89
- `@stripe/stripe-react-native` → Needs Stripe.js web version
- `expo-location` → Needs browser geolocation API
- `react-native-maps` → Needs Google Maps JavaScript API
- `expo-local-authentication` → WebAuthn API
- Turing device sensors, camera, etc.

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix typo in native modules list.
“Turing device sensors” reads like a typo and should be “Other/Additional device sensors.”

✏️ Suggested edit
-- Turing device sensors, camera, etc.
+- Other device sensors, camera, etc.
📝 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
- `@stripe/stripe-react-native` → Needs Stripe.js web version
- `expo-location` → Needs browser geolocation API
- `react-native-maps` → Needs Google Maps JavaScript API
- `expo-local-authentication` → WebAuthn API
- Turing device sensors, camera, etc.
- `@stripe/stripe-react-native` → Needs Stripe.js web version
- `expo-location` → Needs browser geolocation API
- `react-native-maps` → Needs Google Maps JavaScript API
- `expo-local-authentication` → WebAuthn API
- Other device sensors, camera, etc.
🤖 Prompt for AI Agents
In `@WEB_DEPLOYMENT_GUIDE.md` around lines 84 - 89, Replace the typo "Turing
device sensors, camera, etc." in the native modules list with a clearer phrase
such as "Other/Additional device sensors, camera, etc."; update the list item
that currently reads `Turing device sensors, camera, etc.` so it reads
`Other/Additional device sensors, camera, etc.` (or similar wording) to fix the
wording in the native modules section.

Comment on lines +4 to +27
if (typeof window !== "undefined" && process.env.EXPO_USE_WEB_PLATFORM) {
// Mock expo-location
global.expo_location = {
getCurrentPositionAsync: async () => ({
coords: {
latitude: 37.7749,
longitude: -122.4194,
accuracy: 1,
},
}),
requestForegroundPermissionsAsync: async () => ({ status: "granted" }),
};

// Mock stripe payment sheet
global.stripe_payment_sheet = {
initPaymentSheet: async () => ({ paymentOption: null }),
presentPaymentSheet: async () => ({ error: null }),
};

// Mock expo-local-authentication
global.expo_auth = {
authenticateAsync: async () => ({ success: true }),
isEnrolledAsync: async () => true,
};
Copy link

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:

# First, let's confirm the file exists and review the full context
find . -name "index.js" -path "*web-polyfills*" -type f

Repository: adrianhajdin/uber

Length of output: 85


🏁 Script executed:

# Check if there's any documentation or tests that might clarify env var usage
find . -type f \( -name "*.md" -o -name "*.config.js" -o -name "*.env*" \) | grep -E "(README|config|env)" | head -20

Repository: adrianhajdin/uber

Length of output: 129


🌐 Web query:

Expo/React Native web global object polyfill best practices globalThis vs global

💡 Result:

What to use: globalThis vs global (Expo / React Native Web)

  • Prefer globalThis for cross-platform code. React Native explicitly documents that:
    • global is a legacy alias for globalThis and recommends globalThis instead. [1]
    • window/self are also aliases for globalThis and RN recommends globalThis over them too. [2]
  • On the web, globalThis is the standard, spec-defined way to access the global object across environments. [3]

Best-practice polyfill/alias patterns (when you must support a library)

1) If a dependency expects Node-style global on web

Some packages written for Node/RN may reference global. In a browser build, you can safely alias it early:

// polyfills.ts (import first!)
if (typeof globalThis.global === 'undefined') {
  // `@ts-expect-error` - define legacy alias for deps
  globalThis.global = globalThis;
}

This aligns with RN’s “global is a legacy alias for globalThis” model. [1]

2) If you need to support environments missing globalThis

This is uncommon for modern Expo web targets, but if you truly need it, use a spec-compliant shim (rather than hand-rolled Function("return this")() tricks):

  • The globalthis package provides a spec-compliant shim API. [4]

3) Put polyfills before anything else

Ensure your polyfill file is imported before other imports (so dependencies see it at module evaluation time):

import './polyfills';
import { registerRootComponent } from 'expo';
import App from './App';
registerRootComponent(App);

Bundler guidance (Webpack / Expo web)

  • If you’re tempted to inject globals via bundler config (e.g., shimming), do it only when necessary—Webpack’s own guidance is that relying on globals is generally discouraged and shimming is a last resort. [5]

Rule of thumb

  • Write new code against globalThis.
  • Only add global = globalThis (web) to satisfy third-party dependencies.
  • Prefer targeted shims/polyfills over broad “make the web look like Node” polyfills.

Sources: React Native global docs [1], RN window alias docs [2], MDN globalThis reference [3], globalthis shim package docs [4], Webpack shimming guidance [5].


🌐 Web query:

JavaScript environment variables process.env string comparison "true" "false"

💡 Result:

In Node.js, values in process.env are strings (or undefined)—even if you assign non-strings, Node will implicitly convert them to strings (e.g., null becomes 'null'). [1]

So for boolean-like env vars, compare to the string values you expect:

const enabled = process.env.FEATURE_ENABLED === 'true'; // only true when exactly "true"

If you want to accept more inputs ("1", "TRUE", etc.), normalize first:

const enabled = (process.env.FEATURE_ENABLED ?? '').toLowerCase() === 'true';

This “compare to 'true'” pattern is the common approach. [2]

Sources: [1] Node.js process.env docs, [2] Stack Overflow discussion on boolean env vars


🌐 Web query:

globalThis browser compatibility availability web environment

💡 Result:

globalThis is the standardized way to access the global object across JavaScript environments (Window, Web Workers, Node.js, etc.), avoiding environment-specific globals like window, self, or global. [1]

Browser compatibility (web)

Supported in all modern browsers; key minimum versions: Chrome 71+, Firefox 65+, Safari 12.1+, Edge 79+ (Chromium-based). [2][3]

Not supported in Internet Explorer (all versions, including IE 11) and legacy Edge (EdgeHTML 12–18). [2][4]

Overall global support is ~95%+ of users (per Can I use). [2]

Non-browser / other JS environments

  • Node.js: supported since Node 12 (and global is considered legacy—use globalThis). [3][5]
  • Web Workers: globalThis works in worker contexts as well (unlike window). [1]

If you need to support older browsers

Use a globalThis polyfill (commonly via core-js). [1]


🏁 Script executed:

# Let's examine the actual file content and context around the issue
cat -n ./web-polyfills/index.js

Repository: adrianhajdin/uber

Length of output: 1128


🏁 Script executed:

# Check if there are any related config files that might set these env vars
grep -r "EXPO_USE_WEB_PLATFORM" . --include="*.js" --include="*.ts" --include="*.json" --include="*.config.*" 2>/dev/null | head -20

Repository: adrianhajdin/uber

Length of output: 240


🏁 Script executed:

# Check the entry point and how this polyfill file is imported
find . -name "index.js" -o -name "App.js" -o -name "app.js" | xargs grep -l "web-polyfills" 2>/dev/null

Repository: adrianhajdin/uber

Length of output: 45


🏁 Script executed:

# Check how the metro.config.js uses this env var to understand the pattern
cat -n ./metro.config.js | head -30

Repository: adrianhajdin/uber

Length of output: 831


🏁 Script executed:

# Look for any documentation or setup files that explain how EXPO_USE_WEB_PLATFORM is intended to be used
grep -r "EXPO_USE_WEB_PLATFORM" . --include="*.md" 2>/dev/null

Repository: adrianhajdin/uber

Length of output: 114


Use globalThis and explicitly check env var against the string "true".

global is a legacy alias that isn't guaranteed to exist in browser environments; React Native recommends globalThis instead. Additionally, the current truthy check will incorrectly treat the string "false" as enabled, since non-empty strings are truthy in JavaScript. The env var should be explicitly compared to "true".

🛠️ Proposed fix
-if (typeof window !== "undefined" && process.env.EXPO_USE_WEB_PLATFORM) {
+const useWebPolyfills =
+  typeof window !== "undefined" &&
+  process.env.EXPO_USE_WEB_PLATFORM === "true";
+
+if (useWebPolyfills) {
+  const g = globalThis;
   // Mock expo-location
-  global.expo_location = {
+  g.expo_location = {
     getCurrentPositionAsync: async () => ({
       coords: {
         latitude: 37.7749,
         longitude: -122.4194,
         accuracy: 1,
       },
     }),
     requestForegroundPermissionsAsync: async () => ({ status: "granted" }),
   };
 
   // Mock stripe payment sheet
-  global.stripe_payment_sheet = {
+  g.stripe_payment_sheet = {
     initPaymentSheet: async () => ({ paymentOption: null }),
     presentPaymentSheet: async () => ({ error: null }),
   };
 
   // Mock expo-local-authentication
-  global.expo_auth = {
+  g.expo_auth = {
     authenticateAsync: async () => ({ success: true }),
     isEnrolledAsync: async () => true,
   };
📝 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
if (typeof window !== "undefined" && process.env.EXPO_USE_WEB_PLATFORM) {
// Mock expo-location
global.expo_location = {
getCurrentPositionAsync: async () => ({
coords: {
latitude: 37.7749,
longitude: -122.4194,
accuracy: 1,
},
}),
requestForegroundPermissionsAsync: async () => ({ status: "granted" }),
};
// Mock stripe payment sheet
global.stripe_payment_sheet = {
initPaymentSheet: async () => ({ paymentOption: null }),
presentPaymentSheet: async () => ({ error: null }),
};
// Mock expo-local-authentication
global.expo_auth = {
authenticateAsync: async () => ({ success: true }),
isEnrolledAsync: async () => true,
};
const useWebPolyfills =
typeof window !== "undefined" &&
process.env.EXPO_USE_WEB_PLATFORM === "true";
if (useWebPolyfills) {
const g = globalThis;
// Mock expo-location
g.expo_location = {
getCurrentPositionAsync: async () => ({
coords: {
latitude: 37.7749,
longitude: -122.4194,
accuracy: 1,
},
}),
requestForegroundPermissionsAsync: async () => ({ status: "granted" }),
};
// Mock stripe payment sheet
g.stripe_payment_sheet = {
initPaymentSheet: async () => ({ paymentOption: null }),
presentPaymentSheet: async () => ({ error: null }),
};
// Mock expo-local-authentication
g.expo_auth = {
authenticateAsync: async () => ({ success: true }),
isEnrolledAsync: async () => true,
};
}
🤖 Prompt for AI Agents
In `@web-polyfills/index.js` around lines 4 - 27, Replace usage of the legacy
global alias and the truthy env check: change the conditional to check typeof
window !== "undefined" && process.env.EXPO_USE_WEB_PLATFORM === "true", and
assign mocks to globalThis (e.g. globalThis.expo_location,
globalThis.stripe_payment_sheet, globalThis.expo_auth) instead of global.*; keep
the same mock shapes for getCurrentPositionAsync,
requestForegroundPermissionsAsync, initPaymentSheet, presentPaymentSheet,
authenticateAsync and isEnrolledAsync.

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