Skip to content

Developer Onboarding โ€” Lantern โ€‹

Last Updated: 2026-03-13

Welcome to Lantern! This guide walks you through everything you need to go from zero to your first pull request. Read it top-to-bottom on day one; bookmark it for later reference.


1. What Is Lantern? โ€‹

Lantern is an anonymous, real-time people-meeting PWA anchored to physical venues. Users "light lanterns" at bars, cafรฉs, and restaurants to signal availability โ€” not with profiles or photos, but with presence. Think of it as a way to say "I'm here and open to meeting someone" without broadcasting your identity.

The product is currently in Pilot Mode โ€” access is restricted to admin-role users while the core experience is refined. You'll see PILOT_MODE = true in apps/web/src/App.jsx.

For a deeper product understanding, read docs/ABOUT.md and docs/business/timelines/INITIAL_LAUNCH.md.


2. Prerequisites โ€‹

Before you start, make sure you have:

  • Node.js v20+ and npm v8+ (node --version, npm --version)
  • Git configured with your work email
  • 2FA enabled on your GitHub account (required โ€” see Security Onboarding)
  • Access to the cattreedev/lantern_app GitHub repository
  • Firebase project credentials (ask a team member for .env.local values โ€” do not create your own projects for an existing team setup)
  • Membership in the team's Slack/Discord channel for incident alerts

3. Repository Setup โ€‹

Clone and Install โ€‹

bash
git clone https://github.com/cattreedev/lantern_app.git
cd lantern_app
npm install

This is an npm workspaces monorepo. One npm install at the root installs dependencies for all workspaces.

Environment File โ€‹

Once a maintainer has granted you roles/secretmanager.secretAccessor on the lantern-app-dev GCP project, one command populates everything:

bash
gcloud auth application-default login   # one-time
firebase login                            # one-time
npm run env:bootstrap

This fetches all 18 server-side secrets from GCP Secret Manager and the 7 public VITE_FIREBASE_* values via the Firebase Management API โ€” no manual copy-paste required. The script creates .env.local from .env.local.example if it doesn't exist yet.

Three per-developer values you fill yourself in .env.local after running bootstrap: GH_PAT (your own GitHub PAT), GITHUB_OWNER (your username), and (optionally) GOOGLE_APPLICATION_CREDENTIALS.

Never commit .env.local. It is gitignored by design. See ENVIRONMENT_SETUP.md for the full guide (including the manual fallback for environments without gcloud / firebase-tools) and ../security/SECRETS_MANAGEMENT.md for the deep dive on the secret architecture.

Start the Dev Server โ€‹

bash
npm run dev

Open http://localhost:5173. Check the browser console for:

๐Ÿ”ฅ Firebase initialized (local environment)
Project: lantern-app-dev

If you see that, you're connected correctly.


4. Codebase Architecture โ€‹

Monorepo Structure โ€‹

apps/
  web/           โ€” Main Lantern PWA (React 19 + Vite)        โ† you'll work here most
  admin/         โ€” Admin dashboard (separate React app)

services/
  functions/firebase/  โ€” Cloud Functions (Node 22)
  api/analytics/       โ€” Analytics API (Cloud Run)
  api/venues/          โ€” Venues API (Cloud Run)
  api/docs/            โ€” Docs API (Express.js, Cloud Run)
  bots/discord/        โ€” Discord bot for issue triage

packages/
  shared/        โ€” Shared constants & utilities (@lantern/shared)
  forge/         โ€” Shared BigQuery, Firestore, rate limiting, sanitization helpers

tooling/
  .storybook/    โ€” Storybook configuration
  scripts/       โ€” Build, lint, and utility scripts
  schemas/       โ€” BigQuery event schemas

Web App Internals (apps/web/src/) โ€‹

PathPurpose
App.jsxRoot component โ€” routing, auth gate, PILOT_MODE flag
firebase.jsFirebase initialization, environment detection, persistence
screens/{domain}/Page-level components: auth/, dashboard/, profile/, merchant/, frens/
components/Reusable UI components (mostly Storybook-backed)
lib/Service modules: auth.js, encryption.js, venueCacheManager.js, etc.
hooks/Custom React hooks

Routing โ€‹

Lantern uses hash-based routing โ€” no React Router. Routes are defined as window.location.hash checks in App.jsx:

HashScreen
#/Dashboard (Lantern Hub)
#/signupSign up
#/loginLogin
#/profileProfile settings
#/onboarding/profileFirst-time profile setup
#/merchantMerchant dashboard
#/merchant/newNew merchant setup
#/frensFriends
#/feedbackFeedback

To add a new route, update the route checks in App.jsx.

State Management โ€‹

No external state library. State flows through React hooks and Firestore real-time listeners (onSnapshot). Auth state is managed in App.jsx via onAuthChange. Venue data is cached in localStorage via venueCacheManager.js.

Shared Package โ€‹

packages/shared/ is aliased as @lantern/shared:

javascript
import { USER_ROLES, hasRequiredRole } from '@lantern/shared/auth'
import { isDevelopment } from '@lantern/shared/utils'

