terminus is a free, independent student project. It keeps only what it needs to tell you which bus to catch, and you can delete all of it yourself at any time.
What is stored
- Your account: when it was made and last used, and whether it started in an app or on the website.
- Your email address, if you give one, to send sign-in codes and links and to tell you when a device is added to your account. No password is ever stored.
- Your timetable: each class's day, time, venue and nearest bus stop, the classes you add yourself, and the NUSMods share link you imported.
- Your settings: home stops (stop names only, never your address or coordinates), the minutes it takes you to walk to them, your walking pace, favourites, the places you save with the names you give them, usual times (for example the gym on Tuesday evenings), one-off trips, your gap and day-hours preferences, whether to include public buses, your clock and language, and which one-time setup screens you have seen.
- How full buses are, in total: when a bus is about to reach a stop someone asked about, terminus adds one to a count of how often that service is busy at that stop, by kind of day and half hour. The count has no link to you or your request; the bus's plate number is kept for two days only so the same bus is not counted twice.
- Today's trip: for each of today's trips, the class it's for, which bus to catch (the service, the stops and the times) and what happened to it: that you're not going, or, when the location the app sends puts you at your destination, that you've arrived. terminus doesn't ask you. It is kept for the rest of the day so your other devices show the same thing, then deleted at midnight, or straight away if you delete your account. Only that you've arrived is kept, never the location. When you say you're on the bus, the bus's plate number is kept with the rest of the day, to read its arrival at your stop from NUS's feed (or LTA's, for a public bus).
- How each trip went: for 35 days, one word per trip per day: on the bus, missed it, not going, or arrived. It is kept with the trip it was about (the class's day, time and stop, or the trip home) and the date, never the time it happened or a location. It is what suggests leaving a bus earlier for a class you often miss, or stopping reminders for one you keep skipping. What you choose there is kept, with the class's name, until you change it.
- Reports you send: when you tell terminus an answer was wrong, or send feedback, your note and the answer you were looking at (which can name the stop nearest you) are kept with your account for a year, to check against what the buses did. The note is also emailed to the person who runs terminus, without your email address or the answer.
- Your devices: the name each paired device reported (its model, for example "Google Pixel 8" or "MacBook Pro"; a Mac set up with a version before 2.5.0 sent the computer's own name, which stays until you remove that device or delete the account), which app and app version it runs, when it was added and when it was last used, and, for a device that takes notifications, its push address: a Firebase address for the Android app, or for the web app the address your browser's push service gave it (Apple's, Google's, Microsoft's or Mozilla's) and the keys to encrypt for it. Sign-in and device tokens are stored only as one-way hashes. A pairing code is kept as it is for the 10 minutes it works.
- API keys you make: each key's name, its last four characters, and when it was made and last used. The key itself is stored only as a one-way hash.
Using terminus without an email
The Android and Mac apps and the website work without an email address. When you start without one, terminus creates an account with no email, known only to that phone, Mac or browser, and stores the same things as above for it: your timetable, settings, the device's name, and when it was last used. Nothing identifies you unless you add an email later, which keeps your setup and lets you sign in on other devices. On the website, the account is reached through that browser's sign-in cookie: if the browser's data is cleared, or it isn't used for 30 days, there is no way back into it.
An account without an email is deleted, with everything in it, 60 days after it was last used. You can also delete it straight away from the app's settings or the account page. Uninstalling the app doesn't delete it; it is then unused, and deleted after 60 days.
When you sign in from an app, terminus keeps a short-lived request (your email address, the device's name and platform, and when it was made) until you approve it from the email, or for 15 minutes.
What is not stored
- Your location. When the app sends your location to find the nearest stop, terminus rounds it to about 11 metres, whichever app or script sent it, uses it for that one answer and doesn't save it. The same answer also checks whether you are inside an on-campus residence that your home stops serve, so it doesn't send you home when you're already there; which residence is never stored. It travels in the request's address, and terminus's own request logs are switched off; Cloudflare, which carries every request, processes it only to deliver it. Today's plan, worked out from it, is kept in Cloudflare's cache for up to a minute so that looking again is quick; it can't be removed sooner, even by deleting your account.
- Where you are on the map. The dot on the campus map is drawn by your device from its own location, and only when you have already allowed location. It is not sent to terminus.
- No ads, no cookies beyond the one that keeps you signed in and one that remembers the language you chose on the website (for a year, or until you choose again), and nothing that follows you across sites. The website also keeps your theme, clock and card style, and the places you searched for in the web app, in your browser only; signing out or deleting your account removes the places. The website counts page visits with Cloudflare Web Analytics (see below), which sets no cookies and doesn't identify you.
To tune its estimates, terminus records anonymous statistics about answers: which stop (when the app sent your location, the one nearest you), where the trip was going, the walk to the stop, which service and bus (its plate), and how long until it came. These carry no account, email or coordinates, but with the time they say roughly where someone was and where they were going. Cloudflare keeps them for three months.
When something goes wrong on the server, it logs which page or request failed, without your location or anything you sent; Cloudflare keeps those logs for a few days.
terminus records where NUS's own shuttle buses are through the day (each bus's plate and position, every 30 seconds) so a day can be replayed on the map. It holds nothing about you, and is kept.
If you ask not to be emailed again, that address goes on a blocklist so sign-in emails are never sent to it. The blocklist is not tied to an account and is kept after an account is deleted, so the address still gets no email.
Who handles it
Everything runs on Cloudflare (hosting, database, email delivery) in data centres that may be outside Singapore. Bus times come from NUS's shuttle feed and, if you turn on public buses, from LTA's DataMall; they are asked only about stops, and receive nothing about you. Reports are emailed to a mailbox the person who runs terminus keeps. Your data is never sold or shared.
Some pages load things from other services, which see your IP address like any website you visit:
- Cloudflare Turnstile on the sign-in form, to check you're a person. terminus passes your IP address to it for the same check.
- cdnjs (Cloudflare) for the QR code library on the account page.
- unpkg for the API documentation page only.
- Cloudflare Web Analytics on the website, to count visits: which page, how long it took to load, and the browser, device type and country. It uses no cookies or other stored identifiers, and doesn't link visits to you or your account. The apps don't use it.
On Android phones with Google Play services, terminus uses Firebase Cloud Messaging (Google) to tell the app your trip has changed, so it doesn't have to keep checking. To receive messages, the app registers with Firebase once it has an account, with or without an email, which gives Google an installation ID and a push token for the app on that phone. A message says only that the trip changed, and which phase it is in (for example "time to go"), or that a new semester's reminder is waiting; the app then asks terminus for the details itself. (Versions before 2.5.0 are sent the semester reminder's words, which are the same for everyone.)
If you turn on notifications in the web app, the same message goes through your browser's own push service (Apple's for Safari, Google's for Chrome, Microsoft's for Edge, Mozilla's for Firefox), encrypted so that only your browser can read it. Your browser then asks terminus for the details and shows the notification. Turning notifications off in the web app, or signing out there, removes the address.
When you import a timetable, terminus asks NUSMods for the timetables of the modules in your link. It sends module codes only, nothing about you.
Walking times follow footpaths from OpenStreetMap (map data © OpenStreetMap contributors), with room positions from NUSMods. Both were downloaded once to work out distances; nothing about you is ever sent to either.
The campus map's streets come from Protomaps' build of OpenStreetMap, the bus route lines from OpenStreetMap's roads. terminus keeps its own copy and serves it from this site, so no map company sees where you look. Walking directions on a stop opens Apple Maps on Apple devices, and Google Maps elsewhere, with that stop's position, only when you tap it; from there their own privacy terms apply.
How long it is kept
- Until you delete your account, which removes it, and everything above that is kept with it, immediately. What isn't tied to your account stays: the counts and statistics, the blocklist, a report's note in the operator's mailbox, and today's plan in Cloudflare's cache for up to a minute.
- Sign-in links and requests expire after 15 minutes, and pairing codes after 10. A browser session ends 30 days after it was last used, and at most 180 days after you signed in for an account with an email. Paired devices are signed out after 90 days without use.
- Accounts without an email are deleted 60 days after they were last used.
- Reports are deleted after a year.
- How each trip went is kept 35 days. Clear trip history (in the app's settings, or on the account page) deletes it sooner without touching the rest of your account; today's trip still goes at midnight.
Your controls
On the account page you can see and edit everything above, download it all as a file (today's trip included), sign out every device, or delete your account. The apps can see and remove your devices too. An account with an email is deleted from the account page. An account without an email is managed from its app, or on the website from the account page in that browser; either can export or delete it.
Contact
Questions or requests about your data under Singapore's Personal Data Protection Act: privacy@rcn.sh.