Home Lens is a TypeScript React Native app built with Expo. It helps you model property purchases, compare scenarios, and understand long‑term financial impact. UI is built with React Native Paper; navigation via React Navigation. Keyboard handling uses react-native-keyboard-controller.
What’s in this repo
- App source (TypeScript)
- Assets (icons, splash)
- Expo/EAS configs (app.json, eas.json)
- Utility docs (analytics, EAS build guide)
Prerequisites
- Node.js (>= 18)
- pnpm (recommended), npm/yarn also work
- Expo CLI (via npx expo)
- Optional: Android Studio SDK (or use a physical device)
Install deps
pnpm installStart dev server
pnpm run startRun on Android
pnpm run androidRun on iOS (macOS only)
pnpm run iosType check
pnpm run typecheckScripts (from package.json)
- start: expo start
- android: expo run:android
- ios: expo run:ios
- typecheck: tsc --noEmit
- eas:update:preview / eas:update:prod (if using EAS Updates)
We use a single runtime flag to control developer features and console output.
- app.json → expo.extra.dev (boolean)
- Code helper:
ENV.DEVfromsrc/state/env.ts
What ENV.DEV toggles
- Shows DeveloperSection (Reset Onboarding) on Help screen
- Enables verbose console logs for analytics/crash tracking
- Production builds (ENV.DEV = false) silence analytics console logs while still emitting Firebase events (when native modules are available)
Set the flag
File: src/services/analytics.ts
- Uses @react-native-firebase/* when native modules are available; otherwise falls back gracefully.
- Console logs are wrapped with
if (ENV.DEV)– silent in production. - Events include screen views, feature usage, menu navigation, and device info.
Notes
- Managed workflow preview builds may not include RNFB native modules. Events won’t reach Firebase unless you prebuild (bare) or use a supported config plugin.
- Validation guide: see
FIREBASE_VERIFICATION.mdfor DebugView steps.
- Onboarding renders inside
KeyboardProviderand usesScreenContainer(KeyboardAwareScrollView) for proper keyboard avoidance. - app.json uses
android.softwareKeyboardLayoutMode = "resize"to lift content.
- Global theming: userInterfaceStyle = automatic (adapts to system theme)
- Header/logo:
src/components/Logo.tsxuses theme.colors.primary - Tables: table corner uses the same Logo SVG for a consistent, themed look
Preview (internal testing)
eas build --profile preview --platform allProduction
eas build --profile production --platform allOptional auto-submit
eas build --profile production --platform ios --auto-submit
eas build --profile production --platform android --auto-submit- app.json
- iOS/Android googleServicesFile paths set
- Android: softwareKeyboardLayoutMode = resize
- Adaptive icon/splash configured
- Metro cache issues:
npx expo start -c- Android SDK not found: ensure platform-tools on PATH
- RNFB module errors in managed preview: analytics falls back; use prebuild for full native support
- app.json:
extra.devis false for production - Build succeeds on both platforms via EAS
- Onboarding email input scrolls above keyboard on Android
- Theme switch updates Scenario cards (Android / iOS)
- No unexpected console noise in production (analytics logs gated)
- Icons/splash look correct in light/dark
- HubSpot portalId & formGuid configured (or intentionally disabled)
- Test email appears in HubSpot Contacts (if enabled)
- PRs welcome. Run
pnpm run typechecklocally before opening. - Formatting via Prettier (see package.json).
0BSD (see package.json)
The onboarding screen collects the user’s email and (optionally) submits it to HubSpot using the Forms API.
Implementation
- Submission function:
submitUserEmail()insrc/services/backend.ts - Primary call path:
Onboarding.tsx→handleSubmit→submitUserEmail - Graceful failure: If the network or HubSpot responds with an error, onboarding still completes (user is not blocked).
Configuration
- Create (or locate) a HubSpot form with an Email field.
- Copy your Portal ID and Form GUID.
- Edit
src/services/backend.tsand set:const HUBSPOT_CONFIG = { portalId: "<YOUR_PORTAL_ID>", formGuid: "<YOUR_FORM_GUID>", };
- (Optional) Add custom fields in HubSpot for:
platform,device_model,app_version,signup_date. - Ensure the form has consent enabled if you require GDPR compliance (repository already sends a consent object).
Payload example sent to HubSpot
{
"fields": [
{ "objectTypeId": "0-1", "name": "email", "value": "user@example.com" },
{ "objectTypeId": "0-1", "name": "platform", "value": "android" },
{ "objectTypeId": "0-1", "name": "app_source", "value": "mobile_app" },
{ "objectTypeId": "0-1", "name": "signup_date", "value": "2025-11-12T09:15:11.123Z" }
],
"context": { "pageUri": "app://homelens/onboarding", "pageName": "HomeLens Onboarding" },
"legalConsentOptions": { "consent": { "consentToProcess": true, "text": "I agree to allow HomeLens to store and process my personal data." }}
}Testing the integration
- Set real
portalIdandformGuidinbackend.ts. - Delete the app (or reset onboarding via Help → DeveloperSection if
ENV.DEVis true). - Enter a test email and submit.
- Check HubSpot: Contacts → search for the email; confirm form submission in activity timeline.
- For failures, inspect device logs for
[Backend] Failed to submit email to HubSpot:.
Safety / Failure modes
- HubSpot misconfigured (placeholder IDs): A warning is logged (in DEV) and onboarding continues.
- Network failure: Error logged; user still proceeds.
- Duplicate email: HubSpot updates existing contact; onboarding unaffected.
Privacy & Consent
- A consent block is included in the API payload (see above). Adjust wording in
backend.tsif policy changes. - Add a link to your full privacy policy in the onboarding UI if required by your jurisdiction.
Disable or pause HubSpot
- Temporarily comment out the call to
submitUserEmailinOnboarding.tsx. - Or set invalid portal/form IDs (not recommended) — better to remove the call explicitly.
Production considerations
- Keep
ENV.DEVfalse in production builds; HubSpot logs are minimal. - If you want to A/B test email collection, wrap the call in a feature flag (similar to
ENV.DEV).