Zero-Knowledge Encryption โ€‹

User personal data is encrypted client-side before reaching Firestore:

  • Algorithm: PBKDF2 (600,000 iterations) + AES-256-GCM
  • Keys are derived from the user's passphrase โ€” never sent to the server
  • If a user loses their passphrase, their data is unrecoverable (by design)
  • Implementation: apps/web/src/lib/encryption.js

Critical distinction: The user's Lantern passphrase is also their Firebase Auth password AND their encryption key source. Do not conflate this with the admin portal password (see Admin Authentication below).

Firebase Collections โ€‹

CollectionPurposeTTL
usersProfiles (public fields + encrypted personal data)Permanent
lanternsActive check-ins48 hours
wavesMeeting requests7 days
chatsMessages30 days
venuesLocations (imported from OpenStreetMap)Permanent
offersMerchant promotionsPermanent
adminProfilesAdmin-roleโ€“specific data + separate password hashPermanent
merchantProfilesMerchant-roleโ€“specific dataPermanent

Security rules live in firestore.rules (Firestore) and storage.rules (Firebase Storage).


5. Development Workflow โ€‹

The Git Flow โ€‹

All changes go through pull requests. Direct pushes to dev or main are not allowed.

feature branch โ†’ PR โ†’ dev โ†’ (auto-deploy to dev.ourlantern.app)
dev โ†’ PR โ†’ main โ†’ (auto-deploy to ourlantern.app)

Your daily flow:

bash
# 1. Branch off dev
git checkout dev
git pull origin dev
git checkout -b your-name/issue-123-short-description

# 2. Make changes, run tests
npm run dev           # local dev server
npm run validate      # REQUIRED before committing (lint + tests + coverage + audit)

# 3. Commit (reference the issue)
git commit -m "feat(auth): add passphrase strength indicator (fixes #123)"

# 4. Open a PR targeting dev
gh pr create --base dev --title "..." --body "..."

Before Every Commit โ€‹

bash
npm run validate

This runs: lint โ†’ format check โ†’ unit tests โ†’ coverage โ†’ security audit โ†’ all workspace validations. Fix anything that fails before committing.

PR Rules โ€‹

  • Target the dev branch (not main)
  • Reference the GitHub issue: fixes #123 or closes #123
  • Keep PRs small and focused โ€” one feature or fix per PR
  • All CI checks must pass before merging (lint, tests, CodeQL, dependency scan)
  • Sensitive features (auth, encryption, payments) require a security reviewer

6. Key Commands Reference โ€‹

Web App (most common) โ€‹

bash
npm run dev              # Start dev server (http://localhost:5173)
npm run preview          # Production build preview (use for PWA testing)
npm test                 # Vitest in watch mode
npm run test:coverage    # Single run with 75% coverage threshold
npm run lint             # ESLint check
npm run lint:fix         # ESLint auto-fix
npm run format           # Prettier auto-fix
npm run validate         # Full validation โ€” run before every commit
npm run build            # Production build
npm run storybook        # Component library (http://localhost:6006)

Other Workspaces โ€‹

bash
npm run admin:dev                 # Admin panel (separate app)
npm run docs-api:dev              # Docs API
npm run analytics-api:dev         # Analytics API
npm run venue-api:dev             # Venues API

Useful One-Offs โ€‹

bash
npx vitest run apps/web/src/lib/__tests__/encryption.test.js  # Run a single test file
npm run docs:dev                                               # VitePress documentation site
npm run changelog:consolidate                                  # Merge daily changelogs

7. Security Checklist โ€‹

Complete this before your first commit to any production-connected system:

If you find a security issue, do not post it publicly. Follow the vulnerability disclosure process.

Full security onboarding checklist: docs/security/ONBOARDING.md.

Admin Authentication โ€‹

Important: Admin portal authentication is completely separate from the Lantern app passphrase.

The admin portal has its own adminPasswordHash stored in the adminProfiles Firestore collection. This password is verified via Cloud Function (signInAdmin) and is independent of Firebase Auth. This design prevents an admin password reset from breaking their Lantern app encryption.

If you're being set up as an admin:

  1. An existing admin creates your account
  2. You receive a setup link (?mode=adminReset&token=xxx)
  3. You set your admin portal password โ€” keep this separate from your Lantern passphrase

8. Testing โ€‹

Framework โ€‹

  • Vitest + Testing Library React + jsdom
  • Coverage threshold: 75% on lines, functions, branches, and statements

Where Tests Live โ€‹

apps/web/src/**/*.{test,spec}.{js,jsx}

Running Tests โ€‹

bash
npm test                  # Watch mode (during development)
npm run test:coverage     # Single run with full coverage report

Path Alias โ€‹

In tests, @ maps to apps/web/src/:

javascript
import { encrypt } from '@/lib/encryption'

Setup File โ€‹

apps/web/test.setup.js provides DOM polyfills and mocks (e.g., IntersectionObserver). If a test needs a new global mock, add it here.

