A gamified bicycling platform built with Flask and a Vite-powered frontend.
QuestByCycle is a Flask-based web application with a Vite-built frontend designed to engage and motivate the bicycling community through a gamified approach, promoting environmental sustainability and climate activism. Participants complete quests or missions related to bicycling and environmental stewardship, earning badges and recognition among the community. The platform features a competitive yet collaborative environment where users can view their standings on a leaderboard, track their progress through profile pages, and contribute to a greener planet.
This project relies on a variety of open source libraries. The badges below link directly to the GitHub repository for each package.
For automated provisioning details see docs/INFRASTRUCTURE.md.
- User Authentication: Secure sign-up and login functionality to manage user access and personalize user experiences.
- Bot Protection: Login and registration forms are guarded by flask-Humanify using a grid challenge to thwart automated requests.
- Leaderboard/Homepage: A dynamic display of participants, their rankings, and badges earned, fostering a sense of competition and achievement.
- Quest Submission: An interface for users to submit completed quests or missions, facilitating the review and award of badges.
- User Profiles: Dedicated pages for users to view their badges, completed quests, and ranking within the community.
- Responsive Design: Ensuring a seamless and engaging user experience across various devices and screen sizes.
- PWA/TWA Support: Service worker and offline page. See docs/PWA.md for configuration.
- Push Notifications: Optional Web Push support keeps users informed even when the site is closed. See docs/PUSH_NOTIFICATIONS.md for setup.
- AI-Powered Quest Generation: Automatic quest suggestions are generated using the OpenAI API when enabled.
- Background Tasks and Scheduling: Redis-backed RQ workers handle long running jobs and scheduled maintenance tasks.
- Calendar Sync: Link a Google Calendar to auto-create quests from events.
- Calendar Quest View: Upcoming and past calendar quests are shown in separate tables for clarity.
- Python 3.11+
- PostgreSQL
- git
- ffmpeg (optional, for video compression)
- Poetry (for dependency management)
- redis-server
- NGINX with Certbot
- UFW firewall
- Postfix (for email)
- GeoIP2 module and database
- Sass CLI for building CSS
- Node.js 22 and npm
-
Clone the repository and enter the directory:
git clone https://github.com/denuoweb/QuestByCycle.git cd QuestByCycleInstall Poetry and project dependencies (Python 3.11 recommended):
curl -sSL https://install.python-poetry.org | python3 poetry env use 3.11 # ensure a 3.11 virtualenv poetry install --sync
Install Node dependencies and build the frontend assets:
npm install npm run build
Copy
.env.exampleto.envand adjust the values. See docs/DEVELOPER.md for a description of each option.A sample
gunicorn.conf.pyis already provided at the repo root. Adjust values as needed for your environment.Install frontend dependencies and build assets:
npm install npm run build
Start the development environment with one command:
make dev
This simultaneously launches the Flask server, Vite dev server, and the RQ worker.
Use Poetry to run the test suite against Python 3.11.
poetry env use 3.11
poetry install --sync
poetry run pytest -qIf you use external pytest plugins globally, you can isolate the run:
PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 poetry run pytest -qAllocate Swap on low ram systems:
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Secure the postgres superuser
sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD 'STRONG_SUPERSECRET';"
Create application database & role
sudo -u postgres psql <<EOF
CREATE DATABASE questdb;
CREATE USER questuser WITH PASSWORD 'questpassword';
GRANT ALL PRIVILEGES ON DATABASE questdb TO questuser;
\c questdb
ALTER SCHEMA public OWNER TO questuser;
EOF
Ensure Postgres listens only on localhost
sudo sed -i "s/^#listen_addresses =.*/listen_addresses = 'localhost'/" /etc/postgresql/*/main/postgresql.conf
```sudo systemctl restart postgresql``
Install NGINX:
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/mainline/debian `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| sudo tee /etc/apt/preferences.d/99nginx
sudo apt update
sudo apt install nginx nginx-common
-
Install the GeoIP2 module and database
-
Set up UFW
sudo apt install ufwsudo ufw allow 'WWW Full'sudo ufw allow 'OpenSSH'sudo ufw enable -
Edit NGINX config:
sudo nano /etc/nginx/conf.d/default.confExample defaultsudo systemctl restart nginx.servicesudo certbot --nginx -d DOMAINNAME
Set up Emailing
sudo apt update
sudo apt install postfix
sudo nano /etc/postfix/main.cf
Build frontend assets
cd /opt/QuestByCycle
npm install
npm run build
Vite outputs two entry points: main.js for the majority of pages and
submitPhoto.js which is loaded only on submit_photo.html.
If you have ffmpeg installed, ensure it is accessible or set
FFMPEG_PATH in .env. Without ffmpeg videos are stored unmodified.
Run the server in debug
sudo -u APPUSER /home/APPUSER/.local/bin/poetry run flask --app wsgi:app run --host=127.0.0.1 --port=5000
Run the server in production:
sudo nano /etc/systemd/system/questbycycle.service
[Unit]
Description=gunicorn daemon for QuestByCycle application
After=network.target
[Service]
User=APPUSER
Group=APPUSER
WorkingDirectory=/opt/QuestByCycle
ExecStart=/home/APPUSER/.cache/pypoetry/virtualenvs/questbycycle-BK-IO7k_-py3/bin/gunicorn --config /opt/QuestByCycle/gunicorn.conf.py wsgi:app
Nice=-10
Environment="PATH=/home/APPUSER/.cache/pypoetry/virtualenvs/questbycycle-BK-IO7k_-py3/bin"
[Install]
WantedBy=multi-user.targetRun:
sudo systemctl start questbycycle.service
sudo systemctl enable questbycycle.service
Start the background worker:
sudo -u APPUSER /home/APPUSER/.local/bin/poetry run rqworker
Update Poetry:
sudo -u APPUSER HOME=/home/APPUSER /home/APPUSER/.local/bin/poetry update
We welcome contributions from the community! Whether you're interested in adding new features, fixing bugs, or improving documentation, your help is appreciated. Please refer to CONTRIBUTING.md for guidelines on how to contribute to QuestByCycle.
- The bicycling community for their endless passion and dedication to making the world a greener place.
- All contributors who spend their time and effort to improve QuestByCycle.