Skip to content

Infrastructure and Tools

Nirav Patel edited this page Apr 12, 2026 · 19 revisions

For each library, framework, database, tool, etc

Research Scope

The stakeholder, Fares Turki, has a preference towards a web / browser based solution for this project. Adhering to this preference is expected to yield the following benefits:

  • Users don’t need to install software directly onto their computer
  • Updates to the software can be delivered much faster (no need to update)
  • Development speed is expected to be faster, given the team’s experience with web development over desktop app development
  • Users can use the tool without having a powerful enough computer to run the simulations locally
  • Most of BIXI’s internal tooling is already web based

The team decides to proceed with a web and browser based solution based on these advantages. Researching the most appropriate tech for this project is then guided by this decision.

Frontend

React Router v7 (Framework)

React Router Documentation

Modern web development generally involves the use of a JavaScript framework / library like React, Angular, Svelte, etc. Members of this capstone team have worked with different libraries, and React is the most common among them. React is also an industry standard, and its vast ecosystem is expected to facilitate the implementation of a relatively complex UI.

React is technically just a library. It’s un-opinionated and doesn’t itself provide solutions to common web application needs. It’s common to use a framework on top of React, like React Router, Next.js, or TanStack. React Router has been in the game the longest, and it remains the most popular choice for implementing routing in React apps. This sets the team up to build a large enterprise application.

ReactRouter’s biggest weaknesses (such as lack of SEO due to client-side rendering) have been addressed in React Router v7 (in which “framework” mode supports server-side rendering). Further, Next.js is particularly difficult to host within trapping one’s self in the Vercel ecosystem, largely due to the fact that a lot of Next.js features are platform (Vercel) features.

For these reasons, React Router v7 (framework mode) is selected as the framework of choice for this project.

References:

Tailwind CSS

Tailwind CSS Documentation

Both members of the frontend team have experience with Tailwind CSS. Their experience with Tailwind’s utility-first approach is that it facilitates development (styles are defined directly in React markup, which facilitates collaboration). Styling is easier to keep consistent across the application, and there’s less CSS bloat to manage manually.

Shadcn UI

Shadcn UI Documentation

A popular component library (although not technically a library) is shadcn/ui, which itself uses Tailwind for styling its components. These components provide very good starting-points for common UI elements. By default, they are styled to appear minimal and clean, which is in the realm of Mini Metro’s UI styling choices (Mini Metro being the game that the stakeholder offers as inspiration for the UI).

shadcn/ui’s approach to individual component downloads (as opposed to a massive npm package) means the team will only import the components they actually use. The “you own the code” paradigm that shadcn/ui employs makes it easier to adjust components to our liking. Despite the relative novelty of this component library, its extreme popularity suggests that it is battle-tested.

CodeMirror 6

CodeMirror Documentation

CodeMirror 6 is used as the editor component for the scenario JSON editor, where users define and modify simulation scenarios. The project integrates it through the @uiw/react-codemirror React wrapper, which provides a declarative API that aligns well with React’s component lifecycle and state management patterns.

CodeMirror 6 is a complete rewrite of version 5, offering improved performance, modularity, and mobile support. The @codemirror/lang-json extension enables native JSON syntax highlighting and validation, which is essential for editing structured scenario data. Its extension-based architecture allows granular control over features such as line wrapping, bracket matching, autocompletion, and code folding.

The scenario editor leverages CodeMirror’s support for both editable and read-only modes, enabling view-only scenarios when needed. Custom theming integrates smoothly with the Tailwind/shadcn design system to maintain visual consistency across the application.

References:

Vitest

Vitest Documentation

Although Jest is the most mature JavaScript testing library, Vitest seems to be the most modern and best choice for our needs. Vitest is easier to set up in the context of a project that already uses Vite, and Vitest has a Jest compatible API, which helps with adoptability. For typesafe tests, Jest would require us to set up a separate, dedicated TS-to-JS transpilation pipeline because it is not compatible with Vite. Jest’s own documentation references Vitest as a potential alternative if we wish to use Vite for transpilation. Vitest in a project that already uses Vite is then expected to be a much better developer experience. You’ll even find comments on blogs for setting up Jest in a TS React project that suggest simply using Vitest in 2025. The most recent reddit threads on the topic also heavily favor Vitest.

References:

From-Scratch State Management

State management libraries like Redux and Zustand are commonly employed in web apps, but their abstraction of state management is unlikely to fit our simulation use-case. For this reason, the frontend team opts to proceed with no state management library, and to instead handle state ourselves. The team is of course open to adopting a state management library if it finds itself in a position where it would greatly benefit from one.

Mapbox GL JS

Mapbox GL JS documentation

