Technical Documentation: wger-project/wger
βΉοΈ Provenance: Multi-Tier Ingestion Β· CodeWiki Reference
Overview (`README.md`)
wger
wger (ΛvΙΙ‘Ι) is a free workout and fitness manager.
- ποΈ Custom Workout Routines β Create flexible routines with automatic weight progression rules.
- π Comprehensive Tracking β Track diet plans, body weight, and custom measurements.
- π½οΈ Nutrition Management β Log your calories with a food database
from Open Food Facts. - πΈ Progress Gallery β Upload and track your fitness progress with photos.
- π Exercise Wiki β Access and contribute to the built-in exercises.
- π± Cross-Platform Apps β Available on
Android,
iOS,
F-Droid,
and Flathub. - π³ Self-Hostable β Deploy easily with Docker for full control.
- π Multilingual Support β Translated by the community via Weblate.
- π Powerful API β REST API for third-party integrations or automations.
- π₯ Multi-User Support β Includes basic gym management features.
- π 100% Free & Open Source β Licensed under AGPL-3.0 or later.
For a live system, visit: https://wger.de
Self-hosting
Hosting your own instance is basically just a docker compose up -d away. For
more detailed setup instructions take a look at the provided
docker compose file and the
corresponding documentation.
Developing and contributing
Our goal is to build an awesome and flexible fitness and nutrition manager,
along with a comprehensive list of exercises and ingredients, all released
under a free license.
For this, weβd love your help! Whether itβs code, translations, exercises or
reporting issues and ideas, check out our
contribution guide
to get started.
A huge thank you to everyone who has contributed so far! β€οΈ See the full list
in AUTHORS.md.
Documentation
Consult the online documentation at
for installation instructions, API documentation, development guidelines, and
other information
Contact
Feel free to contact us if you found this useful or if there was something that
didn't behave as you expected. We can't fix what we don't know about, so please
report liberally. If you're not sure if something is a bug or not, feel free to
file a bug anyway.
- Discord: https://discord.gg/rPWFv6W
- Mastodon: https://fosstodon.org/@wger
- Issue tracker: https://github.com/wger-project/wger/issues
Sources
All the code and the content is available on github:
Translation
Translate the app to your language on Weblate.
License
- Application Code: AGPL-3.0-or-later
- Exercise/Ingredient Data: Creative Commons (see individual entries)
- Documentation: CC-BY-SA-4.0
Overview (`settings/README.md`)
Settings
This directory contains configuration files and settings for the project.
You can add your own configuration files here, e.g. for development. Set
the DJANGO_SETTINGS_MODULE environment variable to point to the new settings
file. E.g.:
export DJANGO_SETTINGS_MODULE=settings.local_dev
python manage.py runserverIf you want to add settings that are not tracked by git, you can create alocal_dev_extra.py file, this will be imported by local_dev.py if it exists.
Overview (`extras/authors/README.md`)
Generate authors list
This small script reads the commit information and generates a list of authors
and links them to their GitHub profile, if available. This can be run before
each release to keep the data up to date.
Usage
Note that you might run into rate-limiting issues if you run this script too
often. If so, you can generate a token and use it in the script:
https://github.com/settings/personal-access-tokens (no need to select any
permissions, we're just performing reading operations on public data)
Run the script and optionally copy the generated files to their correct locations
uv run generate_authors_api.pyOverview (`extras/open-food-facts/README.md`)
Import Open Food Facts products
This docker compose helps import or update products from the Open Food Facts
database into wger.
Note that the OFF database dump is very large, and you will need several times
this size available on your computer (tar.gz-file, extracted dump, mongo).
1
Download a current dump of their database
cd dump
wget https://static.openfoodfacts.org/data/openfoodfacts-mongodbdump.tar.gz
tar xzvf openfoodfacts-mongodbdump.tar.gz2
Import the data into mongo.
Note that we are running this as a manual step since the import takes a while
docker compose up
docker compose exec mongodb mongorestore --username off --password off-wger -d admin -c products /dump/off/products.bsonThere is also an admin interface available at http://localhost:8081, log in with
these credentials:
- admin
- pass
3
Run the import script
python manage.py import-off-productsTo update the data fixtures:
python manage.py dumpdata nutrition > extras/scripts/data.json
cd extras/scripts
python filter-fixtures.py
zip ingredients.json.zip ingredients.json
zip weight_units.json.zip weight_units.json
zip ingredient_units.json.zip ingredient_units.json4
Don't forget to delete the dump and remove the containers if you love your
hard disk
docker compose down
rm dump -r openfoodfacts-mongodbdump.tar.gz dump/dumpOverview (`wger/trophies/README.md`)
Trophy System
The trophy (achievement) system allows users to earn trophies based on
their workout activities.
Features
- Multiple Trophy Types: Time-based, volume-based, count-based,
sequence-based, date-based, and custom trophies - Progressive Trophies: Show user progress towards earning a trophy
- Hidden Trophies: Secret achievements that are revealed only when
earned - Repeatable Trophies: Trophies can be earned multiple times, for
example PR trophies. Context data can be added to each earned trophy. - Automatic Evaluation: Trophies are evaluated automatically when
workout data changes - Statistics Tracking: Denormalized statistics for efficient trophy
evaluation - API Endpoints: Full REST API for trophy data and progress tracking
Configuration
Global Settings
Add to your settings.py or settings_global.py:
WGER_SETTINGS = {
# Enable/disable the trophy system globally
'TROPHIES_ENABLED': True,
# Number of days of inactivity before skipping trophy evaluation for a user
'TROPHIES_INACTIVE_USER_DAYS': 30,
}User Preferences
Users can enable/disable trophies in their profile settings via thetrophies_enabled field on UserProfile.
Database Models
Trophy
Defines an achievement that users can earn.
Fields:
name: Trophy namedescription: How to earn ittrophy_type: Type (time, volume, count, sequence, date, other)checker_class: Python class that checks if trophy is earned
(e.g., 'count_based')checker_params: JSON parameters for the checker
(e.g.,{'count': 10})is_hidden: Hidden until earnedis_progressive: Shows progress percentageis_active: Can be earned (admins can disable)is_repeatable: Can be earned multiple timesorder: Display order
UserTrophy
Links users to their earned trophies.
Fields:
user: User who earned the trophytrophy: The trophy earnedearned_at: Timestamp when earnedprogress: Progress percentage (0-100)is_notified: For future notification systemcontext_data: Additionnal information on the trophy
UserStatistics
Denormalized statistics for efficient trophy checking.
Fields:
user: OneToOne with Usertotal_weight_lifted: Cumulative weight in kgtotal_workouts: Number of workout sessionscurrent_streak: Current consecutive workout dayslongest_streak: Longest streak ever achievedearliest_workout_time: Earliest workout time everlatest_workout_time: Latest workout time everweekend_workout_streak: Consecutive weekends with workoutslast_complete_weekend_date: Last Saturday with both days workedworked_out_jan_1: Has worked out on any January 1stlast_inactive_date: Last workout before 30+ day gap
Trophy Checkers
Trophy checkers are Python classes that determine if a user has earned a trophy.
Available Checkers
count_based: Check if user reached a count
- Params:
{'count': 10} - Example: "Complete 10 workouts"
- Params:
streak: Check for consecutive day streaks
- Params:
{'days': 30} - Example: "30-day workout streak"
- Params:
weekend_warrior: Check for consecutive complete weekends
- Params:
{'weekends': 4} - Example: "Work out on Saturday AND Sunday for 4 weekends"
- Params:
volume: Check for cumulative weight lifted
- Params:
{'kg': 5000} - Example: "Lift 5,000 kg total"
- Params:
time_based: Check for workout at specific time
- Params:
{'before': '06:00'}or{'after': '21:00'} - Example: "Work out before 6:00 AM"
- Params:
date_based: Check for workout on specific date
- Params:
{'month': 1, 'day': 1} - Example: "Work out on January 1st"
- Params:
inactivity_return: Check for return after inactivity
- Params:
{'inactive_days': 30} - Example: "Return to training after 30 days inactive"
- Params:
personal_record: Check for new PRs
- Params:
{'log': WorkoutLog} - Example: "Beats PR on exercise 'Bench Press Dumbells' by logging 100kg for 10 reps."
- Params:
Management Commands
Load Trophies
Load the initial set of trophies into the database:
# Load trophies (overwrites existing ones if IDs match)
python manage.py loaddata initial_trophiesEvaluate Trophies
Manually trigger trophy evaluation:
# Evaluate for a specific user
python manage.py evaluate_trophies --user username
# Evaluate a specific trophy for all users
python manage.py evaluate_trophies --trophy 5
# Evaluate all trophies for all active users
python manage.py evaluate_trophies --all
# Force re-evaluation (check already earned trophies)
python manage.py evaluate_trophies --all --force-reevaluateRecalculate Statistics
Rebuild user statistics from workout history:
# Recalculate for a specific user
python manage.py recalculate_statistics --user username
# Recalculate for all users
python manage.py recalculate_statistics --all
# Recalculate for active users only
python manage.py recalculate_statistics --all --active-onlyAPI Endpoints
Trophy Endpoints
GET /api/v2/trophy/
List all active trophies
- Hidden trophies excluded unless earned by user
GET /api/v2/trophy/{id}/
Get specific trophy details
GET /api/v2/trophy/progress/
Get progress for all trophies (current user)
- Returns earned status and progress percentage
- Includes current/target values for progressive trophiesUser Trophy Endpoints
GET /api/v2/user-trophy/
List current user's earned trophies
- Ordered by earned_at (newest first)
GET /api/v2/user-trophy/{id}/
Get specific earned trophy detailsUser Statistics Endpoints
GET /api/v2/user-statistics/
Get current user's trophy statisticsAPI Components
Serializers
TrophySerializer (wger.trophies.api.serializers):
- Serializes Trophy model for API responses
- Fields: id, uuid, name, description, trophy_type, checker_class,
checker_params, is_hidden, is_progressive, is_active, order - Read-only serializer for trophy definitions
UserTrophySerializer (wger.trophies.api.serializers):
- Serializes UserTrophy model (earned trophies)
- Fields: id, user, trophy (nested), earned_at, progress, is_notified
- Includes nested trophy details in response
UserStatisticsSerializer (wger.trophies.api.serializers):
- Serializes UserStatistics model
- Fields: All statistics fields (total_weight_lifted, total_workouts,
current_streak, longest_streak, etc.) - Read-only serializer for statistics data
TrophyProgressSerializer (wger.trophies.api.serializers):
- Custom serializer for trophy progress tracking
- Fields: trophy (nested), is_earned, earned_at, progress,
current_value, target_value - Used by
/api/v2/trophy/progress/endpoint
Filtersets
TrophyFilterSet (wger.trophies.api.filtersets):
- Filter trophies by type, active status, hidden status
- Fields:
trophy_type,is_active,is_hidden,is_progressive - Example:
/api/v2/trophy/?trophy_type=volume&is_active=true
UserTrophyFilterSet (wger.trophies.api.filtersets):
- Filter user's earned trophies
- Fields:
trophy,earned_at(date range),progress - Example:
/api/v2/user-trophy/?trophy=5&earned_at__gte=2024-01-01
Example API Usage:
# Get all volume-based trophies
GET /api/v2/trophy/?trophy_type=volume
# Get trophies earned in 2024
GET /api/v2/user-trophy/?earned_at__year=2024
# Get progress for all trophies (authenticated)
GET /api/v2/trophy/progress/
# Get current user's statistics
GET /api/v2/user-statistics/Adding New Trophies
Method 1: Using Code (Recommended for new trophy types)
- Create a new checker class (if needed) in
wger/trophies/checkers/:
# wger/trophies/checkers/my_checker.py
from .base import BaseTrophyChecker
class MyCustomChecker(BaseTrophyChecker):
def check(self) -> bool:
# Your logic here
return True
def get_progress(self) -> float:
# Calculate progress 0-100
return 50.0
def get_current_value(self):
return 'current'
def get_target_value(self):
return 'target'- Register the checker in
wger/trophies/checkers/registry.py:
from .my_checker import MyCustomChecker
class CheckerRegistry:
_registry: Dict[str, Type[BaseTrophyChecker]] = {
# ... existing checkers ...
'my_custom': MyCustomChecker,
}- Add the trophy via Django admin or shell:
from wger.trophies.models import Trophy
Trophy.objects.create(
name='My Custom Trophy',
description='Description of how to earn it',
trophy_type=Trophy.TYPE_OTHER,
checker_class='my_custom',
checker_params={'param1': 'value1'},
is_hidden=False,
is_progressive=True,
order=100,
)Method 2: Using Existing Checkers
Simply create a new Trophy object with an existing checker:
Trophy.objects.create(
name='Heavy Lifter',
description='Lift 10,000 kg total',
trophy_type=Trophy.TYPE_VOLUME,
checker_class='volume',
checker_params={'kg': 10000},
is_progressive=True,
order=50,
)Method 3: Using Fixtures
Create a JSON fixture in wger/trophies/fixtures/:
[
{
"model": "trophies.trophy",
"pk": 10,
"fields": {
"name": "My Trophy",
"description": "Description",
"trophy_type": "count",
"checker_class": "count_based",
"checker_params": {"count": 100},
"is_hidden": false,
"is_progressive": true,
"is_active": true,
"order": 100
}
}
]Load with: python manage.py loaddata my_trophies
Services API
UserStatisticsService
Service for managing user workout statistics.
Methods:
increment_workout(user, workout_date, weight_lifted): Incrementally
update statistics after a workout. Updates streak, total workouts,
weight lifted, and workout times.update_statistics(user): Recalculate all statistics from scratch
by scanning workout history. Use for fixing inconsistencies.get_or_create_statistics(user): Get existing statistics or create
new record with default values.handle_workout_deletion(user, workout_date): Update statistics
after a workout is deleted. Recalculates streaks if needed.
Example Usage:
from wger.trophies.services.statistics import UserStatisticsService
from decimal import Decimal
import datetime
# Increment after workout
UserStatisticsService.increment_workout(
user=request.user, workout_date=datetime.date.today(), weight_lifted=Decimal('150.5')
)
# Recalculate all statistics
stats = UserStatisticsService.update_statistics(request.user)
# Get statistics (create if missing)
stats = UserStatisticsService.get_or_create_statistics(request.user)TrophyService
Service for evaluating and awarding trophies.
Methods:
evaluate_all_trophies(user, force=False): Evaluate all active
trophies for a user. Returns list of newly awarded UserTrophy
objects. Skip already earned unless force=True.award_trophy(user, trophy, progress=100.0): Award a specific
trophy to a user. Creates UserTrophy record. Idempotent (safe to
call multiple times).get_user_trophies(user, include_hidden=False): Get all trophies
earned by a user. Filter hidden trophies unless specified.get_all_trophy_progress(user, include_hidden=False): Get progress
for all trophies. Returns list of dicts with trophy info, earned
status, progress %, current/target values.reevaluate_trophies(user_ids=None, trophy_id=None, force_reevaluate=False): Batch re-evaluate trophies for multiple
users. Returns dict with users_checked, trophies_awarded counts.
Example Usage:
from wger.trophies.services.trophy import TrophyService
# Evaluate all trophies for user
newly_awarded = TrophyService.evaluate_all_trophies(request.user)
for user_trophy in newly_awarded:
print(f'Earned: {user_trophy.trophy.name}')
# Get user's earned trophies
earned = TrophyService.get_user_trophies(request.user)
# Get progress for all trophies
progress = TrophyService.get_all_trophy_progress(request.user)
for item in progress:
print(f'{item["trophy"].name}: {item["progress"]}%')
# Batch re-evaluate for all active users
results = TrophyService.reevaluate_trophies()
print(f'Checked {results["users_checked"]} users')
print(f'Awarded {results["trophies_awarded"]} trophies')Signals and Auto-Evaluation
Signal Handlers
The trophy system uses Django signals for automatic evaluation:
workout_log_saved signal (wger.manager.signals):
- Fires when
WorkoutLogis saved (user logs exercise sets) - Handler: Updates
UserStatisticsincrementally - Then evaluates all trophies for the user
workout_session_saved signal (wger.manager.signals):
- Fires when
WorkoutSessionis saved (user completes workout) - Handler: Updates workout count and streak
- Then evaluates all trophies for the user
workout_deleted signal (wger.manager.signals):
- Fires when workout is deleted
- Handler: Calls
handle_workout_deletion()to update statistics
Configuration:
Signals are automatically connected in wger/trophies/apps.py:
class TrophiesConfig(AppConfig):
def ready(self):
import wger.trophies.signals # noqa: F401How Auto-Evaluation Works
When a user logs a workout:
WorkoutSessionorWorkoutLogis saved- Django signal fires (
post_save) UserStatisticsService.increment_workout()updates statistics
incrementallyTrophyService.evaluate_all_trophies()checks for newly earned
trophies- Earned trophies create
UserTrophyrecords - User sees new trophy (notifications in future version)
Celery Tasks (Optional)
For async evaluation:
from wger.trophies.tasks import evaluate_user_trophies_task
# Evaluate asynchronously
evaluate_user_trophies_task.delay(user_id)Performance Considerations
- Denormalized Statistics:
UserStatisticstable provides O(1)
lookups - Incremental Updates: Statistics update incrementally, not full
recalculation - Inactive User Skipping: Users inactive >30 days are skipped
- Bulk Operations: Batch evaluation supports chunking for large
user sets
Testing
Run the trophy test suite:
# All trophy tests
python manage.py test wger.trophies.tests
# Specific test files
python manage.py test wger.trophies.tests.test_models
python manage.py test wger.trophies.tests.test_checkers
python manage.py test wger.trophies.tests.test_services
python manage.py test wger.trophies.tests.test_api
python manage.py test wger.trophies.tests.test_integrationInitial Trophies
The system includes 10 initial trophies.
- Beginner: Complete your first workout
- Unstoppable: Maintain a 30-day workout streak
- Weekend Warrior: Work out on Saturday and Sunday for 4 consecutive
weekends - Lifter: Lift a cumulative total of 5,000 kg
- Atlas: Lift a cumulative total of 100,000 kg
- Early Bird: Complete a workout before 6:00 AM
- Night Owl: Complete a workout after 9:00 PM
- New Year, New Me: Work out on January 1st
- Phoenix (Hidden): Return to training after being inactive for
30 days - PR Trophy Achieve a new Personal Record on any exercise
Load them with: python manage.py loaddata initial_trophies
Troubleshooting
Trophies not being awarded
- Check if trophy system is enabled:
TROPHIES_ENABLED = True - Check user's profile:
user.userprofile.trophies_enabled - Check user activity: Not inactive >30 days
- Check trophy is active:
trophy.is_active = True - Recalculate statistics:
python manage.py recalculate_statistics --user username
Statistics not updating
- Check signals are connected (should happen automatically)
- Manually recalculate:
python manage.py recalculate_statistics --all - Check for errors in logs
Performance issues
- Add database indexes (already included in migrations)
- Enable Celery for async evaluation
- Adjust
TROPHIES_INACTIVE_USER_DAYSto skip more users - Disable trophies for inactive users in bulk
License
AGPL-3.0 (same as wger Workout Manager)
Overview (`extras/docker/base/README.md`)
Development image for wger - Base image
This is the base image for some of the other wger images and offers no
functionality, it's only use is to provide some common dependencies.
If you want to develop, try wger/server.
Contact
Feel free to contact us if you found this useful or if there was something that
didn't behave as you expected. We can't fix what we don't know about, so please
report liberally. If you're not sure if something is a bug or not, feel free to
file a bug anyway.
- Discord: https://discord.gg/rPWFv6W
- Issue tracker: https://github.com/wger-project/wger/issues
- Mastodon: https://fosstodon.org/@wger
Sources
All the code and the content is freely available:
- Main repository: https://github.com/wger-project/wger
Licence
The application is licenced under the Affero GNU General Public License 3 or
later (AGPL 3+).
The initial exercise and ingredient data is licensed additionally under one of
the Creative Commons licenses, see the individual exercises for more details.
The documentation is released under a CC-BY-SA either version 4 of the License,
or (at your option) any later version.
Some images where taken from Wikipedia, see the SOURCES file in their respective
folders for more details.
Overview (`extras/docker/demo/README.md`)
Demo image for wger
wger (ΛvΙΙ‘Ι) Workout Manager is a free, open source web application that help
you manage your personal workouts, weight and diet plans and can also be used
as a simple gym management utility. It offers a REST API as well, for easy
integration with other projects and tools.
Please note that this image will overwrite your data when you pull a new version,
it is only intended as an easy to setup demo. If you want to host your own
instance, take a look at the provided docker compose file. That config will
persist your database and uploaded images:
https://github.com/wger-project/docker
Installation
This docker image contains an instance of the application running as a WSGI
process under apache with a sqlite database. It is useful to just try it out and
play around. To start it:
docker run -ti --name wger.demo --publish 8000:80 wger/demo
Then just open http://localhost:8000 and log in as: admin, password adminadmin
To stop the container:
sudo docker container stop wger.demo
To start developing again:
sudo docker container start --attach wger.demo
Building
If you build this yourself, keep in mind that you must build from the
project root!
docker build -f extras/docker/demo/Dockerfile --tag wger/demo .
Contact
Feel free to contact us if you found this useful or if there was something that
didn't behave as you expected. We can't fix what we don't know about, so please
report liberally. If you're not sure if something is a bug or not, feel free to
file a bug anyway.
- Discord: https://discord.gg/rPWFv6W
- Issue tracker: https://github.com/wger-project/wger/issues
- Mastodon: https://fosstodon.org/@wger
Sources
All the code and the content is freely available:
- Main repository: https://github.com/wger-project/wger
Licence
The application is licenced under the Affero GNU General Public License 3 or
later (AGPL 3+).
The initial exercise and ingredient data is licensed additionally under one of
the Creative Commons licenses, see the individual exercises for more details.
The documentation is released under a CC-BY-SA either version 4 of the License,
or (at your option) any later version.
Some images where taken from Wikipedia, see the SOURCES file in their respective
folders for more details.
Overview (`extras/docker/development/README.md`)
Development image for wger
Please consult https://wger.readthedocs.io/en/latest/development/docker.html for
instructions on how to use this image.
Overview (`extras/docker/production/README.md`)
Production image for wger
wger (ΛvΙΙ‘Ι) Workout Manager is a free, open source web application that help
you manage your personal workouts, weight and diet plans and can also be used
as a simple gym management utility. It offers a REST API as well, for easy
integration with other projects and tools.
Usage
It is recommended to use this image with the provided docker compose, which has all the different
services configured:
https://github.com/wger-project/docker
Contact
Feel free to contact us if you found this useful or if there was something that
didn't behave as you expected. We can't fix what we don't know about, so please
report liberally. If you're not sure if something is a bug or not, feel free to
file a bug anyway.
- Discord: https://discord.gg/rPWFv6W
- Issue tracker: https://github.com/wger-project/wger/issues
- Mastodon: https://fosstodon.org/@wger
Sources
All the code and the content is freely available:
- Main repository: https://github.com/wger-project/wger
Licence
The application is licenced under the Affero GNU General Public License 3 or
later (AGPL 3+).
The initial exercise and ingredient data is licensed additionally under one of
the Creative Commons licenses, see the individual exercises for more details.
The documentation is released under a CC-BY-SA either version 4 of the License,
or (at your option) any later version.
Some images where taken from Wikipedia, see the SOURCES file in their respective
folders for more details.
Overview (`wger/core/static/images/logos/app-store/README.md`)
App Store
https://developer.apple.com/app-store/marketing/guidelines/
App Store ist a trademark of Apple Inc., registered in the U.S. and other countries.
Overview (`wger/core/static/images/logos/play-store/README.md`)
Play Store
https://partnermarketinghub.withgoogle.com/brands/google-play/visual-identity/badge-guidelines/
Google Play and the Google Play logo are trademarks of Google LLC.
--- METRICS ---
- Files Extracted: 11
- Estimated Token Budget: ~7587 tokens
- Canonical Reference: https://codewiki.google/github.com/wger-project/wger