Make your own running home page
python run_page/get_garmin_secret.py ${email} ${password}
# if cn
python run_page/get_garmin_secret.py ${email} ${password} --is-cn
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.
Clone or fork the repo.
git clone https://github.com/yihong0618/running_page.git --depth=1
pip3 install -r requirements.txt
npm install -g corepack && corepack enable && pnpm install
pnpm develop
Open your browser and visit http://localhost:5173/
# 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 secret_string=""
# Garmin-CN
docker build -t running_page:latest . --build-arg app=Garmin-CN --build-arg secret_string=""
# 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=""
# Keep
docker build -t running_page:latest . --build-arg app=Keep --build-arg keep_phone_number="" --build-arg keep_password=""
# 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.ts
Suggested changes to your own Mapbox token
const MAPBOX_TOKEN =
'pk.eyJ1IjoieWlob25nMDYxOCIsImEiOiJja2J3M28xbG4wYzl0MzJxZm0ya2Fua2p2In0.PNKfkeQwYuyGOTT_x9BJ4Q';
src/static/site-metadata.ts
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',
},
],
},
src/utils/const.ts
// 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;
// styling: set to `true` if you want to display only the routes without showing the map
// Note: This config only affects the page display; please refer to "privacy protection" below for data protection
const PRIVACY_MODE = false;
// styling: set to `false` if you want to make light off as default, only effect when `PRIVACY_MODE` = false
const LIGHTS_ON = true;
src/utils/const.ts
file.const USE_GOOGLE_ANALYTICS = false;
const GOOGLE_ANALYTICS_TRACKING_ID = '';
privacy protection,setting flowing env:
# ignore distance for each polyline start and end.
IGNORE_START_END_RANGE = 200
# ignore meters for each point in below polyline.
IGNORE_RANGE = 200
# a polyline include point you want to ignore.
IGNORE_POLYLINE = ktjrFoemeU~IorGq}DeB
# 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 Google map
Interactive Polyline Encoder Utility
, to making your IGNORE_POLYLINE
.
Download your running data and do not forget to generate svg in
total
page
GPX
dataCopy all your gpx files to GPX_OUT or new gpx files
python3(python) run_page/gpx_sync.py
TCX
dataCopy all your tcx files to TCX_OUT or new tcx files
python3(python) run_page/tcx_sync.py
FIT
dataCopy all your tcx files to FIT_OUT or new fit files
python3(python) run_page/fit_sync.py
Garmin
datatype running
add args --only-runtcx
files add args --tcxfit
files add args --fitEnter the following command in the terminal
# to get secret_string
python3(python) run_page/get_garmin_secret.py ${your email} ${your password}
Copy the Secret output in the terminal,If you are using Github, please configure GARMIN_SECRET_STRING in Github Action
.
# use this secret_string
python3(python) run_page/garmin_sync.py ${secret_string}
example:
python3(python) run_page/get_garmin_secret.py xxxxxxxxxxx
only-run:
python3(python) run_page/garmin_sync.py xxxxxxxxxxxxxx(secret_string) --only-run
Garmin-CN
datatype running
add args --only-runtcx
files add args --tcxfit
files add args --fitEnter the following command in the terminal
# to get secret_string
python3(python) run_page/get_garmin_secret.py ${your email} ${your password} --is-cn
Copy the Secret output in the terminal,If you are using Github, please configure GARMIN_SECRET_STRING_CN in Github Action.
example:
python3(python) run_page/garmin_sync.py xxxxxxxxx(secret_string) --is-cn
only-run:
python3(python) run_page/garmin_sync.py xxxxxxxxxxxxxx(secret_string) --is-cn --only-run
Garmin-CN
data to Garmin
type running
add args --only-run
The Python version must be >=3.10
Enter the following command in the terminal
# to get secret_string
python3(python) run_page/get_garmin_secret.py ${your email} ${your password} --is-cn
Enter the following command in the terminal
# to get secret_string
python3(python) run_page/get_garmin_secret.py ${your email} ${your password}
Enter the following command in the terminal
# to sync garmin-cn to garmin-global
python3(python) run_page/garmin_sync_cn_global.py ${garmin_cn_secret_string} ${garmin_secret_string}
Nike Run Club
dataPlease 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
ALL need to do outside GFW
Login from this website, open F12 -> XHR -> get the refresh_token
from login api.
copy this refresh_token
and use it in GitHub Secrets or in command line
Execute in the root directory:
python3(python) run_page/nike_sync.py ${nike refresh_token}
example:
python3(python) run_page/nike_sync.py eyJhbGciThiMTItNGIw******
Strava
data My API Application
: Enter the following informationCreated successfully:
${your_id}
in the link with My API Application
Client IDhttps://www.strava.com/oauth/authorize?client_id=${your_id}&response_type=code&redirect_uri=http://localhost/exchange_token&approval_prompt=force&scope=read_all,profile:read_all,activity:read_all,profile:write,activity:write
Example:
https://www.strava.com/oauth/authorize?client_id=115321&response_type=code&redirect_uri=http://localhost/exchange_token&approval_prompt=force&scope=read_all,profile:read_all,activity:read_all,profile:write,activity:write
code
value in the linkexample:
http://localhost/exchange_token?state=&code=1dab37edd9970971fb502c9efdd087f4f3471e6e&scope=read,activity:write,activity:read_all,profile:write,profile:read_all,read_all
code
value:
1dab37edd9970971fb502c9efdd087f4f3471e6
Client_id
、Client_secret
、Code
get refresh_token
: Execute in Terminal/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
Strava
dataThe 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) run_page/strava_sync.py ${client_id} ${client_secret} ${refresh_token}
References:
python3(python) run_page/tcx_to_strava_sync.py ${client_id} ${client_secret} ${strava_refresh_token}
example:
python3(python) run_page/tcx_to_strava_sync.py xxx xxx xxx
or
python3(python) run_page/tcx_to_strava_sync.py xxx xxx xxx --all
--all
python3(python) run_page/gpx_to_strava_sync.py ${client_id} ${client_secret} ${strava_refresh_token}
example:
python3(python) run_page/gpx_to_strava_sync.py xxx xxx xxx
or
python3(python) run_page/tcx_to_strava_sync.py xxx xxx xxx --all
--all
Nike Run Club
data and upload to stravapython3(python) run_page/nike_to_strava_sync.py ${nike_refresh_token} ${client_id} ${client_secret} ${strava_refresh_token}
example:
python3(python) run_page/nike_to_strava_sync.py eyJhbGciThiMTItNGIw****** xxx xxx xxx
Garmin
data and upload to stravapython3(python) run_page/garmin_to_strava_sync.py ${client_id} ${client_secret} ${strava_refresh_token} ${garmin_secret_string} --is-cn
e.g.
python3(python) run_page/garmin_to_strava_sync.py xxx xxx xxx xx
Strava
data and upload to Garminsecrets.STRAVA_EMAIL
,secrets.STRAVA_PASSWORD
python3(python) run_page/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }} ${{ secrets.GARMIN_SECRET_STRING }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }}
if your garmin account region is China, you need to execute the command:
python3(python) run_page/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }} ${{ secrets.GARMIN_SECRET_STRING_CN }} ${{ 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.
the final command will be:
python3(python) run_page/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }} ${{ secrets.GARMIN_SECRET_STRING_CN }} ${{ 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.
python run_page/coros_sync.py 'your coros account' 'your coros password'
run_data_sync.yml
env.RUN_TYPE: corosconfigure the COROS_ACCOUNT
, COROS_PASSWORD
python run_page/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 run_page/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) run_page/gen_svg.py --from-db --type circular --use-localtime
For more display effects, see: https://github.com/flopp/GpxTrackPoster
Vercel
to deploy Cloudflare
to deploy Login to Cloudflare dashboard.
Click Workers & Pages
on the left side.
Click Create application
and select Pages
tab, connect your GitHub account and select running_page
Repo, then click Begin setup
.
Scroll down to Build settings
, choose Create React App
from Framework preset
, and set Build output directory
to dist
.
Scroll down, click Environment variables (advanced)
, then add a variable like the below:
Variable name =
PYTHON_VERSION
, Value =3.7
Click Save and Deploy
Go to repository's Settings -> GitHub Pages -> Source
, choose GitHub Actions
Go to the repository's Actions -> Workflows -> All Workflows
, choose Run Data Sync
from the left panel, and click Run workflow
.
Run Data Sync
will update data and then trigger the Publish GitHub Pages
workflowF5
.Ctrl+F5
(Windows) or Shift+Cmd+r
(Mac) to force clearing the cache and reload the page.make sure you have write permissions in Workflow permissions settings.
If you want to deploy your running_page to xxx.github.io instead of xxx.github.io/running_page or redirect your GitHub Pages to a custom domain, you need to do three things:
xxx.github.io
, where xxx is your GitHub username${{ github.event.repository.name }}
and change to run: PATH_PREFIX=/ pnpm build
src/static/site-metadata.ts
, set siteUrl: '' or your custom domain URL GitHub Actions
Actions source code The following steps need to be taken
Settings -> Code and automation -> Actions ->General
, Scroll to the bottom, find Workflow permissions
, choose the first option Read and write permissions
, click Save
. iOS Shortcuts
Take the keep app as an example. Close the app after running, and then automatically trigger Actions to update the data.
curl https://api.github.com/repos/yihong0618/running_page/actions/workflows -H "Authorization: token d8xxxxxxxxxx" # change to your config
Binding shortcut instruction
Get it via icloud running-page-shortcuts-template
Modify the dictionary parameters in the following figure
Automation
When SAVE_DATA_IN_GITHUB_CACHE
is set to true
in the run_data_sync.yml
file, the script can store fetched and intermediate data files in the GitHub Action Cache. This helps keep your GitHub commit history and directory clean.
If you are deploying using GitHub Pages, it is recommended to set this value to true
, and set BUILD_GH_PAGES
to true.
supported manufacturer:
Before submitting PR:
black
(black .
)Just enjoy it~
Strava Api limit
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
vercel git ignore gh-pages:
you can change settings -> build -> Ignored Build Step -> Custom command
if [ "$VERCEL_GIT_COMMIT_REF" != "gh-pages" ]; then exit 1; else exit 0;