The map-based nature of simulations, paired with the fact that the network we’re attempting to simulate is based in the real world, practically requires us to use a map provider like Google Maps or Mapbox. Based on the team's prior experience with both map providers, Mapbox is cheaper, and easier to set up than Google Maps. Mapbox also has an incredibly generous free-tier that the team can likely rely on for the entire capstone duration.

Mapbox maps have more style options, allowing for granular control over the look of the final interface. Styles can also be edited in code, whereas Google Map styles are defined in the cloud console. Mapbox also has more extensible support for overlaying GeoJSON elements, which is something the team expects to do a lot of to render the simulation.

Mapbox provides some of its service using public data from the OpenStreetMap (OSM) initiative. We are likely to use this same OSM data for generating routes in the simulation engine, which means Mapbox’s coordinate system is much more likely to line-up properly with the coordinate system used within the simulation. This is another advantage of Mapbox over Google Maps.

Mapbox is generally integrated with React apps in one of two ways; either you use the official mapbox-gl library directly, or you use a more React-specific library (like react-map-gl) that is built on top of mapbox-gl. Mapbox themselves suggest using mapbox-gl directly in your React app. Although this means more work to integrate the Mapbox map animation cycle with the React render lifecycle, the frontend team will have more granular control of the underlying APIs which might be necessary for maximizing performance. Another bonus of using mapbox-gl directly, is that the official mapbox documentation assumes this approach in their example snippets. See this example.

References:

Backend

FastAPI

FastAPI Documentation

Prior to the team’s research, Python was already the leading choice for writing backend code. The current backend team already has strong experience with the language and some of its popular libraries (namely PyTest) from months of coursework and past internships. This minimizes the learning curve. Two popular Python backend frameworks were researched in depth; Django and FastAPI. Additionally, research was conducted on non-Python backend frameworks, despite the disadvantage of not being Python-based.

Django Rest Framework (DRF)

  • Has plenty of documentation and resources online to look into in case of doubts
  • Comes with a web GUI similar to Swagger to test endpoints
  • Django has its own ORM so we can customize certain things for our use cases
  • Major drawback is that Django was built for Relational Databases but if we choose to go with a NoSQL database then it will be extra work to set it up.

FastAPI

  • Easy to generate OpenAPI (formerly Swagger) docs
  • current scripts at BIXI are written in Python by developers; choosing Python could possibly reduce the learning curve if ever the project gets undertaken by BIXI’s small team of developers
  • Probably no native websockets support, otherwise seems like a reasonable choice
  • Might be additional overhead involved in writing front-end code in TS to call the Python backend, if FastAPI won’t spit out a Typescript automatically (will it?)

Node.js with Express or NestJS

  • These are popular backend choices for real-time applications with JavaScript/TypeScript compatibility, and work well with WebSocket streaming for pushing simulation updates to the browser.

Spring Boot

  • Spring Boot provides auto-configuration, embedded servers, layered architecture. It should support WebSockets to do microservices with. It has a strong ecosystem and extensive developer tooling support.
  • The team is already familiar with Java from coursework

Research was also conducted on the API design and communication protocols to be leveraged for this project:

  • Considering the nature of simulation and real-time data, favoring streaming protocols like WebSockets or gRPC over traditional REST APIs can enable lower latency and better interactivity.
  • WebSockets are broadly supported and widely used to push real-time updates to clients in browser environments.
  • gRPC can provide efficient, strongly typed RPC calls but may introduce complexity in frontend integrated compared to WebSockets.

The possibility of a microservices / modular backend infrastructure implementation was also considered:

  • We can perhaps adopt a microservice architecture or modular monolith that can help separate concerns:
    • One service handles simulation logic input/output and streaming updates.
    • Another service manages user data, sessions and static resources.
  • This can help us facilitate simulation computing separately from user management.

FastAPI was selected as the framework of choice, and web sockets will be utilized when necessary (during a running simulation).

PIP

Pip Documentation

Similar to the rationale from frontend research, pip (the standard package installer for Python) will be used as it’s mature and widely supported.

PostgreSQL

PostgreSQL Documentation

We want to choose a database that balances the need for structured data-like user info and flexible data storage such as simulation logs and geo-coordinates. Relational databases (PostgreSQL, MySQL) are strong candidates for consistent transactional data. NoSQL databases (MongoDB, Redis) can be used for caching, fast read/writes, or storing semi-structured data.

PyTest

PyTest Documentation

Pytest:

  • A popular and flexible testing framework. Should be suitable for our range of testing, which would be unit to functional tests.
  • unittest (PyUnit): This is Python’s built-in testing module, inspired by Java’s JUnit. Provides test suites, assertion methods, which is ideal for straightforward testing.
  • pytest-html: HTML test report generator for code coverage.
  • pytest-cov: Similar to the one above, report generator to display code coverage metrics.

