For other campuses
Fork this for your campus
Room TBA is built for UPLB. The license (MIT) lets you fork it. This is not a "swap the logo and ship" kind of fork. A lot of the app is UPLB data and UPLB-specific glue. Here is what you actually replace, in the order that matters, with the real file paths.
· Last edited July 27, 2026 · 9 revisions · History · Edit on GitHub
What you keep
The engine is generic. You do not rewrite these:
- The map UI, search bar, side panel, and pin flyouts.
- PGlite offline cache (the app answers "where is this room" with no signal).
- The editor and the suggest-an-edit review queue.
- The course planner and the personal-schedule routing.
- Events on the map, alias synonym matching, share links.
- The Drizzle schema. Tables for
buildings,rooms,classes,aliases,events,organizations,places,colleges,dorms,jeepney_routes, and final exams are campus-shaped, not UPLB-shaped.
What is UPLB-only (you rip this out or replace it)
| File / thing | Why it is UPLB-only |
|---|---|
src/lib/site.ts | Site name, URL, title, and description are UPLB. |
src/constants/map-terrain.ts | Map bounds, default camera (center lng/lat, zoom, pitch), and the Mt. Makiling terrain source. |
src/constants/community-links.ts + status-bar-links.ts | UPLB Tools, Discord, and Messenger links. |
public/room_info.json | UPLB buildings, aliases, and walking directions. Seed file for aliases. |
src/constants/jeepney-routes.ts + jeepney-geometries.json | UPLB jeepney routes. Delete if your campus has no equivalent. |
scripts/import-amis-classes.ts | AMIS is UPLB's course system. You do not have AMIS. |
scripts/import-final-exams.ts | Reads UPLB OUR finals JSON. |
scripts/import-osa-orgs.ts + import-campus-offices.ts | UPLB org and office directories. |
astro.config.mjs site | Hardcoded to room-tba.uplb.tools. |
| The database contents | Every row is UPLB. The schema stays; the data goes. |
If a fork only changes the logo and the site name, it is still a UPLB app pointing at UPLB data. That is the thing the license line in the README is warning you about.
What you need before you start
- A GitHub account (to fork).
- Bun 1.3+ on your machine.
- A Supabase project. Free tier is fine for a small campus.
- A MapTiler key for vector and terrain tiles. Free tier exists; watch the quota.
- Your campus data: a building list with coordinates, room codes, class schedules from your registrar or SAIS equivalent, and a final-exam schedule if you want that panel.
- Somewhere to deploy. Vercel free tier works; the app is built for the Vercel adapter.
The actual steps
1. Fork and clone
Fork uplbtools/room-tba on GitHub, then:
git clone https://github.com/<your-org>/room-tba.git
cd room-tba
cp .env.example .env.local
2. Make a Supabase project and grab the URL
Create a project. In SQL settings, copy the session pooler
connection string (the one ending in *.pooler.supabase.com).
Paste it as DATABASE_URL in .env.local. Set
ADMIN_PASSWORD to something long and random — you need it
to log into the editor.
3. Install and create the tables
bun install
bunx drizzle-kit push
drizzle-kit push creates every table from
drizzle/schema.ts in your Supabase Postgres. You start
with an empty campus.
4. Edit src/campus.config.ts — the single config file
This is the one file for campus-specific config. It holds the site
name, URL, title, description, the map center / bounds / camera, and
the community links. The rest of the app
(site.ts, map-terrain.ts,
community-links.ts, astro.config.mjs) imports
from here. Change the values, save, and you are done with the code-side
rebrand.
campusSite—url,name,title,description.campusMap—maxBounds(the lng/lat box that keeps the camera on your campus) anddefaultCamera(center: [lng, lat],zoom,pitch,bearing).campusCommunity— your org, GitHub, Discord, and Messenger links. Delete entries you do not have.
If your campus has no hill like Mt. Makiling, also disable the terrain
source in src/constants/map-terrain.ts
(TERRAIN_SOURCE_ID, getTerrainTileJsonUrl).
The 3D toggle just turns off. The terrain IDs are not in
campus.config.ts yet — they are a follow-up.
5. Delete or replace the UPLB data files
- Replace
public/room_info.jsonwith your buildings (or delete it and seed the DB directly). - Delete
src/constants/jeepney-routes.tsandjeepney-geometries.jsonif you have no campus transit overlay. - Delete the UPLB import scripts you cannot reuse:
import-amis-classes.ts,import-final-exams.ts,import-osa-orgs.ts,import-campus-offices.ts. Keep them as reference while you write your own. - Delete
src/pages/wiki/section-times.astro(the UPLB section-code glossary) and its card on the wiki index.
6. Start the dev server
bun dev
Open http://localhost:4321. The map loads with your new
center and bounds. Nothing is on it yet because the DB is empty.
7. Run fork:check to catch what you missed
bun run fork:check
Scans the repo for hardcoded UPLB strings you forgot to replace
(uplb, uplbtools.me, AMIS,
Makiling, PSLH, the UPLB map center coords,
Messenger invites, …). Reports file:line hits with hints. On a finished
fork it should report zero. Wire it into your fork's CI
(--silent for exit-code-only) so a stray UPLB string does
not sneak back in on a merge from upstream.
Loading your own data
Two ways. Use both.
The in-app editor. Log in at
/?editor=login with your ADMIN_PASSWORD. Drop
pins, add buildings and rooms, set aliases. This is how you fix data
day-to-day and how volunteers contribute without touching the DB.
A seed script. For a first bulk load (every building,
every room, every class), write a script that reads your registrar's
export and upserts into Postgres. Use
scripts/import-amis-classes.ts as a template for the
shape — Drizzle upsert by natural key, term handling, the
class/room join — not the AMIS fetch. Your data source is different.
The import scripts read from files under data/ (gitignored)
and write to DATABASE_URL; copy that pattern.
Class schedules are the hard part. Room TBA pulls from AMIS, which is
UPLB's system. You do not have AMIS. You need whatever export your
registrar or SAIS equivalent gives you — CSV, JSON, a scraped portal,
a PDF someone has to retype. Write one importer for it, point it at the
classes table, and rerun it each term.
After you change the Drizzle schema at all, regenerate the offline cache schema so PGlite matches Postgres:
bun run generate:pglite-schema
Deploy
Import your fork into Vercel. Set these env vars in the project (Production and Preview):
DATABASE_URL— your Supabase pooler URL.ADMIN_PASSWORD— same one you used locally.ADMIN_SESSION_SECRET— 32+ random chars, used to sign editor cookies.ISR_BYPASS_TOKEN— 32+ random chars, must matchbypassTokeninastro.config.mjs. Without it, editor publishes do not revalidate the SEO pages.PUBLIC_MAPTILER_KEY— your key.PUBLIC_APP_ENV=productionon your production deploy;stagingon preview.
Deploy. Push to your default branch and Vercel builds it. The build
needs DATABASE_URL or prerendered pages 500.
The painful parts
- Class import is write-your-own. AMIS is UPLB-only. Your registrar's export is the long pole. Budget time for it.
- Map tiles cost money at scale. MapTiler free tier is fine for a campus with a few thousand users. If the whole student body hits it during enrollment, you may need a paid plan or a self-hosted tile server.
- The 3D terrain needs a DEM. If your campus is flat, just disable the terrain source. No DEM, no 3D hills.
- Supabase free tier pauses after a week of no activity. Fine for a small campus. For high traffic, upgrade or self-host Postgres.
- You are maintaining a fork. Upstream moves. Rebase pain is real. Keep your campus-specific changes in the clearly UPLB-marked files above so merges do not stomp your data config.
- The wiki page you are reading is UPLB-specific too. Replace it with your own campus guide, or delete it.
License and credit
MIT. Keep the LICENSE file. You can run a fork for your
campus, sell hosting around it, teach with it. You do not have to ask.
Credit is free. The README credits the people who built this. Do not
strip those names and pass the work off as yours. If your fork takes
off, a line back to uplbtools/room-tba is good manners.