Skip to content

Add React Native + Expo mobile app (bare workflow) - #2

Merged
King-Austin merged 20 commits into
mainfrom
claude/review-deployment-readiness-3tEAH
May 27, 2026
Merged

King-Austin merged 20 commits into
mainfrom
claude/review-deployment-readiness-3tEAH

Conversation

@King-Austin

Copy link
Copy Markdown
Owner

Summary

This PR introduces a complete React Native + Expo implementation of the Smart Campus Presence attendance system, running in bare workflow mode. The native app mirrors the web application's core functionality while leveraging platform-specific APIs for GPS, BLE, and biometric verification.

Key Changes

New Mobile App Structure (/native)

  • Root setup: App.tsx, index.ts, configuration files (app.json, eas.json, tsconfig.json, babel.config.js, metro.config.js)
  • Navigation: Type-safe navigation stack with RootNavigator, AuthStack, StudentTabs, LecturerTabs, and RegisterStack
  • Theme & UI: Dark mode color system, reusable component library (Button, Input, Badge, Card, BlurCard)

Core Screens Implemented

  • Authentication: LandingScreen, LoginScreen, LecturerRegisterScreen
  • Student Registration (3-step flow): BasicInfoScreen, CourseSelectScreen, FaceEnrollScreen
  • Student Dashboard: StudentDashboardScreen with live sessions list and attendance stats
  • Attendance Verification: AttendanceVerificationScreen — multi-step verification (init → GPS → BLE → face → upload) with animated checklist and haptic feedback
  • Lecturer Dashboard: LecturerDashboardScreen with stat cards and session management
  • Session Management: CreateSessionScreen (form to launch sessions), LiveSessionScreen (real-time attendance feed)
  • History: AttendanceLedgerScreen with search and filtering

Verification & Biometrics

  • CameraCapture.tsx: Expo Camera integration for face enrollment and verification (base64 JPEG capture)
  • useBiometrics hook: Communicates with remote InsightFace API for face vectorization and similarity scoring
  • useBleScanner hook: BLE proximity scanning with RSSI threshold validation (> -80 dB)
  • GPS integration: Haversine distance calculation with 500m soft-gate for campus proximity

Dashboard Components

  • AttendanceScoreboard: Animated progress ring (Reanimated) showing overall attendance % and per-course breakdown
  • LiveSessionCard: Session card with course info, lecturer name, and "Mark Attendance" CTA
  • AttendanceFeed: Real-time list of student check-ins with status badges
  • SessionStats: Present/total enrollment counters
  • SessionHeader: Course code, name, topic, and date display
  • EngagementChart: Cumulative attendance sparkline by 5-minute intervals

Hooks & Utilities

  • useProfile: Fetch authenticated user profile from Supabase
  • useLiveSessions: Query active sessions for students
  • useAttendanceStats: Calculate overall and per-course attendance metrics
  • useSessionData: Fetch session details and attendance records with real-time subscriptions
  • useLecturerData: Dashboard stats (total students, course count, avg attendance)
  • useBlePeripheral: BLE broadcast control for lecturer sessions
  • getUniqueDeviceId: Secure device binding via expo-secure-store
  • getCurrentPosition / calculateDistance: Geolocation helpers using expo-location

Database Types

  • native/src/integrations/supabase/types.ts: Auto-generated TypeScript types for all Supabase tables (attendance_records, profiles, courses, sessions, enrollments, face_embeddings, etc.)

Configuration & Build

  • Supabase client: Configured with AsyncStorage for React Native persistence
  • Toast notifications: react-native-toast-message integration
  • Styling: NativeWind (Tailwind CSS for React Native) with dark mode preset
  • Dependencies: Expo 54, React Native Reanimated, React Navigation, Lucide icons, BLE libraries