Simulation

Discrete-Event Simulation Strategy (DES)

Why DES simulation fits our use case

  • Efficient resource handling : DES focuses computation only on events (not continuous time steps), making it scalable for thousands of events.
  • Natural mapping to real operations : each entity (bike, technician, station) can be modeled as a process interacting through shared resources (trucks, drivers, stations, etc.).
  • Queue and scheduling realism : captures waiting lines, limited repair capacity, technician availability, and travel delays accurately.
  • Scenario testing and policy analysis : enables testing “what-if” strategies (e.g., increasing repair vans, dynamic dispatching) before deployment.
  • Widely validated : DES is the standard in logistics, manufacturing, and transportation systems research.

SimPy

SimPy Documentation

Why SimPy is a strong choice for our use case

  • Discrete-Event Simulation (DES) : ideal for modeling event-driven systems like battery repair tasks, and technician dispatches.
  • Process-based design : each Resource, station, and bike can operate as an independent process interacting through shared events and resources.
  • Python-native : integrates directly with our stack (Pandas for data analysis, PostgreSQL for persistence, FastAPI backend).
  • Supports real-time and accelerated modes : allows both real-time dashboards and fast-forward simulation for experiments.
  • Extensive community and academic support : used in logistics, transport, and operations research applications.
  • Integrates well with machine learning : later extendable for predictive dispatching or maintenance forecasting.

Supporting references


Summary

SimPy offers the best balance of realism, flexibility, and integration for our goals.
It supports detailed event-driven maintenance modeling, efficient dispatch logic, and future extensions with analytics or ML — all within our existing Python ecosystem.

Python Package (as opposed to standalone executable)

Network Communication Considerations - the team settled on having backend call sim directly (same executable). Research supporting this decision is presented here.

Rest API vs Streaming Protocols:

GraphHopper (Active Routing Engine)

Full research and implementation context can be found in the routing research wiki and merged implementation PRs.

GraphHopper is the active routing engine in Release 3, using OpenStreetMap data with traffic-aware behavior through per-request custom models.

Why GraphHopper is used in Release 3:

  • HTTP API Architecture: Routing remains decoupled from the simulation engine through a provider adapter layer
  • Traffic-Aware Routing: Supports per-request custom model adjustments, enabling dynamic speed/weight behavior without rebuilding the graph for each scenario
  • Containerized Deployment: Runs as a dedicated Docker service for consistent local/dev/prod behavior
  • Operational Simplicity: Clear startup flow with dedicated compose file and npm scripts
  • Performance and Scale: Suitable for city-scale routing workloads used by the simulator

Implementation Details:

  • GraphHopper server runs in Docker container (israelhikingmap/graphhopper:10.2)
  • Port mapping defaults to 8989:8989 (host:container)
  • Montreal OSM data prepared via scripts/prepare-graphhopper.js
  • Runtime orchestration via docker-compose.graphhopper.yml and npm scripts (graphhopper:prepare, graphhopper:up, graphhopper:down)
  • Simulator connects via HTTP API using GRAPHHOPPER_URL (default: http://localhost:8989)
  • Adapter pattern remains in place to decouple routing provider (see sim/osm/graphhopper_adapter.py)

Architecture:

Simulator → GraphHopper Adapter → HTTP Request → GraphHopper Container → OSM Road Network Data
             ↓
           Route Geometry + Distance/Time Response

Environment Configuration:

  • GRAPHHOPPER_URL: Connection string for GraphHopper service
  • GRAPHHOPPER_TIMEOUT: Request timeout in seconds
  • GRAPHHOPPER_PORT: Optional local port override for container mapping

References:

E2E Tests

Playwright

Playwright is an open-source end-to-end testing library. It allows the creation of reliable automated tests for modern web applications on any browser and platform. Due to the varied operating systems used between team members (Windows or Mac), its cross-platform support would be needed. It creates browser contexts for each test to provide isolation between tests. However, it still allows reuse of log-in operations to contexts, such that the steps are not repeated each time. This authentication fixture would be useful as the application's pages would require an authenticated state for access. This tool is simple to use and learn and provides clear test reports. These can be viewed in the form of a simple HTML report or through an automated video recording (.webm) of the test. The video recordings are easily accessible and could be used for AT approvals.

References:

Logging and Metrics

Our application uses multiple tools to produce detailed logs and metrics of important events which occur in the app. These could include warnings, information and errors. The list of all logging/metrics stacks can found in the Logging and Metrics Wiki pages with more details.

Clone this wiki locally