Skip to content

ezrakoreen/Timely

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Timely

Timely is a Cornell-focused mobile app and backend that figures out when you should leave for your next event, based on your Google Calendar, your latest location, and how fast you actually walk.

The repo contains:

  • frontend/: an Expo Router React Native app
  • backend/: an Express + Prisma API with reminder scheduling, calendar sync, place resolution, and route-learning logic

What Timely does

Timely is built around a simple flow:

  1. A user signs in with a Cornell Google account through Supabase Auth.
  2. The app syncs upcoming Google Calendar events and stores the user's Google Calendar connection on the backend.
  3. Event locations are resolved against a Cornell place dataset.
  4. The backend estimates a walking route and computes a leave time using:
    • the event start time
    • the user's latest location or saved campus home
    • a configurable reminder buffer
    • a learned walking speed factor
  5. A background reminder worker checks for due sessions every minute and sends Expo push notifications.
  6. Completed walks are stored as tracks and used to update route-specific and global walking speed models.

If a Google Maps API key is available, route estimation uses Google Routes API. If not, the backend falls back to a distance-based estimate.

Current product surface

The mobile app currently includes:

  • Google sign-in restricted to @cornell.edu users
  • Home screen with the next leave time and next event
  • Calendar sync controls
  • Device permission/bootstrap flow for push and location
  • Route analytics based on repeated walks
  • Daily path history shown on a map
  • Basic profile settings like buffer minutes

The backend currently includes:

  • Supabase JWT verification for protected API routes
  • Prisma models for users, devices, calendar connections, events, location pings, walk sessions, walk tracks, and route stats
  • Google Calendar sync for visible calendars
  • Cornell place seeding on server boot
  • Walk-session recomputation when profile or location changes
  • Push reminder processing on a fixed interval

Tech stack

  • Frontend: Expo, React Native, Expo Router, Supabase JS, react-native-maps
  • Backend: Node.js, Express, Prisma, PostgreSQL, Zod, JOSE
  • Auth: Supabase Auth with Google OAuth
  • Mapping/routing: Google Routes API when configured
  • Notifications: Expo push tokens stored on the backend

Repository layout

.
├── backend/
│   ├── prisma/               # Prisma schema and migrations
│   └── src/
│       ├── routes/           # Express API routes
│       ├── services/         # Calendar sync, routing, reminders, speed model
│       ├── middleware/       # Auth, validation, error handling
│       └── constants/        # Seed data, including Cornell places
├── frontend/
│   ├── app/                  # Expo Router screens
│   ├── src/context/          # Auth context
│   ├── src/hooks/            # App data fetching hooks
│   ├── src/services/         # API client and native bootstrap
│   └── assets/
└── README.md

Prerequisites

You will need:

  • PostgreSQL
  • A Supabase project with Google auth enabled
  • A Google OAuth client for the Expo app
  • Optionally, a Google Maps API key for better route estimates
  • Expo tooling for running the mobile app

Environment variables

Backend

Create backend/.env with:

NODE_ENV=development
PORT=4000
DATABASE_URL=postgresql://...
DIRECT_URL=postgresql://...
SUPABASE_PROJECT_ID=your-supabase-project-id
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_PUBLISHABLE_KEY=your-supabase-publishable-key
FRONTEND_ORIGIN=http://localhost:8081
GOOGLE_MAPS_API_KEY=your-google-maps-api-key
GOOGLE_OAUTH_CLIENT_ID=your-google-oauth-client-id
GOOGLE_OAUTH_CLIENT_SECRET=your-google-oauth-client-secret

Notes:

  • DATABASE_URL is required.
  • DIRECT_URL is optional.
  • GOOGLE_MAPS_API_KEY is optional, but without it Timely uses a fallback walking estimate.
  • FRONTEND_ORIGIN only matters for production-style CORS restrictions.

Frontend

Copy frontend/.env.example to frontend/.env and fill in the values:

EXPO_PUBLIC_BACKEND_URL=http://localhost:4000
EXPO_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
EXPO_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your-supabase-publishable-key
EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID=your-google-web-client-id.apps.googleusercontent.com

If you want Expo push token registration to work in development builds, also provide:

EXPO_PUBLIC_EAS_PROJECT_ID=your-eas-project-id

Local development

1. Install dependencies

Backend:

cd backend
pnpm install

Frontend:

cd frontend
npm install

Notes:

  • The repo has a root pnpm-workspace.yaml, but it currently only includes backend.
  • The frontend also has its own package-lock.json, so the safest local path today is to install it from frontend/.

2. Run database migrations

From backend/:

pnpm exec prisma migrate deploy

For local schema iteration, you can use:

pnpm exec prisma migrate dev

3. Start the backend

From backend/:

pnpm dev

The API starts on http://localhost:4000 by default. On boot, it seeds Cornell places and starts the reminder worker.

4. Start the mobile app

From frontend/:

npm start

You can also use:

npm run ios
npm run android
npm run web

Backend API overview

Most API routes are protected and require a Supabase bearer token.

Key routes:

  • GET /health
  • GET /api/user-profile/me
  • PATCH /api/user-profile/me
  • GET /api/calendar/connection
  • POST /api/calendar/connection
  • POST /api/calendar/sync
  • GET /api/events/upcoming
  • POST /api/routes/estimate
  • POST /api/location-pings
  • GET /api/walk-sessions/upcoming
  • POST /api/walk-sessions/:id/complete
  • GET /api/history/daily?date=YYYY-MM-DD
  • GET /api/route-stats
  • GET /api/places?q=...

Data model summary

Important Prisma models:

  • UserProfile: user preferences, permissions, home location, and global speed factor
  • CalendarConnection: stored Google Calendar tokens and sync status
  • CalendarEvent: normalized upcoming events with resolved Cornell destinations
  • LocationPing: recent user coordinates used for leave-time computation
  • WalkSession: scheduled leave reminders for specific events
  • WalkTrack: completed walks with route geometry and actual duration
  • RouteStat: learned per-route walking speed adjustments
  • UserDevice: Expo push tokens for reminders

Development notes

  • The frontend only permits Cornell users. Non-@cornell.edu accounts are signed out after Google auth.
  • Route learning blends a user's global speed factor with route-specific history once enough samples exist.
  • Reminder delivery is server-driven, not local-only. The backend checks for due reminders every 60 seconds.
  • Event syncing currently focuses on visible Google calendars over roughly the next 48 hours.

Gaps and cleanup worth tackling

  • Add committed backend and root .env.example files
  • Unify package management across the repo instead of splitting pnpm and npm
  • Add tests for calendar sync, route estimation, and reminder scheduling
  • Document Expo native configuration for notifications and location more fully
  • Add deployment instructions for Supabase, Postgres, and the backend

About

Cornell-focused mobile app that tells you when you should leave for your next event based on your Google Calendar, your latest location, and how fast you actually walk.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors