Profile
Back to NewsBack
GitHub Trending 8 min
Reader Mode
vanalmsick/workout_challenge: No matter if a healthy close your rings competition with friends or a September steps challenge with work colleagues, this webapp enables you to compete with friends and co-workers across devices using the metrics you wa

vanalmsick/workout_challenge: No matter if a healthy close your rings competition with friends or a September steps challenge with work colleagues, this webapp enables you to compete with friends and co-workers across devices using the metrics you wa

6 hours ago

Workout Challenge

No matter if a healthy close your rings competition with friends or a September steps challenge with work colleagues, this webapp enables you to compete with friends and co-workers across devices (Apple / Android / Garmin / etc.) using the metrics you want to use (km / minutes / kcal / # of times / etc.) respecting your privacy. Participants can either add their workouts and/or steps manually or link their free Strava account for automatic workout import.

How does it work?

Create your own competition or use a friend’s invitation link to join their competition, enter your workouts manually or link your Strava for automatic workout import, and enjoy the competition. You can customize each competition's activity goals individually. Participants earn 1 point for every 1% progress towards a goal. For example, if the goal is 100 minutes of exercise and you work out 50 minutes, you earn 50 points. Additionally, you can cap / floor the maximum / minimum points participants can earn per workout / day / week to e.g. ensure a healthy competition that is focused on consistency.

Features:

  • Create your own competition or use a friend’s invitation link to join their competition
  • Enter workouts manually or import them automatically via Strava (daily at 4 AM)
  • Your personal dashboard shows workout stats and your workout streak
  • The competition dashboards show friends’ workouts, leaderboards, and your progress towards the competition goals
  • A weekly email on Mondays shows you your spot on the competition leaderboards
  • An optional weekly email on Thursday shows your progress against your personal goals
  • Fully responsive website and emails (mobile, tablet, desktop)
  • Light and dark mode
Competition Goal Choices: Create one or several goals for your competition.
  • Metrics: time (minutes) / number of times (#) / distance (km) / calories (kcal) / kilojoules (kj)
  • Period: per day / per week / per month / during the entire competition
  • Limits: min / max per workout, min / max per day, min / max per week

Your Personal Dashboard:

!Preview Dashboard

Competition Dashboards:

!Preview Competition

Automatic Strava Workout Import:

!Preview Strava Import

If you like Workout Challenge, consider giving it a star ⭐! Made with ❤️ in London

Buy Me a Coffee at ko-fi.com

Give it a quick try

docker run -p 80:80 -e ALLOW_ALL_HOSTS=true vanalmsick/workout_challenge

Full Production Deployment

docker-compose.yml
version: '3.9'

services: workoutchallenge: image: vanalmsick/workout_challenge container_name: workoutchallenge ports: - "80:80" - "5555:5555" # Celery Flower task monitoring - do not open to public - only for local network for debugging - "9001:9001" # Supervisord process monitoring - do not open to public - only for local network for debugging - "8000:8000" # Django admin space - do not open to public - only for local network for debugging volumes: - /usr/pi/workout_challenge/django:/workout_challenge/src-backend/data environment: - POSTGRES_HOST=workoutchallenge-database - POSTGRES_DB=workoutchallenge - POSTGRES_USER=postgres - POSTGRES_PASSWORD=password - MAIN_HOST=http://your-url.com - HOSTS=http://your-url.com,http://localhost,http://127.0.0.1 - SECRET_KEY=<your_random_string_for_encryption> - TIME_ZONE=Europe/London - STRAVA_CLIENT_ID=000000 - STRAVA_CLIENT_SECRET=<secret_key> - SENTRY_DSN=https://<PUBLIC_KEY>@<HOST>/<PROJECT_ID> - EMAIL_HOST=smtp.gmail.com - EMAIL_PORT=465 - [email protected] - EMAIL_HOST_PASSWORD=password - EMAIL_USE_SSL=True - EMAIL_USE_TLS=False - [email protected] - [email protected] - OPENAI_API_KEY=<secret_key> restart: unless-stopped depends_on: database: condition: service_healthy

database: image: postgres:15 container_name: workoutchallenge-database environment: - POSTGRES_DB=workoutchallenge - POSTGRES_USER=postgres - POSTGRES_PASSWORD=password ports: - "5432:5432" volumes: - /usr/pi/workout_challenge/postgres:/var/lib/postgresql/data restart: unless-stopped healthcheck: test: [ "CMD-SHELL", "pg_isready -U postgres" ] interval: 5s timeout: 5s retries: 5

docker compose -f /path/to/docker-compose.yml up

Environment variables

| Variable | Default | Definition | |-----------------------|-------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | MAIN_HOST | "http://localhost" | The main hosting url for the Django backend. | | HOSTS | "http://localhost,http://127.0.0.1" | Comma seperated list of hosts for Django. This is used for ALLOWED_HOSTS, CORS_ALLOWED_ORIGINS, and CSRF_TRUSTED_ORIGINS. | | SECRET_KEY | [a hard-coded string in code] | Django's SECRET_KEY for cryptographic signing. | | TIME_ZONE | "Europe/London" | Timezone for Django and Celery | | DEBUG | false | Django's DEBUG mode. If true, CORS_ALLOW_ALL_ORIGINS will also be true and the CACHE will use Local Memory Cache instead of Redis. | | ALLOW_ALL_HOSTS | false | For quick testing to not having to set HOSTS. Do not set to true in production but set HOSTS. | | POSTGRES_HOST | None | If set to None, Django will use SQLite as database (might cause database lock errors in production), else this is the host url to the Postgres database. | | POSTGRES_PORT | 5432 | Database port in Postgres database | | POSTGRES_DB | "postgres" | Database name in Postgres database | | POSTGRES_USER | "postgres" | Database username in Postgres database | | POSTGRES_PASSWORD | "" | Database password in Postgres database | | SENTRY_DSN | None | If None no Sentry.io error capturing, else please provide the project url https://@/ (In local development you might have to set REACT_APP_SENTRY_DSN instead) | | STRAVA_CLIENT_ID | "1234321" | Strava API Client Id. Please see below how to get one. (In local development you might have to set REACT_APP_STRAVA_CLIENT_ID instead) | | STRAVA_CLIENT_SECRET | "ReplaceWithClientSecret" | Strava API Client Secret. Please see below how to get one. | | STRAVA_LIMIT_15MIN | 100 | Strava API Limit per 15min. 300 if part of developer program, else 100. | | STRAVA_LIMIT_DAY | 1000 | Strava API Limit per day. 3000 if part of developer program, else 1000. | | REACT_APP_BACKEND_URL | "" | Overwrite the url to the Django API used by React. This is intended for local development outside of the docker container - e.g. http://localhost:8000. | | EMAIL_HOST | None | SMTP server host url to send out automated emails. | | EMAIL_PORT | None | SMTP server port to send out automated emails. | | EMAIL_HOST_USER | None | SMTP server username to send out automated emails. | | EMAIL_HOST_PASSWORD | None | SMTP server password to send out automated emails. | | EMAIL_USE_SSL | False | SMTP server - if SSL ise used for authentication. | | EMAIL_USE_TLS | False | SMTP server - if TLS ise used for authentication. | | EMAIL_FROM | None | Sender email address of automated emails. | | EMAIL_REPLY_TO | None | Reply-To email address of automated emails. | | OPENAI_API_KEY | None | OpenAI API key to generate workout / health / nutritional facts for the weekly update email. |

How to get the Strava API Client id & secret

  1. Login to your Strava account strava.com/login
  2. Profile picture -> Settings
  3. "My API Application"
  4. Test the workout challenge (only works with your own Strava account)
  5. If you like the workout challenge, apply to the Strava developer program here to also allow other users to link their Strava

Do you want to help / contribute?

Code Overview / Structure

  • Docker Container for deployment
  • Supervisord to start all processes in docker container
  • Nginx to run frontend (React) and proxy traffic to backend (Django) which is run by gunicorn

Frontend (src-frontend)

Backend (src-backend)

  • Django (RestAPI) via gunicorn for production
  • Redis as cache and for Celery
  • Celery as task que for Django
  • Celery Beat for task scheduling for Django
  • Celery Flower UI to inspect task que and task status
  • mjml Framework / app to write responsive email html (mjml.io)

How to run locally for development

Backend - Task-Scheduling (Celery)

working dir: /workout_challenge/src-backend run Redis: redis-server run Celery Worker: celery -A workout_challenge worker --loglevel INFO --without-mingle --without-gossip --events run Celery Beat: celery -A workout_challenge beat --scheduler django_celery_beat.schedulers:DatabaseScheduler --loglevel INFO run Celery Flower: celery -A workout_challenge flower Note: For testing email celery tasks, please set the Email env variables. For testing Strava sync celery tasks, please set the Strava env variables. For celery beat, don't forget to set the timezone env variable.

Backend - RESTApi Server (Django)

working dir: /workout_challenge/src-backend suggested env variables:
PYTHONUNBUFFERED=1
DJANGO_SETTINGS_MODULE=workout_challenge.settings
DEBUG=true
MAIN_HOST=http://localhost
HOSTS=http://localhost,http://127.0.0.1
TIME_ZONE=Europe/London
STRAVA_CLIENT_ID=000000
STRAVA_CLIENT_SECRET=<secret_key>
initial Django setup: python manage.py makemigrations && python manage.py migrate run Django: python manage.py runserver

Frontend (React)

working dir: /workout_challenge/src-frontend suggested env variables:
REACT_APP_BACKEND_URL=http://localhost:8000
run React: npm start

ToDos / Ideas:

  • Add help text to "Link Strava Button" if Strava linkage is not set up
  • Add explanation text for how Steps are converted
  • Add tickbox for runs/walks if they count towards the total daily steps
  • Group finished competitions in archive button
  • Remove total daily steps from weekly email
  • Add competition finish email
  • Send competition start email if user joins after competition already started
  • Add help text if users try joining competitions using non-invite link
  • Add option for competition admin to remove users
  • Improve README texts
  • Improve repo link preview picture
  • Add Garmin API support
  • Add Fitbit API suport
  • Add friends page
  • Add more personal statistics
  • Add medals and achievements
  • Add UI hint if old version of workout challenge is used
Chat with me