Maintaining a daily exercise routine is a good habit. Recently, while browsing GitHub, I came across a project that can visualize our data from various sports apps on the front end. So, I decided to give it a try and set one up myself. Below, I will share how I implemented it, focusing mainly on the configuration of Keep.
Clone the main project to local#
The Running Page is an open-source project created by @yihong0618. Through this project, you can synchronize exercise data from multiple mainstream running platforms and automatically generate a map visualization running page. GitHub Pages allows for quick automatic deployment.
Project address: https://github.com/yihong0618/running_page
We can fork this repository to our own and clone it, or directly clone and upload it to our newly created repository.
Configure project files#
Note: The compressed package contains multiple files starting with a dot. On macOS, you need to use the shortcut "Command + shift + ." to show hidden files.
1. Find "gatsby-config.js" in the root directory and configure personalized options.#
pathPrefix: '/', # If you need to use a custom domain, change this to /
siteMetadata: {
siteTitle: 'Running Page', # Site title
siteUrl: 'https://running.domain.com', # Site domain
logo: 'https://q.qlogo.cn/headimg_dl?bs=qq&dst_uin=*********&spec=640', # Top left avatar
description: 'Just Do It',
navLinks: [
{
name: 'Blog', # Top right navigation bar
url: 'https://blog.domain.com',
},
],
},
2. Open the ".github" > "workflows" > "run_data_sync.yml" file, and modify the platform type and information. You can view the configuration information for different platforms on the documentation page.#
name: Run Data Sync
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
env:
# please change to your own config.
RUN_TYPE: keep # support strava/nike/garmin/garmin_cn/keep/only_gpx/nike_to_strava/strava_to_garmin/strava_to_garmin_cn/garmin_to_strava/garmin_to_strava_cn, Please change the 'pass' it to your own
ATHLETE: BarryYangi
TITLE: Barry Running
MIN_GRID_DISTANCE: 4 # change min distance here
TITLE_GRID: Over 4km Runs # also here
GITHUB_NAME: BarryYangi
GITHUB_EMAIL: [email protected]
jobs:
sync:
name: Sync
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: 3.7
# from pdm
- name: Set Variables
id: set_variables
run: |
echo "PY=$(python -c 'import hashlib, sys;print(hashlib.sha256(sys.version.encode()+sys.executable.encode()).hexdigest())')" >> $GITHUB_OUTPUT
echo "PIP_CACHE=$(pip cache dir)" >> $GITHUB_OUTPUT
- name: Cache PIP
uses: actions/cache@v2
with:
path: ${{ steps.set_variables.outputs.PIP_CACHE }}
key: Ubuntu-pip-${{ steps.set_variables.outputs.PY }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
if: steps.pip-cache.outputs.cache-hit != 'true'
- name: Run sync Nike script
if: env.RUN_TYPE == 'nike'
run: |
python scripts/nike_sync.py ${{ secrets.NIKE_REFRESH_TOKEN }}
- name: Run sync Nike to Strava(Run with nike data backup and show with strava)
if: env.RUN_TYPE == 'nike_to_strava'
run: |
python scripts/nike_to_strava_sync.py ${{ secrets.NIKE_REFRESH_TOKEN }} ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}
- name: Run sync Keep script
if: env.RUN_TYPE == 'keep'
run: |
python scripts/keep_sync.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
- name: Run sync Strava script
if: env.RUN_TYPE == 'strava'
run: |
python scripts/strava_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}
# for garmin if you want generate `tcx` you can add --tcx command in the args.
- name: Run sync Garmin script
if: env.RUN_TYPE == 'garmin'
run: |
python scripts/garmin_sync.py ${{ secrets.GARMIN_EMAIL }} ${{ secrets.GARMIN_PASSWORD }}
# If you only want to sync `type running` add args --only-run, default script is to sync all data (rides and runs).
# python scripts/garmin_sync.py ${{ secrets.GARMIN_EMAIL }} ${{ secrets.GARMIN_PASSWORD }} --only-run
- name: Run sync Garmin CN script
if: env.RUN_TYPE == 'garmin_cn'
run: |
python scripts/garmin_sync.py ${{ secrets.GARMIN_CN_EMAIL }} ${{ secrets.GARMIN_CN_PASSWORD }} --is-cn
- name: Run sync Only GPX script
if: env.RUN_TYPE == 'only_gpx'
run: |
python scripts/gpx_sync.py
- name: Run sync Strava to Garmin(Run with strava(or others upload to strava) data backup in Garmin)
if: env.RUN_TYPE == 'strava_to_garmin'
run: |
python scripts/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }} ${{ secrets.GARMIN_EMAIL }} ${{ secrets.GARMIN_PASSWORD }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }}
- name: Run sync Strava to Garmin-cn(Run with strava(or others upload to strava) data backup in Garmin-cn)
if: env.RUN_TYPE == 'strava_to_garmin_cn'
run: |
python scripts/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }} ${{ secrets.GARMIN_CN_EMAIL }} ${{ secrets.GARMIN_CN_PASSWORD }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }} --is-cn
- name: Run sync Garmin-cn to Strava(Run with Garmin data backup in Strava)
if: env.RUN_TYPE == 'garmin_to_strava_cn'
run: |
python scripts/garmin_to_strava_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }} ${{ secrets.GARMIN_CN_EMAIL }} ${{ secrets.GARMIN_CN_PASSWORD }} --is-cn
- name: Run sync Garmin to Strava(Run with Garmin data backup in Strava)
if: env.RUN_TYPE == 'garmin_to_strava'
run: |
python scripts/garmin_to_strava_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }} ${{ secrets.GARMIN_EMAIL }} ${{ secrets.GARMIN_PASSWORD }}
- name: Run sync Tulipsport script
if: env.RUN_TYPE == 'tulipsport'
run: |
python scripts/tulipsport_sync.py ${{ secrets.TULIPSPORT_TOKEN }} --with-gpx
- name: Make svg GitHub profile
if: env.RUN_TYPE != 'pass'
run: |
python scripts/gen_svg.py --from-db --title "${{ env.TITLE }}" --type github --athlete "${{ env.ATHLETE }}" --special-distance 10 --special-distance2 20 --special-color yellow --special-color2 red --output assets/github.svg --use-localtime --min-distance 0.5
python scripts/gen_svg.py --from-db --title "${{ env.TITLE_GRID }}" --type grid --athlete "${{ env.ATHLETE }}" --output assets/grid.svg --special-color yellow --special-color2 red --special-distance 20 --special-distance2 40 --use-localtime --min-distance "${{ env.MIN_GRID_DISTANCE }}"
python scripts/gen_svg.py --from-db --type circular --use-localtime
python scripts/gen_svg.py --from-db --year $(date +"%Y") --language zh_CN --title "$(date +"%Y") Running" --type github --athlete "${{ env.ATHLETE }}" --special-distance 10 --special-distance2 20 --special-color yellow --special-color2 red --output assets/github_$(date +"%Y").svg --use-localtime --min-distance 0.5
- name: Deploy site
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.MY_GIT_TOKEN }}
publish_branch: vercel-pages
publish_dir: .
force_orphan: true
# keep_files: true
Here, it is recommended to delete the remaining three workflow configuration yml files, as we do not need them. Later, we will configure the site on Vercel and then copy the content of my run_data_sync.yml
file to overwrite this file.
3. Find the account information that needs to be completed for your corresponding platform#
For example, keep:
python scripts/keep_sync.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx
We need to be able to log into the Keep mobile account and password, which we will need later.
4. The Running Page uses Mapbox for map display, so you need to go to the Mapbox site to register a developer account.#
After logging in, select "Create a token" to create a token and complete the relevant information. After submission, you will receive a string of token information. Edit the "src" > "utils" > "const.js" file and replace your token in MAPBOX_TOKEN.
5. Save the file and push it to your git repository#
Git repository secrets configuration#
Go to your repository, click Settings -> Secrets and variables -> Actions -> New repository secret to create the following three secrets as shown in the picture
The first two items are the mobile account and password for Keep, and the last item is the GitHub token. If you don't have one, you can click your avatar -> Settings -> Developer settings -> Personal access tokens (classic) -> Generate new token.
When creating, you can check all permissions, and after creating, copy it down. This token will only appear once; after viewing, you will not be able to see it again. Then put this token into the secret in your repository.
Configure Vercel#
Go to our Vercel and register if you don't have an account, then bind it to our GitHub. After binding, click to import the newly created repository directly.
Then we go back to the GitHub repository and click Actions, and manually trigger a workflow as follows.
Wait for the workflow to finish running. If it is checked, it means there is no problem. At this point, we will find an additional vercel-pages branch. This branch will be used for deployment on Vercel. We go to the settings page of this project on Vercel and change the default deployment branch to vercel-pages, as shown in the picture:
After saving, we need to push once again to the vercel-pages branch for Vercel to truly apply it. We just need to re-execute the workflow we just operated on in the Actions page of the GitHub repository.
Wait for the workflow to finish running, and then return to the Vercel page to wait for the deployment to complete. You will find that the deployment branch has changed to vercel-pages.
Vercel domain binding#
If you want to share this page with your friends, this is certainly not elegant enough. If you have your own domain, you can bind it to your domain in the Domains option on the Vercel settings page.
End#
I hope this project brings us not just a simple project deployment experience, but also helps us develop a good exercise habit, which is the most important thing, and then record it so that we can trace back to the present in the future.
Just enjoy it.