Real‑time campus occupancy and productivity app for students. CampusFlow helps you find less crowded study spots, stay focused with a Pomodoro timer, and connect with study buddies—all while contributing simple surveys that improve the crowdsourced map.
- Demo video: https://drive.google.com/file/d/1fNOGq6g5XUiXB0PS0emFqbMba9Z-_lMn/view?usp=sharing
- GitHub: https://github.com/Kevin88866/CampusFlow
- Features
- Architecture
- Screens & UX
- Data & Algorithms
- Quality & Testing
- Local Setup
- Troubleshooting
- Roadmap
- Credits
- Authentication
- Email + Password
- Google Sign‑In
- Email OTP (6‑digit, 5‑minute expiry) for registration and password reset
- Map with real‑time crowd/vacancy
- Overlays recent survey data and active user counts
- Updates location every minute during normal usage
- Survey‑based data collection
- One‑tap occupancy survey when entering an area
- Anti‑spam: 30‑minute cooldown per user per area
- Coins rewarded for valid submissions; Leaderboard shows rankings
- Automated occupancy detection
- As user base grows, occupancy can be derived from # of active users in an area
- Profiles & study history
- Name, phone, interests, avatar; history of study spots → buddy matching
- Chat
- Real‑time 1‑1 chat via Socket.IO
- Pomodoro timer
- Earn coins on completion; geofence rule: leaving study area cancels reward
- During timing: location updates every 10 seconds
- Reset password
- OTP‑based reset flow
Mobile (React Native)
- Screens: Login, Register, Map, Survey, Pomodoro, ChatList, Chat, Profile, Settings
- Shared UI in
/components; contexts in/contexts(e.g.,TimerContext,AuthContext) - Navigation:
AuthStackand bottom‑tabAppTabs
Backend (Node.js + Express + Socket.IO)
- REST routes:
auth,users,survey,occupancy,messages,pomodoro,ranking - Real‑time: Socket.IO private rooms (
user_<id>) for messaging - Security: bcrypt password hashing, Google ID token verification, request validation
Database (PostgreSQL)
- Tables (high‑level):
users,surveys,messages,user_habits,pomodoro_logs
Key screens you can capture from the app build (or mock in Figma):
- Area bucketing:
computeAreaId(lat, lon)truncates to ~1 km² cells. - Weighted crowd score from surveys:
- 0–1h weight 0.6, 1–2h 0.3, 2–3h 0.1
- Levels → scores: Sparse 0, Moderate 33, Crowded 66, Very Crowded 100
- Automated updates: As usage scales, live active user counts augment/replace surveys.
- Security: 6‑digit OTPs stored in memory (
purpose_email) with 5‑min expiry; sent via SMTP (Nodemailer). Passwords hashed with bcrypt.
- Principles: KISS/YAGNI, DRY, SRP, accessibility, privacy & security, 12‑factor config
- Testing (Jest):
- Frontend: RN Testing Library; mocks for navigation, AsyncStorage, geolocation, sockets, network, image picker
- Backend: Supertest for Express routes; Postgres test DB with migrations + seeds
- CI: GitHub Actions for lint + unit tests + coverage (target ≥70% overall; ≥85% for critical paths)
- Observability: Structured logs; consistent toast/error patterns on client
Prerequisites: Node.js LTS, Android SDK, Java 17, Postgres (local or Docker)
# 1) Clone
git clone https://github.com/Kevin88866/CampusFlow.git
cd CampusFlow
# 2) Backend database (choose one)
# Option A: Local Postgres
createdb campusflow_poc
psql campusflow_poc < backend/schema.sql
# Option B: Docker Postgres
docker run --name campusflow-db -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=campusflow -p 5432:5432 -d postgres:16
# 3) Environment
cp .env.example .env
# fill in: DATABASE_URL, SMTP creds, GOOGLE_CLIENT_ID, JWT/secret, etc.
# 4) Install & Run (server + app)
npm install
node server.js
npx react-native run-android
# 5) Build release APK
cd android
./gradlew assembleRelease
adb install -r app/build/outputs/apk/release/app-release.apkTesting
# All tests
npm test
# FE tests (examples)
npx jest __tests__/SurveyScreen.test.js
npx jest -t "should throttle survey submissions"
# BE tests (examples)
npx jest server.routes.test.js
# Coverage
npx jest --coverage- Google Sign‑In shows
DEVELOPER_ERROR- Ensure Android OAuth client in Google Cloud Console has correct package name + SHA‑1
- Download updated
google-services.jsontoandroid/app/ - Use
module:metro-react-native-babel-presetand@babel/plugin-transform-typescriptif needed
- Map jumps to (0,0) after tab switch
- Re‑run GPS + occupancy fetch on screen focus (
useIsFocused), keepregionand markercoordinatein sync
- Re‑run GPS + occupancy fetch on screen focus (
- Marker “sticks” to screen
- Bind
<MapView region>and<Marker coordinate>to the same live location state
- Bind
- Metro parser crash in Chat screen
- Update Babel config as above; reset Metro cache
- In‑app buddy matching (based on shared interests + study history)
- Push notifications for chat and Pomodoro milestones
- iOS build and distribution
- Admin dashboard for anomaly detection and abuse control
- Team: Zheng Kaiwen, Li Ziyu
- Built with React Native, Node.js/Express, Socket.IO, PostgreSQL