Writing Tests โ€‹

  • Write tests for any new behavior you add
  • Unit test service modules in lib/ and hooks in hooks/
  • Component tests use Testing Library (prefer user-behavior queries over implementation details)
  • Run npm run test:coverage before your PR to verify you haven't dropped coverage below 75%

9. Documentation Practices โ€‹

Where Documentation Lives โ€‹

All documentation lives in docs/. Never put docs in src/ or other source directories. The canonical guide to what goes where is:

docs/engineering/guides/DIRECTORY_DEFINITIONS.md โ€” read this before creating any new doc

Naming Conventions โ€‹

TypeConventionExample
Regular docsCAPS_SNAKE_CASE.mdFEATURE_NAME.md
Worklog entriesYYYY-MM-DD_FEATURE_OUTCOME.md2026-03-13_WAVE_COMPLETE.md
Audit reportsAUDIT_YYYY-MM-DD.mdAUDIT_2026-03-13.md

Changelog โ€‹

Every PR should include a changelog entry. Add it to the daily section in docs/changelogs/dev/:

bash
# File: docs/changelogs/dev/dev-MM.DD.YYYY-v{version}.md

Use present tense: "Add feature" not "Added feature". See docs/engineering/guides/CHANGELOG_WORKFLOW.md for the full format.

Documentation Types โ€‹

TypeLocationWhen to Use
Feature specsdocs/features/{name}/New user-facing feature
Engineering guidesdocs/engineering/guides/How-to, workflows, operational procedures
Worklogsdocs/worklog/Completed work (2+ hours of significant work)
Plansdocs/plans/Roadmaps, large-scale planning
Architecture decisionsdocs/engineering/architecture/System design

10. Environments โ€‹

EnvironmentFirebase ProjectURLBranch
Locallantern-app-devlocalhost:5173Any
Developmentlantern-app-devdev.ourlantern.appdev
Productionlantern-app-prodourlantern.appmain

Environment Detection โ€‹

The app detects its environment via VITE_APP_ENV and hostname checks. When adding dev-only UI (debug panels, simulate buttons, etc.):

javascript
const hostname = typeof window !== 'undefined' ? window.location.hostname : ''
const isProductionEnv = import.meta.env.VITE_APP_ENV === 'production' || hostname === 'ourlantern.app'
const isDev = !isProductionEnv

Dev Utilities โ€‹

In dev mode, useful utilities are exposed on window (via apps/web/src/main.jsx): location spoofing, venue testing, and cache management. Open the browser console and type window. to see what's available. These utilities are stripped from production builds.


11. Deployment Rules โ€‹

Golden rule: never deploy directly. All deployments happen through GitHub Actions.

ActionBranchResult
Merge PR to devdevAuto-deploys to dev environment + Firebase
Merge PR to mainmainAuto-deploys to production
Open a PRAny branchPreview deployment created

Commands you must never run:

bash
wrangler pages deploy   # โŒ
firebase deploy         # โŒ
git push origin dev     # โŒ (direct push, not via PR)
git push origin main    # โŒ

CI pipeline details: docs/engineering/deployment/CICD_GUIDE.md.


12. Key Documentation Map โ€‹

Use this as a navigation guide. Start with what you need right now.

Getting Started โ€‹

Architecture โ€‹

Daily Development โ€‹

Deployment โ€‹

Features โ€‹

Business Context โ€‹


13. Common Gotchas โ€‹

"My changes aren't showing in Firebase" โ€” Check VITE_APP_ENV. If it's production, you're pointing at the prod project. Use local for development.

"Tests are passing locally but failing in CI" โ€” Run npm run validate (not just npm test). CI also runs lint and format checks that the test command alone skips.

"Coverage is below 75%" โ€” Run npm run test:coverage to see which files are under-covered. Write tests for new functions before the PR.

"I can't log into the admin portal" โ€” The admin password is separate from your Lantern passphrase. See Admin Authentication above.

"The app uses my real location" โ€” Use location spoofing in dev. Set VITE_DEV_TEST_LOCATION="lat,lon" in .env.local or use the debug panel in Profile Settings โ†’ Privacy.

"ESLint is complaining about console.log" โ€” Use console.warn or console.error instead. console.log is not allowed in production code. See docs/engineering/guides/CONSOLE_LOGGING.md.

"I accidentally pushed to dev directly" โ€” Alert the team lead immediately. Do not try to revert on your own without guidance.


14. Your First Week Checklist โ€‹

  • [ ] Complete environment setup and verify the dev server runs
  • [ ] Complete the security onboarding checklist
  • [ ] Read CLAUDE.md at the project root (AI assistant guidelines; also documents key conventions)
  • [ ] Browse docs/engineering/guides/DIRECTORY_DEFINITIONS.md to understand the docs structure
  • [ ] Explore apps/web/src/App.jsx to understand routing and the auth gate
  • [ ] Run npm run test:coverage and review what's tested
  • [ ] Read one completed worklog in docs/worklog/ to understand the cadence
  • [ ] Open your first PR (even a small docs fix counts!)
  • [ ] Join the incident channel and confirm you're on the on-call rotation (if applicable)

See Also โ€‹

Built with VitePress