Documentation

  • **`MOBILE_MIGRATION_PLAN.

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE

claude added 7 commits May 19, 2026 19:05
Sets up the complete React Native + Expo (SDK 54) project in native/ alongside
the existing web app. Covers all infrastructure, configuration, and business
logic layers so parallel screen-conversion agents can build on a clean base.

What's in this commit
─────────────────────
• MOBILE_MIGRATION_PLAN.md — full route→screen mapping doc (Phase 1)
• native/app.json — bundle IDs, permissions, dark splash, scheme
• native/eas.json — development / preview / production EAS Build profiles
• native/babel.config.js — NativeWind + module-resolver + Reanimated (last)
• native/metro.config.js — withNativeWind wrapper
• native/tailwind.config.js — brand palette (#0E0E12, #00E5FF, #9B59B6)
• native/tsconfig.json — @/ path alias → ./src/
• native/.env.example — EXPO_PUBLIC_* variable template
• src/integrations/supabase/client.ts — AsyncStorage auth (replaces localStorage)
• src/integrations/supabase/types.ts — verbatim copy of generated DB types
• src/constants/, src/types/ — copied as-is from web app
• src/lib/{utils,toast,geo,device,ble}.ts — native rewrites
• src/hooks/ — 9 hooks (5 verbatim, useBiometrics env-var swap,
  useBlePeripheral→ble-advertiser, useBleScanner NEW central scan)
• src/navigation/ — RootNavigator (auth-aware), AuthStack, StudentTabs,
  LecturerTabs, typed ParamLists
• src/theme/colors.ts — brand color tokens
• src/components/ui/ — Button, Card, Input, Badge (RN primitives)
• src/components/ — BlurCard (expo-blur), PresenceLoader (Reanimated),
  CameraCapture (expo-camera, replaces MediaPipe LivenessScanner)
• src/components/dashboard/ — LiveSessionCard, DashboardHeader,
  AttendancePinger, CourseManagementDialog, LogoutConfirmDialog
• src/components/live-session/ — SessionHeader, SessionStats
• src/screens/ — LandingScreen, LoginScreen (auth screens in progress)
• App.tsx — GestureHandlerRootView → SafeAreaProvider → QueryClient → RootNavigator

Screens still being written by parallel agents (follow-up commit pending):
register wizard, StudentDashboard, AttendanceVerification, AttendanceLedger,
LecturerDashboard, CreateSession, LiveSession, remaining live-session components.

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
Written by parallel agents:
- src/screens/StudentDashboardScreen.tsx
- src/screens/register/CourseSelectScreen.tsx
- src/screens/register/FaceEnrollScreen.tsx
- src/components/live-session/AttendanceFeed.tsx
- src/components/live-session/EngagementChart.tsx
- src/components/live-session/SessionStats.tsx (updated)

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
…tion

Full React Native + Expo (SDK 54, bare workflow) project in native/ alongside
the untouched web app. All infrastructure, business logic, and UI layers are
complete; remaining screens being written by parallel agents will follow.

See MOBILE_MIGRATION_PLAN.md for the full route→screen mapping.

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
Add the remaining lecturer/student screen implementations (Attendance
Verification, Ledger, Create Session, Live Session, Lecturer Dashboard,
Lecturer Register, Manual Entry, Analytics, Not Found) plus a stub
EngagementChart that renders a sparkline via react-native-svg instead of
victory-native v41 (which requires Skia).

Resolve outstanding TypeScript errors:
- Toast shim accepts both string and `{ description }` second-argument
  shapes and exposes `warning` so existing call sites compile.
- Button accepts an optional `style` prop merged into its Pressable.
- NativeWind type reference points at `nativewind/types` so `className`
  is recognised on RN intrinsic elements.
- BLE peripheral broadcast encodes the token prefix as a manufacturer-
  data byte array (matches `react-native-ble-advertiser` v0 signature).
- BLE scanner uses the v12 `ScanOptions` object form for `scan()`.
- Strongly type checklist colours and add `day_number` to session
  inserts so the Supabase row matches the schema.

Install the missing native runtime deps (lucide-react-native, victory-
native, react-native-svg, react-native-toast-message, react-native-ble-
manager/advertiser, expo-camera/location/device/secure-store/blur/
haptics) so `tsc --noEmit` and module resolution both succeed.

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
Replaces the old Capacitor Gradle workflow with an EAS Build job that:
- Triggers on pushes to main / the native migration branch and via
  workflow_dispatch (so you can trigger a build manually from the
  GitHub Actions tab with a choice of preview or production profile).
- Runs tsc --noEmit first so the build only proceeds when the
  TypeScript check is green.
- Uses the existing eas.json `preview` profile which outputs a
  side-loadable APK (not an AAB) via `android.buildType: apk`.
- Passes Supabase + biometric server env vars from repo secrets.
- Writes the EAS build dashboard URL to the job summary so the APK
  download link is one click away after the ~10-min cloud build.

Required repo secrets to set before triggering:
  EXPO_TOKEN                        — from expo.dev/settings/access-tokens
  EXPO_PUBLIC_SUPABASE_URL
  EXPO_PUBLIC_SUPABASE_PUBLISHABLE_KEY
  EXPO_PUBLIC_BIOMETRIC_SERVER_URL

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
Replaces the EAS cloud build workflow with a direct Gradle build that
runs entirely on the ubuntu-latest runner (which ships with the Android
SDK). No EXPO_TOKEN or Expo account required.

Steps:
1. npm ci + tsc --noEmit — fail fast on type errors
2. expo prebuild --platform android -- generates android/ from app.json
3. gradlew assembleDebug -- compiles the debug APK
4. upload-artifact -- makes app-debug.apk downloadable directly from
   the Actions run page (retained 14 days)

Env vars for Supabase / biometric server fall back to placeholder
strings during prebuild (only needed at runtime, not compile time).
Real values can be added as repo secrets to bake them into the bundle.

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
actions/checkout, setup-node, setup-java, cache, and upload-artifact
all updated from v4 → v5 so the action runners use Node.js 22.

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
Copilot AI review requested due to automatic review settings May 20, 2026 09:09
@vercel

vercel Bot commented May 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
smart-attendance Ready Ready Preview, Comment May 27, 2026 7:38pm

@ecc-tools

ecc-tools Bot commented May 20, 2026

Copy link
Copy Markdown

Analyzing 200 commits...

@ecc-tools

ecc-tools Bot commented May 20, 2026

Copy link
Copy Markdown

Analysis Complete

Generated ECC bundle from 7 commits | Confidence: 70%

View Pull Request #3

Repository Profile
Attribute Value
Language TypeScript
Framework Not detected
Commit Convention conventional
Test Directory separate
Changed Files (80)
Metric Value
Files changed 80
Additions 23659
Deletions 1

Top hotspots

Path Status +/-
native/package-lock.json added +10796 / -0
native/src/screens/AttendanceVerificationScreen.tsx added +1309 / -0
native/src/screens/CreateSessionScreen.tsx added +884 / -0
native/src/screens/LecturerDashboardScreen.tsx added +675 / -0
native/src/screens/StudentDashboardScreen.tsx added +634 / -0

Top directories

Directory Files Total changes
native 15 11153
native/src/screens 11 5198
native/src/components/dashboard 5 1440
native/src/screens/register 3 1296
native/src/components/live-session 5 809
Analysis Depth Readiness (evidence-backed, 43%)

ECC Tools uses this to decide whether recommendations should stay at commit-history/setup guidance or expand into CI, security, harness, reference-set, AI-routing, and team backlog work.

Area Status Evidence / Next Step
Commit history Ready 7 commits sampled
CI/CD signals Ready .github/workflows/build-android.yml
Security evidence Missing Add AgentShield, audit, SARIF, SBOM, or security review evidence so recommendations can cover security posture.
Harness configuration Missing Add Claude, Codex, OpenCode, Zed, dmux, MCP, plugin, or cross-harness config evidence for harness-agnostic recommendations.
Reference/eval evidence Missing Add fixtures, golden traces, reference sets, or evaluator benchmarks so deeper recommendations have regression evidence.
AI routing and cost controls Ready MOBILE_MIGRATION_PLAN.md, native/CLAUDE.md
Team handoff and project tracking Missing Add roadmap, runbook, project, Linear, or follow-up tracking docs so generated work can land in a team queue.
Reference Set Readiness (0/7, 0%)
Area Status Evidence / Next Step
Deep analyzer corpus Missing Add analyzer fixture, golden, benchmark, or reference-set files that can catch analyzer regressions.
RAG/evaluator comparison Missing Add retrieval or evaluator reference-set comparison fixtures with expected ranking behavior.
PR salvage/review corpus Missing Add stale-PR, review-thread, reopen-flow, or salvage reference cases for queue cleanup automation.
Discussion triage corpus Missing Add public discussion triage fixtures, golden cases, or reference sets for informational, answered, and no-response classifications.
Harness compatibility Missing Add cross-harness, adapter-compliance, or harness-audit evidence for Claude, Codex, OpenCode, Zed, dmux, and agent surfaces.
Security evidence Missing Attach security evidence such as SBOMs, SARIF, audit reports, or AgentShield evidence packs.
CI failure-mode evidence Missing Add captured CI failure logs, dry-run fixtures, or troubleshooting docs for common workflow failure modes.
Likely Future Issues (5)
Severity Signal Why it may show up
HIGH Regression coverage may lag behind the diff 35 generic code paths changed; 0 test files changed
MEDIUM Runtime config changes may ship without example or template updates 4 runtime config paths changed; 0 example or template config files changed
MEDIUM User-facing UI changes may ship without browser coverage 21 user-facing UI paths changed; 0 browser or e2e coverage files changed
HIGH Security-sensitive changes may ship without scanner evidence 9 security-sensitive paths changed; 0 security scanner or security-focused validation artifacts changed
MEDIUM CI workflow changes may ship without failure-mode evidence 1 CI/test-runner paths changed; 0 CI failure-mode evidence artifacts changed
  • Regression coverage may lag behind the diff: The PR changes multiple code paths but does not touch any obvious test files.
  • Runtime config changes may ship without example or template updates: The PR changes runtime config or deployment settings but does not update any obvious example env file or config template.
  • User-facing UI changes may ship without browser coverage: The PR changes components, pages, or other user-facing UI files without touching any obvious browser or end-to-end coverage.
  • Security-sensitive changes may ship without scanner evidence: The PR touches billing, secrets, auth, webhooks, agent, or CI-sensitive surfaces without adding obvious security scanner, code scanning, or security-focused validation evidence.
  • CI workflow changes may ship without failure-mode evidence: The PR changes CI workflows or test-runner entrypoints without touching CI failure fixtures, captured logs, troubleshooting notes, or regression evidence.
Suggested Follow-up Work (5)
Type Suggested title Targets
PR test: add regression coverage for native/App.tsx + native/babel.config.js native/App.tsx, native/babel.config.js
PR chore: sync config templates for native/.claude/settings.json + native/babel.config.js native/.claude/settings.json, native/babel.config.js
PR test: add browser coverage for native/global.css + native/src/components/BlurCard.tsx native/global.css, native/src/components/BlurCard.tsx
PR security: add scanner evidence for native/src/hooks/use-toast.ts + native/src/hooks/useAttendanceStats.ts native/src/hooks/use-toast.ts, native/src/hooks/useAttendanceStats.ts
PR ci: add failure-mode evidence for .github/workflows/build-android.yml .github/workflows/build-android.yml
  • test: add regression coverage for native/App.tsx + native/babel.config.js: Backfill regression coverage before another change set lands on the touched code paths.
  • chore: sync config templates for native/.claude/settings.json + native/babel.config.js: Backfill example env files or config templates before a fresh setup drifts from the shipped runtime surface.
  • test: add browser coverage for native/global.css + native/src/components/BlurCard.tsx: Backfill browser coverage before another user-facing UI change lands on the touched surface.
  • security: add scanner evidence for native/src/hooks/use-toast.ts + native/src/hooks/useAttendanceStats.ts: Backfill explicit scanner or code-scanning evidence before another security-sensitive change lands on the touched surface.
  • ci: add failure-mode evidence for .github/workflows/build-android.yml: Backfill CI failure-mode evidence before another workflow or test-runner change lands on the touched surface.

Copy-ready bodies

test: add regression coverage for native/App.tsx + native/babel.config.js

## Summary
- Add regression coverage for the recently touched code paths before more changes stack on top.

## Why
- Backfill regression coverage before another change set lands on the touched code paths.

## Touched paths
- `native/App.tsx`
- `native/babel.config.js`

## Validation
- Add or extend focused tests that exercise the touched paths.
- Run the affected test suite and verify the new coverage closes the gap.

chore: sync config templates for native/.claude/settings.json + native/babel.config.js

## Summary
- Update the example env files, sample configs, or deployment templates that should mirror the changed runtime configuration surface.

## Why
- Backfill example env files or config templates before a fresh setup drifts from the shipped runtime surface.

## Touched paths
- `native/.claude/settings.json`
- `native/babel.config.js`

## Validation
- Update the repo example env file or config template that should reflect the new runtime settings.
- Run the setup, boot, or deployment validation flow that depends on the changed config surface.

test: add browser coverage for native/global.css + native/src/components/BlurCard.tsx

## Summary
- Add browser or end-to-end coverage for the recently changed user-facing surface.

## Why
- Backfill browser coverage before another user-facing UI change lands on the touched surface.

## Touched paths
- `native/global.css`
- `native/src/components/BlurCard.tsx`

## Validation
- Add or extend browser / e2e coverage for the changed component, page, or flow.
- Exercise the visible user journey that depends on the touched UI surface.

security: add scanner evidence for native/src/hooks/use-toast.ts + native/src/hooks/useAttendanceStats.ts

## Summary
- Add security scanner or code-scanning evidence for the recently changed security-sensitive surface.

## Why
- Backfill explicit scanner or code-scanning evidence before another security-sensitive change lands on the touched surface.

## Touched paths
- `native/src/hooks/use-toast.ts`
- `native/src/hooks/useAttendanceStats.ts`

## Validation
- Run or add the relevant security scanner, code scanning, secret scanning, or dependency/security review check for the touched surface.
- Attach the scanner output, SARIF/code-scanning result, or focused security regression test to the follow-up PR.
- Confirm the changed auth, billing, webhook, secret-handling, agent, or CI surface has an explicit pass/fail gate.

ci: add failure-mode evidence for .github/workflows/build-android.yml

## Summary
- Add CI failure-mode evidence for the recently changed workflow or test-runner surface.

## Why
- Backfill CI failure-mode evidence before another workflow or test-runner change lands on the touched surface.

## Touched paths
- `.github/workflows/build-android.yml`

## Validation
- Add or update a CI failure fixture, captured failing log, troubleshooting note, workflow dry-run evidence, or regression test for the changed CI/test-runner behavior.
- Run the affected workflow or test-runner entrypoint locally or in CI and record pass/fail evidence.
Detected Workflows (3)
Workflow Description
feature-development Standard feature implementation workflow
add-or-update-react-native-screen-or-component Implements a new screen or component in the React Native (Expo) app, or updates an existing one, as part of feature development or migration.
ci-android-build-workflow-update Adds or updates the GitHub Actions workflow for building the Android APK, switching between EAS Build and local Gradle, and updating action versions.
Generated Instincts (29)
Domain Count
git 4
code-style 10
architecture 1
testing 3
workflow 11

After merging, import with:

/instinct-import .claude/homunculus/instincts/inherited/Smart_Classroom_Attendance-instincts.yaml

Files

  • .claude/ecc-tools.json
  • .claude/skills/Smart_Classroom_Attendance/SKILL.md
  • .agents/skills/Smart_Classroom_Attendance/SKILL.md
  • .agents/skills/Smart_Classroom_Attendance/agents/openai.yaml
  • .claude/identity.json
  • .codex/config.toml
  • .codex/AGENTS.md
  • .codex/agents/explorer.toml
  • .codex/agents/reviewer.toml
  • .codex/agents/docs-researcher.toml
  • .claude/homunculus/instincts/inherited/Smart_Classroom_Attendance-instincts.yaml
  • .claude/commands/feature-development.md
  • .claude/commands/add-or-update-react-native-screen-or-component.md
  • .claude/commands/ci-android-build-workflow-update.md

ECC Tools | Everything Claude Code

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a new React Native + Expo (bare workflow) mobile app under /native to mirror the existing Smart Campus Presence attendance features, including Supabase-backed auth/data flows and student/lecturer navigation.

Changes:

  • Added a full Expo workspace (/native) with build configuration, NativeWind styling, Supabase client integration, and navigation scaffolding.
  • Implemented core auth + registration screens and lecturer/student flows (live session monitoring, ledger/history, dashboards/components).
  • Added GitHub Actions workflow updates to build an Android debug APK from the new native app.

Reviewed changes

Copilot reviewed 74 out of 80 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
native/tsconfig.json Expo TS config + path aliases
native/tailwind.config.js NativeWind/Tailwind theme tokens
native/src/types/index.ts Supabase-derived domain types
native/src/theme/colors.ts Central color system
native/src/screens/register/CourseSelectScreen.tsx Registration step: course selection
native/src/screens/register/BasicInfoScreen.tsx Registration step: basic info
native/src/screens/NotFoundScreen.tsx Fallback screen
native/src/screens/LoginScreen.tsx Supabase password login
native/src/screens/LiveSessionScreen.tsx Lecturer live session monitoring UI
native/src/screens/LecturerRegisterScreen.tsx Lecturer registration flow
native/src/screens/LandingScreen.tsx Unauthenticated landing/CTA screen
native/src/screens/AttendanceLedgerScreen.tsx Ledger/history screen
native/src/screens/AnalyticsScreen.tsx Lecturer analytics placeholder
native/src/navigation/types.ts Navigation param typing
native/src/navigation/StudentTabs.tsx Student bottom tabs + nested stack
native/src/navigation/RootNavigator.tsx Auth/role-based root switching
native/src/navigation/LecturerTabs.tsx Lecturer bottom tabs + nested stack
native/src/navigation/AuthStack.tsx Unauthenticated navigation + register stack
native/src/lib/utils.ts Utility helpers (cn, percentage)
native/src/lib/toast.ts Toast wrapper API
native/src/lib/geo.ts Location permission + haversine distance
native/src/lib/device.ts SecureStore-based device ID + metadata
native/src/lib/ble.ts BLE advertiser wrapper
native/src/integrations/supabase/types.ts Generated Supabase database types
native/src/integrations/supabase/client.ts RN Supabase client with AsyncStorage auth
native/src/hooks/useSessionData.ts Session details + realtime records hook
native/src/hooks/useProfile.ts Current user profile hook
native/src/hooks/useLiveSessions.ts Student live sessions hook
native/src/hooks/useLecturerData.ts Lecturer dashboard data hook
native/src/hooks/useBleScanner.ts Student BLE scanning hook
native/src/hooks/useBlePeripheral.ts Lecturer BLE broadcast hook
native/src/hooks/useBiometrics.ts Biometric enroll/verify API hook
native/src/hooks/useAttendanceStats.ts Student attendance stats hook
native/src/hooks/use-toast.ts Re-export of toast API
native/src/constants/index.ts Shared constants (statuses, BLE UUIDs, etc.)
native/src/components/ui/Input.tsx Input UI component
native/src/components/ui/index.ts UI barrel exports
native/src/components/ui/Card.tsx Card UI component
native/src/components/ui/Button.tsx Button UI component
native/src/components/ui/Badge.tsx Badge UI component
native/src/components/PresenceLoader.tsx Animated loader component
native/src/components/OfflineStatus.tsx Connectivity banner component
native/src/components/LogoutConfirmDialog.tsx Logout confirmation modal
native/src/components/live-session/SessionStats.tsx Live session stats widget
native/src/components/live-session/SessionHeader.tsx Live session header widget
native/src/components/live-session/ManualEntry.tsx Manual attendance entry modal
native/src/components/live-session/EngagementChart.tsx Lightweight sparkline chart
native/src/components/live-session/AttendanceFeed.tsx Live attendance feed list
native/src/components/dashboard/LiveSessionCard.tsx Student “mark attendance” session card
native/src/components/dashboard/DashboardHeader.tsx Lecturer dashboard header
native/src/components/dashboard/CourseManagementDialog.tsx Course enrollment management modal
native/src/components/dashboard/AttendanceScoreboard.tsx Attendance ring + breakdown UI
native/src/components/dashboard/AttendancePinger.tsx “Live/no sessions” indicator
native/src/components/BlurCard.tsx Blur/glassmorphism card wrapper
native/package.json Native app dependencies/scripts
native/nativewind-env.d.ts NativeWind type reference
native/metro.config.js Metro + NativeWind config
native/index.ts Expo root registration
native/global.css Tailwind directives for NativeWind
native/eas.json EAS build profiles
native/CLAUDE.md Agent config reference
native/babel.config.js Babel config (NativeWind + module resolver + reanimated)
native/App.tsx App root providers + RootNavigator + Toast
native/app.json Expo app config + permissions
native/AGENTS.md Agent guidance note
native/.gitignore Native workspace gitignore
native/.claude/settings.json Claude plugin settings
MOBILE_MIGRATION_PLAN.md Migration plan documentation
.github/workflows/build-android.yml Android APK build workflow for /native

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread native/src/lib/toast.ts Outdated
Comment on lines +9 to +11
Toast.show({ type: "info", text1, text2: typeof text2 === "object" ? text2?.description : text2 }),
warning: (text1: string, text2?: string | { description?: string }) =>
Toast.show({ type: "info", text1, text2: typeof text2 === "object" ? text2?.description : text2 }),
Comment on lines +54 to +59
const { data, error } = await supabase
.from('courses')
.select('*')
.eq('level', params.level)
.eq('semester', params.semester);

Comment on lines +49 to +52
useEffect(() => {
if (!sessionId) return;
fetchLedgerData();
}, [sessionId]);
Comment thread native/src/lib/ble.ts
Comment on lines +52 to +68
try {
// Encode first 4 chars of token as ASCII bytes in manufacturer data so
// student scanners can match the broadcast without GATT service discovery.
const tokenPrefix = token.slice(0, 4);
const manufData: number[] = [];
for (let i = 0; i < tokenPrefix.length; i++) {
manufData.push(tokenPrefix.charCodeAt(i));
}

await BLEAdvertiser.broadcast(
SERVICE_UUID,
manufData,
{
includeDeviceName: false,
connectable: false,
}
);
Comment on lines +119 to +144
foundRef.current = false;
resolveRef.current = resolve;

const expectedName = 'Session-' + targetToken.slice(0, 4);

setIsScanning(true);

try {
// Ensure the BLE module is started before scanning
await BleManager.start({ showAlert: false });
} catch (err) {
// start() throws if already initialized — safe to ignore
console.log('[useBleScanner] BleManager.start() (may already be running):', err);
}

// Register the peripheral discovery listener before starting the scan
// so we don't miss advertisements that arrive immediately.
subscriptionRef.current = bleEmitter.addListener(
'BleManagerDiscoverPeripheral',
(peripheral: Peripheral) => {
if (foundRef.current) return; // already resolved

const name = peripheral.name ?? '';

if (name === expectedName) {
foundRef.current = true;
Comment on lines +32 to +36
const { data: records } = await supabase
.from("attendance_records")
.select("session_id")
.eq("student_id", studentId);

Comment on lines +31 to +44
if (sessionsData) {
const sessionsWithStats = await Promise.all(
sessionsData.map(async (s: any) => {
const { count: totalEnrolled } = await supabase
.from("enrollments")
.select("*", { count: "exact", head: true })
.eq("course_id", s.course_id);

const present =
s.attendance_records?.filter(
(r: any) => r.status === "verified"
).length || 0;
return { ...s, present, total: totalEnrolled || 0 };
})
Comment on lines +99 to +113
function CourseRow({ course }: { course: CourseBreakdown }) {
const barWidth = useSharedValue(0);

useEffect(() => {
barWidth.value = withTiming(course.percentage, {
duration: 1000,
easing: Easing.out(Easing.ease),
});
}, [course.percentage]);

const animatedBarStyle = {
width: `${course.percentage}%` as `${number}%`,
};

return (
Comment thread .github/workflows/build-android.yml Outdated
Comment on lines +5 to +8
branches: [main, claude/review-deployment-readiness-3tEAH]
paths:
- 'native/**'
- '.github/workflows/build-android.yml'
Comment on lines +59 to +63
const [authState, setAuthState] = useState<AuthState>('loading');
// Keep a stable ref so the auth-state-change listener can read it without
// becoming a stale closure dependency.
const authStateRef = useRef<AuthState>('loading');

actions/cache and actions/upload-artifact do not have v5 releases yet,
so resolving them at parse time was failing the workflow silently
(no run appeared on the latest commit). Reverting just those two to v4
while keeping checkout/setup-node/setup-java on v5 (which is what was
actually flagged by the Node 20 deprecation warning).

Also guard the job summary step with `if: success()` and a file-exists
check so it doesn't crash when an earlier step fails.

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
CI:
- Revert all build-android.yml actions to @v4 (actions/setup-java@v5,
  cache@v5, upload-artifact@v5 do not have v5 tags yet, which caused
  the workflow to fail at parse time in 9s with no run logs).
- Add a pull_request trigger and drop the hard-coded feature-branch
  name from on.push.branches (per Copilot review).

Critical BLE fix:
- useBleScanner previously matched `peripheral.name === "Session-XXXX"`,
  but the broadcaster (after the type-fix earlier in this branch) no
  longer advertises a local name and instead encodes the token prefix
  as ASCII bytes in manufacturer data. That mismatch meant the scanner
  would never resolve `found: true`. The scanner now walks the raw
  `advertising.manufacturerData.bytes` array and looks for the
  contiguous token-prefix subsequence — aligning student-side discovery
  with what the lecturer is actually broadcasting.

Review-comment fixes (small, low-risk):
- toast.warning now maps to the "error" type so warnings are visually
  distinct from info; docstring explains how to wire a true "warning"
  renderer if needed.
- AttendanceLedgerScreen no longer hangs on the loading spinner when
  `sessionId` is undefined (history-tab use case) — it sets loading=false
  and renders the empty state.
- LiveSessionScreen presentCount now includes ATTENDANCE_STATUS.MANUAL
  so manual entries don't undercount lecturer stats.

Remaining Copilot review items deferred for follow-up (need more
context / are larger refactors): CourseSelectScreen department filter,
useAttendanceStats status filter, useLecturerData N+1 query,
AttendanceScoreboard dead Reanimated value, RootNavigator authStateRef.

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
The native workspace's lockfile was generated under --legacy-peer-deps
because react-native-screens@4.25.1 declares a peer dep on RN >= 0.82
while Expo 54 ships RN 0.81.5. Without this .npmrc, GitHub Actions'
strict `npm ci` aborts immediately with ERESOLVE — which is why the
Android build failed at ~14 seconds before reaching any real work.

A future cleanup would be to pin react-native-screens to Expo SDK 54's
recommended version (~4.4.x) and drop the override, but adding .npmrc
is the minimal change to get CI green now and keep local installs
consistent with package-lock.json.

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
Three runs in a row have failed at 30s with no visible logs through MCP.
Adding a Diagnostics step that prints node/npm versions and the resolved
`legacy-peer-deps` setting, plus `--verbose 2>&1 | tail -40` on
`npm ci`, so the next run's job output makes the failure point obvious.

Will revert once the underlying issue is identified.

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
Once `expo prebuild` has generated the native android/ and ios/
folders, the project is on the bare workflow and `expo start --android`
will not actually build/install the local native code. `expo run:*`
does the right thing.

(Side-effect of running prebuild locally during CI debugging — the
scripts were auto-updated by expo and are worth keeping.)

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
The TypeScript check in CI failed with:
  src/lib/utils.ts(1,39): error TS2307: Cannot find module 'clsx'
  src/lib/utils.ts(2,25): error TS2307: Cannot find module 'tailwind-merge'

These are used by the `cn()` helper but were never added to the
native workspace's package.json (carried over from the web project
without their deps). Local installs picked them up via npm's lookup
through the parent web project; CI's `npm ci` runs in isolation and
strictly enforces the lockfile, so the missing deps surfaced.

Also reverts the diagnostic step / verbose npm ci added in 1d4c1d2 —
no longer needed now that the failure is pinpointed.

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
Gradle failed at react-native-reanimated/android/build.gradle:310 with
a Groovy script error. Root cause: we had 4.3.1 installed, but Expo 54's
bundledNativeModules.json specifies ~4.1.1. The patch release bump
introduced a Gradle-script regression incompatible with the AGP version
expo prebuild generates.

Pinning to ~4.1.1 so we stay on the Expo 54 tested version.

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
…ch req)

reanimated v4.x has two hard requirements that don't fit our setup:

1. Gradle build.gradle has an `assertNewArchitectureEnabledTask` that
   fails the build unless `newArchEnabled=true`. Our app.json explicitly
   opts out of the new architecture because several deps in this app
   (BLE manager/advertiser, etc.) haven't been validated under Fabric.

2. v4 split the worklets runtime into a separate `react-native-worklets`
   package, which isn't installed. Its build.gradle calls
   `node ./../scripts/validate-worklets-build.js` which exits 1 when the
   package isn't there — that's the actual error we were seeing.

v3.16 keeps worklets in-tree, supports both architectures, and works
with RN 0.81. Our reanimated usage (shared values, useAnimatedStyle,
withTiming/withSpring) is unchanged between v3 and v4, so no source
changes are needed — `tsc --noEmit` and `expo prebuild` both pass.

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
Full diff against bundledNativeModules.json — all packages were ahead
of Expo 54's tested/pinned versions, which caused Gradle to fail during
dependency resolution for :react-native-async-storage_async-storage
(v3.0.3 → needs KSP/Kotlin ≥2.1 which wasn't present; Expo wants 2.2.0).

Packages downgraded to Expo 54 recommendations:
  @react-native-async-storage/async-storage  3.0.3  → 2.2.0
  expo-blur                                  55.0.x → 15.0.8
  expo-camera                                55.0.x → 17.0.10
  expo-device                                55.0.x → 8.0.10
  expo-haptics                               55.0.x → 15.0.8
  expo-location                              55.1.x → 19.0.8
  expo-secure-store                          55.0.x → 15.0.8
  react-native-gesture-handler               2.31.x → 2.28.0
  react-native-screens                       4.25.x → 4.16.0
  react-native-safe-area-context             5.8.x  → 5.6.0
  react-native-svg                           15.15.x→ 15.12.1

react-native-reanimated stays at ~3.16.0 (v4.x requires newArchEnabled
which we keep disabled due to BLE libs not being validated on Fabric).

tsc --noEmit and expo prebuild both pass after the downgrade.

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
- Add web bundling deps: react-native-web, react-dom, @expo/metro-runtime
- Pin babel-preset-expo to ~54.0.10 (matches Expo SDK 54) and add
  babel-plugin-module-resolver as a devDep (was implicitly required by
  babel.config.js but missing — could break native builds too)
- Add react-native-worklets (required by nativewind v4's babel preset)
- Move nativewind/babel to presets[] (was incorrectly in plugins[])
- Add .web.ts/.web.tsx to module-resolver extensions
- Stub BLE modules for web (lib/ble.web.ts, hooks/useBleScanner.web.ts)
  so the bundler doesn't pull native-only packages on web
- Add web-only RootNavigator.web.tsx that bypasses Supabase auth and
  exposes every screen at a URL path for headless screenshotting

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
The previous commit added react-native-worklets as a babel plugin
dependency for nativewind/babel preset. But worklets ships its own
Android native module (build.gradle + CMakeLists.txt + codegenConfig),
so Expo autolinks it during prebuild → Gradle tries to build it →
conflicts with the pinned reanimated v3.16.

Drop nativewind/babel from the babel preset chain entirely —
babel-preset-expo with { jsxImportSource: "nativewind" } already
provides the NativeWind transform. Verified web export still works
(4.04 MB bundle) and tsc --noEmit is clean.

https://claude.ai/code/session_013FrbpAh4Sg7nG88Y62p3yE
@King-Austin
King-Austin merged commit 94ffb0e into main May 27, 2026
2 of 3 checks passed
@King-Austin
King-Austin deleted the claude/review-deployment-readiness-3tEAH branch August 15, 2026 22:25

This branch was successfully deployed

1 active deployment
Preview 8d27227a Deployed May 27, 2026 by vercel[bot]
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.

3 participants