Search for a bus line and instantly display busses from SL, Storstockholms Lokaltrafik π
Min Buss.nu
is a Next.js application that show real-time bus information from SL (Storstockholms Lokaltrafik). It uses both static GTFS data and real-time GTFS-RT data from Trafiklab. The data is rendered on a map from Google Maps.
To get started with Min Buss.nu
, you will need to apply for for two API-keys from Trafiklab. You can get started immediately by following the guide on Trafiklab. For this project you will need one key for GTFS Regional Realtime
and one key for GTFS Regional Static Data
. Since we will ask for real-time data quite frequently, you will also need to upgrade the quota for GTFS Regional Realtime to silver.
Next, you need to apply for a key from Google for the Maps Javascript API.
To serve the data, you will need a PostgreSQL-compatible database. This project uses Vercel Postgres, a serverless and scalable solution from Neon, but you can choose any database you prefer.
Currently, database migrations are not set up, so some manual steps are required:
Steps:
Create the following five tables:
- routes
- stop_times
- stops
- trips
- calendar_dates
You can find the required table structures and data types in the SQL schema files located in the /schema directory of this project. Use these files to create the tables in your database. You can also have a look at the UML diagram below.
Download the GTFS Regional Static Data from Trafiklab and unzip the file to access the .txt files.
Use a database tool like DBeaver or a SQL command-line tool to import the text files into the corresponding tables.
In the root of the project, create a file named .env.local. This file will store your environment variables for local development.
Place all your environment variables inside this file. For example:
NEXT_PUBLIC_GOOGLE_MAPS_API_KEY=your-google-maps-api-key
DATABASE_URL=your-database-url
Environment variables prefixed with NEXT_PUBLIC are exposed to the client-side code in Next.js. Since Google Maps runs on the client, its API key must be prefixed NEXT_PUBLIC to make it accessible in the browser.
Ensure .env.local is listed in your .gitignore file to prevent sensitive data from being committed to your repository.
git clone https://github.com/StyleSensei/degree-project-where-is-the-bus.git && cd where-is-the-bus && npm install
First, run the development server:
npm run dev
Open http://localhost:3000 with your browser to see the result.
Tech stack
- Next.js (with App directory): Used for server-side-rendering, routing, and API handling.
- TypeScript: Types! For improved developer experience.
- Sass: Provides advanced CSS features like variables, mixins, and nesting for maintainable and scalable styling.
- Axios: Used for making HTTP requests to fetch real-time bus data and static GTFS files.
- Vercel Postgres: Serverless PostgreSQL database for scalability and easy integration
- Drizzle ORM: For type-safe SQL queries.
- Upstash Redis β Used to avoid unnecessary API calls and improve performance. We cache both real-time data from Trafiklab and static data from the database.
- GTFS-realtime Language Bindings: For parsing the protobuf format into JavaScript objects.
- Unzipper: allow access to the underlying files of the zip-archive we get from Trafiklab's
GTFS Regional Static Data
API.
- Csv parser converts the unzipped csv/txt-files into JSON.
- Zod & Drizzle-Zod: Allows us to generate Zod schemas from Drizzle ORM schemas and enable validation during runtime.
- Biome: Ensures consistent code quality with built-in formatting and linting.
- Google Maps Javascript API: For map visualization.
- @vis.gl/react-google-maps: React integration for efficient map rendering.
- GSAP: for smooth movement of the bus markers.
- GTFS-RT: For real-time bus position updates.
- Static GTFS data: Used for mapping and bus route metadata.
- Vercel: For seamless deployment and serverless infrastructure.
To ensure the static GTFS data remains up-to-date, a GitHub Actions workflow runs the GTFS update script once a month. Trafiklab updates the static data infrequently, so this monthly update is sufficient.
- This project uses GitHub Actions to schedule and run the cron job. The workflow is configured to run monthly and execute the GTFS update script directly.
- You can find the workflow configuration in the
.github/workflows/cron-job.yml
file.
Example GitHub Actions Workflow
name: Run GTFS Update Cron Job
on:
schedule:
- cron: '0 3 1 * *' # Once a month at 03:00 UTC on the first day
workflow_dispatch: # Allow manual triggering from GitHub
jobs:
run-cron:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build cron job
run: npm run build:cron
- name: Run GTFS update script
run: NODE_PATH=./dist-cron node scripts/updateGTFSData.mjs
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
GTFS_REGIONAL_STATIC: ${{ secrets.GTFS_REGIONAL_STATIC }}
The GTFS Regional API documentation from Trafiklab was a key reference for understanding how to decode and use real-time transit data.
- Trafiklab - Overview
- Trafiklab - GTFS regional
- Trafiklab - Using Trafiklab data
- GTFS-realtime Language Bindings
- Google Maps API
- Drizzle ORM
- Biome
- Zod
- Axios
- Upstash Redis
- unzipper
- csv-parser
To learn more about Next.js, take a look at the following resources:
- Next.js Documentation - learn about Next.js features and API.
- Learn Next.js - an interactive Next.js tutorial.
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out Next.js deployment documentation for more details.
Got questions? Reach out!
- Email: [email protected]
- GitHub: @StyleSensei
- Linkedin: https://www.linkedin.com/in/patrikarell/