Fuel Wizard
This is the source code mono-repository for the Fuel Wizard front end and server/API applications.
What is Fuel Wizard?
Fuel Wizard (https://fuelwizard.au) is a free, open source web application, which provides simple, useful fuel price analytics to everyone. We currently plan to integrate with all of Australia's state government-provided fuel price data sources. Currently, we integrate with NSW, but more will be added in the future. If you are interested in working on an integration for a particular state, please reach out!
Why do this?
Fuel Wizard was a response to limitations with state-government provided fuel price applications. Whilst these have been a positive step for empowering consumers with open data, these apps have a long way to go in terms of functionality. Some third-parties have created fuel price applications, but we hope to provide an application which is modern, fast, simple to use, and contains intelligent price analytics, which can help our users to find better deals on fuel.
Architecture
Front End
The front end application is a Next.js, TypeScript web app, which uses the Mantine UI library and utilities to display the application data. Leaflet is used for the map views, and openapi-generator for automatically generating types and wrappers for requests to the API.
Back End
The back end/API server is an ASP.NET, C# web app, which serves a REST API for consumption by the front end, and by third-parties. OpenAPI/Swagger are used to automatically create API definitions, and provide a handy web interface for viewing this spec. Hangfire is used to schedule cron-like jobs directly within the application code.
Database
A local TimescaleDB instance is used for persistence, and more complex queries of time-series data. The back end utilises ServiceStack.OrmLite to interface with the database in application code.
Getting Started
Linux
To run a local development instance of the application, a TimescaleDB instance must be set up. This can be done quickly and easily through Docker, by utilising the docker-compose config found at: backend/Database/Deployment/compose.yaml. You can reference the Timescale docs for how to set up the database using docker here: https://docs.timescale.com/self-hosted/latest/install/installation-docker/ .
Once the database is running, you can get a development environment set up for the API. You will need .NET SDK 9 installed on your machine: https://learn.microsoft.com/en-us/dotnet/core/install/linux . I would recommend using an IDE to run, debug, and edit the application code. Most of the development work has been done using JetBrains Rider, though I'd like to move entirely to VSCodium (which I use for the front end) at some point.
You can build and run the .NET app in the usual way with the CLI, or through your IDE of choice, and then navigate to the Scalar endpoint to see the API spec, and try out some requests. This should be: http://localhost:<port>/api-docs, but double-check the port if you can't see anything (the application console will output a line on startup detailing which port the server has started on).
When running locally, you can also access the Hangfire dashboard to manually run scheduled tasks (such as fetching new prices, seeding reference data, etc.). This is served at the /hangfire endpoint (so simply visit http://localhost:<port>/hangfire, and you should see the dashboard).
Whilst you should be able to get away with npm or yarn, I would strongly reccommend using pnpm. I have found this to be the best performing, and most reliable package manager for React projects, and so I will tailor these instructions to it.
Install pnpm, as they recommend: https://pnpm.io/installation .
At the root of the front end project (fuel-wizard/frontend), run the install command: pnpm i. This will download and install all of the required packages, which could take a while, so sit tight until that finishes.
After this has completed, you can run pnpm dev to start the Next.js development server, with hot-reload, etc. and then navigate to http://localhost:3000 (again, double-check the port in the console messages) to see the web application.
Other command aliases which will be useful for you are:
pnpm update- update dependenciespnpm generate- with the API server running, this will automatically generate code in thegenerateddirectory to interface with the API via Axiospnpm lint- run ESLint on the front end codebase, to check for linting errorspnpm build- creates a production-optimised build of the Next.js app in the.nextdirectory
Attribution
Thank you to these fantastic projects, and their respective communities, without which, this application would be much worse!
- Hangfire (for background and scheduled tasks): https://www.hangfire.io
- ASP.NET Core (as the basis of our web API): https://github.com/dotnet/aspnetcore
- ServiceStack.OrmLite (as our lightweight .NET ORM): https://github.com/ServiceStack/ServiceStack/tree/main/ServiceStack.OrmLite
- PostgreSQL (as our database): https://www.postgresql.org
- TimescaleDB (as our time-series database): https://github.com/timescale/timescaledb
- Mantine (as our UI/component library): https://mantine.dev
- OpenAPI Generator (for automatic generation of front end API interfaces): https://openapi-generator.tech
- TanStack Query (as our front end query management library): https://tanstack.com/query/latest
- DefinitelyTyped (for their fantastic TypeScript type definitions): https://github.com/DefinitelyTyped/DefinitelyTyped
- Axios (as our front end HTTP client): https://axios-http.com
- Day.js (as our time/date library for the front end): https://day.js.org
- Leaflet (as our interactive map): https://leafletjs.com
- Next.js (as the basis of our SSR front end): https://nextjs.org
- React.js (as our JS framework): https://react.dev
- React Icons (for our icons!): https://react-icons.github.io/react-icons
- React Leaflet (as a minimal React wrapper for Leaflet): https://react-leaflet.js.org
- Recharts (for charts in Mantine): https://recharts.org
- Sharp (for image processing): https://sharp.pixelplumbing.com
- ESLint (for code linting): https://eslint.org
- eslint-plugin-react (for their React ESLint rules): https://github.com/jsx-eslint/eslint-plugin-react
- globals (for Node.js global variables): https://github.com/sindresorhus/globals
- Node.js (as our JS runtime): https://nodejs.org
- PostCSS (for CSS transformation in Mantine): https://postcss.org
- TypeScript ESLint (for TS linting rules): https://typescript-eslint.io
- TypeScript (as our front end language): https://www.typescriptlang.org
- PNPM (as our front end package manager): https://pnpm.io
- .NET (as the basis of our back end): https://github.com/dotnet
- OSRM (as the routing API): https://project-osrm.org
TODO (in rough order of priority)
- Email notifications (WIP)
- Generalise pagination across back end code (pass in simple Pagination objects to methods, rather than the large signature we have currently)
- Western Australia fuel price data integration (nice, simple RSS source, without tonnes of regulatory hoops to jump through)
- VIC, SA, QLD fuel price data (tough to get access to)
- Trend predictions (need more data to work with before we start this)
- Trip tracking and cost vs. distance calculations
- And more...
License
This program is free software: you can redistribute it and/or modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.