illiniSpots is a web application that helps UIUC students find available study spaces and classrooms across campus. The app shows live building availability on an interactive map and provides detailed room status information.
- Interactive map and list: Visualize building availability or browse a searchable list.
- Real-time and time travel: check now or any date/time.
- Coverage: Academic classrooms and reservable library study rooms (Grainger, Funk ACES, Main Library).
- Room details:
- Academic Rooms: See current/next class or event, availability duration, and view the full daily schedule (classes + events) for the selected date.
- Library Rooms: View reservation timelines, direct reservation links, and room photos (where available).
- PWA: install on your phone as an app for quick access.
Need help? See this guide on installing PWAs. - Search and filters: find buildings and libraries fast.
- Combines official class schedules with daily university event data to determine whether a room is in use at a specific date/time.
- Academic rooms: a room is unavailable if any class or daily event overlaps the selected time; otherwise it’s available. Availability ends at the earliest of the next class/event or building close. Very short gaps (< ~30 minutes) are not surfaced as “available” to avoid unusable slivers.
- Library rooms: uses the UIUC LibCal reservation grid; a room is available if the current slot is free, and the duration lasts until the next booking or closing time.
- Time travel: daily events are included for past dates and for future dates up to 14 days ahead; for dates further in the future, only class schedules and building hours are used.
- Timezone: all times are evaluated in campus local time (America/Chicago), handling DST.
- Sources: class data from Course Explorer, daily events from the university Tableau feed, building hours from Facilities, and library reservations from LibCal (links below).
- Freshness: library reservations are read live; daily events are scraped and updated regularly via a cron job; class/building data is refreshed via the data pipeline.
- Deterministic rules: availability for academic rooms is computed in SQL (
get_spotsmigration), using only official schedules + events and building hours. - Known limitations:
- Unofficial use (study groups, ad‑hoc meetings) and last‑minute changes may not be reflected.
- Departmental access restrictions can make an “available” room unusable.
- Special schedules (exams/holidays), maintenance closures, or data source outages can reduce accuracy.
- Short “micro‑gaps” are intentionally filtered out (< ~30 minutes) to avoid noise.
- Future dates exclude daily events; academic availability for future times uses class schedules + building hours only (events are only available per-day as they are published).
- Class data: Course Explorer. See the data flow in
data-pipeline/README.MD. - Daily events: Tableau Daily Event Summary.
- Building hours: Facility Scheduling and Resources.
- Library reservations: UIUC LibCal.
- Frontend: React 19, Vite 8, TanStack Router, TanStack Query, TypeScript, Tailwind CSS, shadcn/ui, and Mapbox.
- Backend: Hono on Bun, Supabase (PostgreSQL), and SQL functions (
database/functions). - Analytics: PostHog for browser usage analytics.
- Observability: Sentry for the React client, Bun server, API dependencies, and scheduled data pipelines.
The Vite client and Hono API live in one package and are deployed as one same-origin application:
src/client/ React entrypoint, providers, routes, and browser telemetry
src/server/routes/ HTTP validation and response contracts
src/server/services/ availability, Supabase, and LibCal domain services
src/components/ shared React UI
src/types/ shared API and UI types
During development Vite runs on port 5173 and proxies /api/* to Hono on port
3000. In production Hono serves the built Vite assets and the API from the same
port. The two public data endpoints remain /api/facilities and
/api/room-schedule.
- Bun 1.4+
- Supabase project (PostgreSQL)
- Install dependencies
git clone https://github.com/plon/illinispots
cd illinispots
bun install- Supabase database
- Create a database (e.g., via Supabase).
- Link the project with
bunx supabase link --project-ref <project-ref>. - Apply the versioned schema and security policies with
bunx supabase db push. - The files under
database/remain readable references for the current tables and functions;supabase/migrationsis the deployment source of truth.
- Environment
Copy .env.example to .env.local and configure:
SUPABASE_URL=your_supabase_url
SUPABASE_PUBLISHABLE_KEY=your_supabase_anon_publishable_key
VITE_MAPBOX_ACCESS_TOKEN=your_public_mapbox_token
VITE_MAPBOX_STYLE_URL=mapbox://styles/<user>/<style-id>PostHog analytics and Sentry observability are optional. To enable them, add the relevant variables:
VITE_PUBLIC_POSTHOG_PROJECT_TOKEN=your_posthog_project_token
VITE_PUBLIC_POSTHOG_HOST=https://your-posthog-host
SENTRY_DSN=your_sentry_dsn
VITE_SENTRY_DSN=your_sentry_dsn
SENTRY_AUTH_TOKEN=your_sentry_auth_tokenSUPABASE_PUBLISHABLE_KEY is used by the Hono server for read-only database queries. In local development, Mapbox, PostHog, and Sentry configuration is read from .env (VITE_*). In production/staging, the server injects configuration at runtime from environment variables / Fly secrets. SENTRY_AUTH_TOKEN is only needed to upload source maps during a production build. Writing pipeline scrapers (data-pipeline/) use SUPABASE_SECRET_KEY (service role).
- Run locally
bun run devOpen http://localhost:5173. Hono continues to listen on http://localhost:3000 for direct API access.
bun run checkThis runs ESLint, Bun's route and service tests, the Vite production build, and TypeScript validation.
The application runs as a long-lived Bun server in Docker containers on
Fly.io Machines. Hono serves both the Vite
production build and /api/* from port 3000, keeping the frontend and API on
the same origin.
Production uses fly.toml, and staging uses
fly.staging.toml. Both environments use rolling deploys
and health checks against /api/health; production keeps at least two Machines
running. Pushes to main deploy production through GitHub Actions. Pull
requests deploy to staging when labeled deploy:staging.
The Hono API can also run as a Vercel Function using the serverless entrypoint
at api/[...route].ts.
Configure the production and staging environment variables shown above as Fly
secrets, then deploy with flyctl:
flyctl deploy --config fly.toml
flyctl deploy --config fly.staging.tomlTo run the production server locally without Docker:
bun run build
bun run startOr use the same Docker image deployed to Fly:
docker build -t illinispots .
docker run --env-file .env.local -p 3000:3000 illinispotsFor collecting and loading source data, see data-pipeline/README.MD for Python setup, script order, and outputs (including the daily events job).
MIT — see LICENSE.