Running page runners
- GitHub Actions manages automatic synchronization of runs and generation of new pages.
- Gatsby-generated static pages, fast
- Support for Vercel (recommended) and GitHub Pages automated deployment
- React Hooks
- Mapbox for map display
- Supports most sports apps such as nike strava...
automatically backup gpx data for easy backup and uploading to other software.
Note: If you don't want to make the data public, you can choose strava's fuzzy processing, or private repositories.
- Garmin
- Garmin-CN
- Nike Run Club
- Strava
- GPX
- TCX
- Nike_to_Strava(Using NRC Run, Strava backup data)
- Tcx_to_Strava(upload all tcx data to strava)
- Gpx_to_Strava(upload all gpx data to strava)
- Garmin_to_Strava(Using Garmin Run, Strava backup data)
- Strava_to_Garmin(Using Strava Run, Garmin backup data)
Clone or fork the repo.
git clone https://github.com/yihong0618/running_page.git --depth=1
pip3 install -r requirements.txt
yarn install
yarn develop
Open your browser and visit http:https://localhost:8000/
#build
# NRC
docker build -t running_page:latest . --build-arg app=NRC --build-arg nike_refresh_token=""
# Garmin
docker build -t running_page:latest . --build-arg app=Garmin --build-arg email="" --build-arg password=""
# Garmin-CN
docker build -t running_page:latest . --build-arg app=Garmin-CN --build-arg email="" --build-arg password=""
# Strava
docker build -t running_page:latest . --build-arg app=Strava --build-arg client_id="" --build-arg client_secret="" --build-arg refresh_token=""
#Nike_to_Strava
docker build -t running_page:latest . --build-arg app=Nike_to_Strava --build-arg nike_refresh_token="" --build-arg client_id="" --build-arg client_secret="" --build-arg refresh_token=""
#run
docker run -itd -p 80:80 running_page:latest
#visit
Open your browser and visit localhost:80
If you use English please change
IS_CHINESE = false
insrc/utils/const.js
Suggested changes to your own Mapbox token
const MAPBOX_TOKEN =
'pk.eyJ1IjoieWlob25nMDYxOCIsImEiOiJja2J3M28xbG4wYzl0MzJxZm0ya2Fua2p2In0.PNKfkeQwYuyGOTT_x9BJ4Q';
- Find
gatsby-config.js
in the repository directory, find the following content, and change it to what you want.
siteMetadata: {
siteTitle: 'Running Page', #website title
siteUrl: 'https://yihong.run', #website url
logo: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQTtc69JxHNcmN1ETpMUX4dozAgAN6iPjWalQ&usqp=CAU', #logo img
description: 'Personal site and blog',
navLinks: [
{
name: 'Blog', #navigation name
url: 'https://yihong.run/running', #navigation url
},
{
name: 'About',
url: 'https://github.com/yihong0618/running_page/blob/master/README-CN.md',
},
],
},
- Modifying styling in
src/utils/const.js
// styling: set to `false` if you want to disable dash-line route
const USE_DASH_LINE = true;
// styling: route line opacity: [0, 1]
const LINE_OPACITY = 0.4;
- privacy protection
setting flowing env:
IGNORE_START_END_RANGE = 200 # ignore distance for each polyline start and end.
IGNORE_RANGE = 200 # ignore meters for each point in below polyline.
IGNORE_POLYLINE = ktjrFoemeU~IorGq}DeB # a polyline include point you want to ignore.
# Do filter before saving to database, you will lose some data, but you can protect your privacy, when you using public repo. enable for set 1, disable via unset.
IGNORE_BEFORE_SAVING =
You can using this, to making your IGNORE_POLYLINE
.
Download your running data and do not forget to generate svg in total
page
Make your GPX
data
Copy all your gpx files to GPX_OUT or new gpx files
python3(python) scripts/gpx_sync.py
Make your TCX
data
Copy all your tcx files to TCX_OUT or new tcx files
python3(python) scripts/tcx_sync.py
Get your Garmin
data
If you only want to sync `type running` add args --only-run
If you only want tcx
files add args --tcx
If you only want fit
files add args --fit
python3(python) scripts/garmin_sync.py ${your email} ${your password}
example:
python3(python) scripts/garmin_sync.py example@gmail.com example
only-run:
python3(python) scripts/garmin_sync.py example@gmail.com example --only-run
Get your Garmin-CN
data
If you only want to sync `type running` add args --only-run
If you only want tcx
files add args --tcx
If you only want fit
files add args --fit
python3(python) scripts/garmin_sync.py ${your email} ${your password} --is-cn
example:
python3(python) scripts/garmin_sync.py example@gmail.com example --is-cn
Get your Nike Run Club
data
Please note: When you choose to deploy running_page on your own server, due to Nike has blocked some IDC's IP band, maybe your server cannot sync Nike Run Club's data correctly and display
403 error
, then you have to change another way to host it.
Get Nike's refresh_token
- Login Nike website
- In Develop -> Application-> Storage -> https:unite.nike.com look for
refresh_token
- Execute in the root directory:
python3(python) scripts/nike_sync.py ${nike refresh_token}
example:
python3(python) scripts/nike_sync.py eyJhbGciThiMTItNGIw******
Get your Strava
data
-
Sign in/Sign up Strava account
-
Open after successful Signin Strava Developers -> Create & Manage Your App
-
Create
My API Application
: Enter the following information
Created successfully:
- Use the link below to request all permissions: Replace
${your_id}
in the link withMy API Application
Client ID
https://www.strava.com/oauth/authorize?client_id=${your_id}&response_type=code&redirect_uri=http:https://localhost/exchange_token&approval_prompt=force&scope=read_all,profile:read_all,activity:read_all,profile:write,activity:write
- Get the
code
value in the link
example:
http:https://localhost/exchange_token?state=&code=1dab37edd9970971fb502c9efdd087f4f3471e6e&scope=read,activity:write,activity:read_all,profile:write,profile:read_all,read_all
code
value:
1dab37edd9970971fb502c9efdd087f4f3471e6
- Use
Client_id
、Client_secret
、Code
getrefresh_token
: Execute inTerminal/iTerm
curl -X POST https://www.strava.com/oauth/token \
-F client_id=${Your Client ID} \
-F client_secret=${Your Client Secret} \
-F code=${Your Code} \
-F grant_type=authorization_code
example:
curl -X POST https://www.strava.com/oauth/token \
-F client_id=12345 \
-F client_secret=b21******d0bfb377998ed1ac3b0 \
-F code=d09******b58abface48003 \
-F grant_type=authorization_code
- Sync
Strava
data
The first time you synchronize Strava data you need to change line 12 of the code False to True in strava_sync.py, and then change it to False after it finishes running. If you only want to sync
type running
add args --only-run
python3(python) scripts/strava_sync.py ${client_id} ${client_secret} ${refresh_token}
References:
upload all tcx files to strava
- follow the strava steps
- copy all your tcx files to TCX_OUT
- Execute in the root directory:
python3(python) scripts/tcx_to_strava_sync.py ${client_id} ${client_secret} ${strava_refresh_token}
example:
python3(python) scripts/tcx_to_strava_sync.py xxx xxx xxx
or
python3(python) scripts/tcx_to_strava_sync.py xxx xxx xxx --all
- if you want to all files add args
--all
upload all gpx files to strava
- follow the strava steps
- copy all your gpx files to GPX_OUT
- Execute in the root directory:
python3(python) scripts/gpx_to_strava_sync.py ${client_id} ${client_secret} ${strava_refresh_token}
example:
python3(python) scripts/gpx_to_strava_sync.py xxx xxx xxx
or
python3(python) scripts/tcx_to_strava_sync.py xxx xxx xxx --all
- if you want to all files add args
--all
Get your Nike Run Club
data and upload to strava
- follow the nike and strava steps
- Execute in the root directory:
python3(python) scripts/nike_to_strava_sync.py ${nike_refresh_token} ${client_id} ${client_secret} ${strava_refresh_token}
example:
python3(python) scripts/nike_to_strava_sync.py eyJhbGciThiMTItNGIw****** xxx xxx xxx
Get your Garmin
data and upload to strava
- finish garmin and strava setps
- Execute in the root directory:
python3(python) scripts/garmin_to_strava_sync.py ${client_id} ${client_secret} ${strava_refresh_token} ${garmin_email} ${garmin_password} --is-cn
e.g.
python3(python) scripts/garmin_to_strava_sync.py xxx xxx xxx xx xxx
Get your Strava
data and upload to Garmin
- finish garmin and strava setps, at the same time, you need to add additional strava config in Github Actions secret:
secrets.STRAVA_EMAIL
,secrets.STRAVA_PASSWORD
- Execute in the root directory:
python3(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 }}
if your garmin account region is China, you need to execute the command:
python3(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
If you want to add Garmin Device during sync, you should add --use_fake_garmin_device
argument, this will add a Garmin Device (Garmin Forerunner 245 by default, and you can change device in garmin_device_adaptor.py
) in synced Garmin workout record, this is essential when you want to sync the workout record to other APP like Keep, JoyRun etc.
![image](https://private-user-images.githubusercontent.com/8613196/250119133-b5076942-3133-4c89-ad66-a828211667dc.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQwMzA1NTYsIm5iZiI6MTcyNDAzMDI1NiwicGF0aCI6Ii84NjEzMTk2LzI1MDExOTEzMy1iNTA3Njk0Mi0zMTMzLTRjODktYWQ2Ni1hODI4MjExNjY3ZGMucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDgxOSUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA4MTlUMDExNzM2WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MDc3YzcwMjEyYjViYTgzZTYzM2YwNjVhMDcwOTdhMGIzZTNhNDY0YTQzYzhiMmY3MzliYWYxYWMwM2I3NWIwMyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ._FdxLJf-nCCR3gzJJD2XYoS7Ig9Ja93_eVCivlAH_KI)
the final command will be:
python3(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 }} --use_fake_garmin_device
ps: when initializing for the first time, if you have a large amount of strava data, some data may fail to upload, just retry several times.
Running data display
- Generate SVG data display
- Display of results:Click to view、Click to view
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 --min-distance 10.0 --special-color yellow --special-color2 red --special-distance 20 --special-distance2 40 --use-localtime
Generate year circular svg show
python3(python) scripts/gen_svg.py --from-db --type circular --use-localtime
For more display effects, see: https://github.com/flopp/GpxTrackPoster
Use Vercel
to deploy
- vercel connects to your GitHub repo.
- import repo
- Awaiting completion of deployment
- Visits
Use Cloudflare
to deploy
-
Click
Create a project
inPages
to connect to your Repo. -
After clicking
Begin setup
, modify Project'sBuild settings
. -
Select
Framework preset
toGatsby
-
Scroll down, click
Environment variables
, then variable below:Variable name =
PYTHON_VERSION
, Value =3.7
-
Click
Save and Deploy
Deploy to GitHub Pages
-
If you are using a custom domain for GitHub Pages, open .github/workflows/gh-pages.yml, change
fqdn
value to the domain name of your site. -
(Skip this step if you're NOT using a custom domain) Modify
gatsby-config.js
, changepathPrefix
value to the root path. If the repository name isrunning_page
, the value will be/running_page
. -
Go to repository's
Actions -> Workflows -> All Workflows
, choosePublish GitHub Pages
from the left panel, clickRun workflow
. Make sure the workflow runs without errors, andgh-pages
branch is created. -
Go to repository's
Settings -> GitHub Pages -> Source
, chooseBranch: gh-pages
, clickSave
.
Modifying information in GitHub Actions
Actions source code The following steps need to be taken
- change to your app type and info
- Add your secret in repo Settings > Secrets (add only the ones you need).
- My secret is as follows
- Go to repository's
Settings -> Code and automation -> Actions ->General
, Scroll to the bottom, findWorkflow permissions
, choose the first optionRead and write permissions
, clickSave
.
- Complete this document.
- Support Garmin, Garmin China
- support for nike+strava
- Support English
- Refine the code
- add new features
- tests
- support the world map
- support multiple types, like hiking, biking~
- support for Zeep life
- Any Issues PR welcome.
- You can PR share your Running page in README I will merge it.
Before submitting PR:
- Format Python code with
black
(black .
)
- @flopp great repo GpxTrackPoster
- @danpalmer UI design
- @shaonianche icon design and doc
- @geekplux Friendly help and encouragement, refactored the whole front-end code, learned a lot
- @MFYDev Wiki
- @gongzili456 for motorcycle version
- @ben-29 for different types support
- @geekplux for different types support
Just enjoy it~
https://www.strava.com/settings/api https://developers.strava.com/docs/#rate-limiting
Strava API Rate Limit Exceeded. Retry after 100 seconds
Strava API Rate Limit Timeout. Retry in 799.491622 seconds