Skip to content

yihong0618/running_page

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Note

  1. clone or Fork before vercel 404 need to pull the latest code
  2. python3(python) in README means python3 python
  3. use v2.0 need change vercel setting from gatsby to vite
  4. 2023.09.26 garmin need secret_string(and in Actions) get
  python run_page/get_garmin_secret.py ${email} ${password}
  # if cn
  python run_page/get_garmin_secret.py ${email} ${password} --is-cn

Github Action Chat on telegram

demo

English | 简体中文 | Wiki

Running page runners
Runner page App
zhubao315 https://zhubao315.github.io/running Strava
shaonianche https://run.duanfei.org Strava
yihong0618 https://yihong.run Nike
superleeyom https://running.leeyom.top Strava
geekplux https://activities.geekplux.com Nike
guanlan https://grun.vercel.app Strava
tuzimoe https://run.tuzi.moe Nike
ben_29 https://running.ben29.xyz Strava
kcllf https://running-tau.vercel.app Garmin-cn
mq https://running-iota.vercel.app Keep
zhaohongxuan https://zhaohongxuan.github.io/workouts Strava
yvetterowe https://run.haoluo.io Strava
love-exercise https://run.kai666666.top Keep
zstone12 https://running-page.zstone12.vercel.app Keep
Lax https://lax.github.io/running Keep
lusuzi https://running.lusuzi.vercel.app Nike
wh1994 https://run4life.fun Garmin
liuyihui https://run.foolishfox.cn Keep
sunyunxian https://sunyunxian.github.io/running_page Strava
AhianZhang https://running.ahianzhang.com Nike
L1cardo https://run.licardo.cn Nike
luckylele666 https://0000928.xyz Strava
MFYDev https://mfydev.run Garmin-cn
Eished https://run.iknow.fun Keep
Liuxin https://liuxin.run Nike
loucx https://loucx.github.io/running Nike
winf42 https://winf42.github.io Garmin-cn
sun0225SUN https://run.sunguoqi.com Nike
Zhan https://run.zlog.in Nike
Dennis https://run.domon.cn Garmin-cn
hanpei https://running.nexts.top Garmin-cn
liugezhou https://run.liugezhou.online Strava
Jason Tan https://jason-cqtan.github.io/running_page Nike
Conge https://conge.github.io/running_page Strava
zHElEARN https://workouts.zhelearn.com Strava
Ym9i https://bobrun.vercel.app/ Strava
jianchengwang https://jianchengwang.github.io/running_page Suunto
fxbin https://fxbin.github.io/sport-records/ Keep
shensl4499 https://waner.run codoon
haowei93 https://running-fun.eu.org gpx
stevenash0822 https://run.imangry.xyz/ Strava
Vint https://vinton.store/Running/ Keep
Muyids https://muyids.github.io/running Garmin-cn
Gao Hao https://efish2002.github.io/running_page/ Garmin-cn
Jinlei https://jinlei.run/ 咕咚
RealTiny656 https://tiny656.github.io/running_page/ JoyRun
EINDEX https://workouts.eindex.me/ Strava/Nike
Melt https://running.autove.dev/ Strava
deepinwine https://deepin.autove.dev/ Garmin-cn
Echo https://donghao526.github.io/running JoyRun
Jeffggmm https://jeffggmm.github.io/workouts_page/ Garmin
s1smart https://s1smart.github.io/running_page/ Strava
XmchxUp https://xmchxup.github.io/running_page/ Strava
Ryan https://85ryan.github.io/gooorun/ Strava
PPZ https://run.dudubbbbbbbbb.top/ Strava
Yer1k https://running.yer1k.com/ Strava
AlienVision https://run.drink.cafe/ Strava
闻笑忘 https://wenxiaowan.com 苹果健身
Vensent https://vensent.github.io/workouts_page/ Garmin
Zeonsing https://run.jogzeal.com/ Coros
yaoper https://running.yaoper.cn codoon
laqieer https://laqieer.github.io/running_page/ Strava
Guoxin https://running.guoxin.space/ Strava
laihj https://run.laihjx.com/ 苹果健身
Ginta https://running.ginta.top/ Keep
Samuel https://samueldixxon.github.io/running_page/ Keep

How it works

image

Features

  1. GitHub Actions automatically synchronizes running data and generates page displays
  2. Support for Vercel (recommended) and GitHub Pages automated deployment
  3. React Hooks
  4. Mapbox for map display
  5. 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.

Support

Download

Clone or fork the repo.

git clone https://github.com/yihong0618/running_page.git --depth=1

Installation and testing (node >= 20 python >= 3.11)

pip3 install -r requirements.txt
npm install -g corepack && corepack enable && pnpm install
pnpm develop

Open your browser and visit http://localhost:5173/

Docker

# 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

Local sync data

Modifying Mapbox token

If you use English please change IS_CHINESE = false in src/utils/const.ts
Suggested changes to your own Mapbox token

const MAPBOX_TOKEN =
  'pk.eyJ1IjoieWlob25nMDYxOCIsImEiOiJja2J3M28xbG4wYzl0MzJxZm0ya2Fua2p2In0.PNKfkeQwYuyGOTT_x9BJ4Q';

Custom your page

  • Find 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',
    },
  ],
},
  • Modifying styling in 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
// update for now 2024/11/17 the privacy mode is true
const PRIVACY_MODE = true;
// update for now 2024/11/17 the lights on default is false
// styling: set to `false` if you want to make light off as default, only effect when `PRIVACY_MODE` = false
const LIGHTS_ON = false;
  • To use Google Analytics, you need to modify the configuration in the 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

Download your running data and do not forget to generate svg in total page

GPX

Make your GPX data

Copy all your gpx files to GPX_OUT or new gpx files

python3(python) run_page/gpx_sync.py

TCX

Make your TCX data

Copy all your tcx files to TCX_OUT or new tcx files

python3(python) run_page/tcx_sync.py

FIT

Make your FIT data

Copy all your tcx files to FIT_OUT or new fit files

python3(python) run_page/fit_sync.py

Garmin

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
  • If you are using Garmin as a data source, it is recommended that you pull the code to your local environment to run and obtain the Garmin secret. The Python version must be >=3.8

Get Garmin Secret

Enter the following command in the terminal

# to get secret_string
python3(python) run_page/get_garmin_secret.py ${your email} ${your password}

Execute Garmin Sync Script

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(China)

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
  • If you are using Garmin as a data source, it is recommended that you pull the code to your local environment to run and obtain the Garmin secret. The Python version must be >=3.10

Get Garmin CN Secret

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

get_garmin_cn_secret

Execute Garmin CN Sync Script

Copy the Secret output in the terminal,If you are using Github, please configure GARMIN_SECRET_STRING_CN in Github Action. get_garmin_secret

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 to Garmin

Sync your Garmin-CN data to Garmin
  • If you only want to sync type running add args --only-run The Python version must be >=3.10

Get Garmin CN Secret

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

Get Garmin Secret

Enter the following command in the terminal

# to get secret_string
python3(python) run_page/get_garmin_secret.py ${your email} ${your password}

Sync Garmin CN to Garmin

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 New

Get your Nike Run Club data

Please note:Due to the discontinuation of Nike Run Club in mainland China, you can only log in through a VPN. Before starting, please ensure that you are using a global non-mainland China proxy, allowing you to access nike.com instead of nike.com.cn, as shown in the following image.

nike.com

  1. Sign in/Sign up NikeRunClub account login
  2. after successful login,openF12->Application->localstorage-> copy the content of "access_token" from the value of keyhttps://www.nike.com.
  3. Execute in the root directory , you should be able to see the image below, and then you can log into your account on the mobile as usual:
python3(python) run_page/nike_sync.py ${access_token}

tg_image_166091873

if you want to automate the submission of NRC data, you can refer to issue692.

If you've previously synced activities and want to continue syncing new ones, with --continue-sync args

python3(python) run_page/nike_sync.py ${access_token} --continue-sync

Nike Run Club

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

ALL need to do outside GFW

example img

  1. Login from this website, open F12 -> XHR -> get the refresh_token from login api.

  2. copy this refresh_token and use it in GitHub Secrets or in command line

  3. Execute in the root directory:

python3(python) run_page/nike_sync.py ${nike refresh_token}

example:

python3(python) run_page/nike_sync.py eyJhbGciThiMTItNGIw******

example img

Strava

Get your Strava data
  1. Sign in/Sign up Strava account
  2. Open after successful Signin Strava Developers -> Create & Manage Your App
  3. Create My API Application: Enter the following information

My API Application

Created successfully:


  1. Use the link below to request all permissions: Replace ${your_id} in the link with My API Application Client ID
https://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

get_all_permissions

  1. Get the code value in the link

example:

http://localhost/exchange_token?state=&code=1dab37edd9970971fb502c9efdd087f4f3471e6e&scope=read,activity:write,activity:read_all,profile:write,profile:read_all,read_all

code value:

1dab37edd9970971fb502c9efdd087f4f3471e6

get_code

  1. Use Client_idClient_secretCode 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

get_refresh_token

  1. 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) run_page/strava_sync.py ${client_id} ${client_secret} ${refresh_token}

References:

TCX_to_Strava

upload all tcx files to strava
  1. follow the strava steps
  2. copy all your tcx files to TCX_OUT
  3. Execute in the root directory:
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
  1. if you want to all files add args --all

TCX_to_Garmin

upload all tcx files to garmin
  1. follow the garmin steps
  2. copy all your tcx files to TCX_OUT
  3. Execute in the root directory:
python3 run_page/tcx_to_garmin_sync.py ${{ secrets.GARMIN_SECRET_STRING_CN }} --is-cn

example:

python run_page/tcx_to_garmin_sync.py xxx --is-cn
or Garmin Global
python run_page/tcx_to_garmin_sync.py xxx
  1. if you want to all files add args --all

GPX_to_Strava

upload all gpx files to strava
  1. follow the strava steps
  2. copy all your gpx files to GPX_OUT
  3. Execute in the root directory:
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
  1. if you want to all files add args --all

Nike_to_Strava

Get your Nike Run Club data and upload to strava
  1. follow the nike and strava steps
  2. Execute in the root directory:
python3(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_to_Strava

Get your Garmin data and upload to strava
  1. finish garmin and strava setup
  2. Execute in the root directory:
python3(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_to_Garmin

Get your Strava data and upload to Garmin
  1. finish garmin and strava setup, at the same time, you need to add additional strava config in Github Actions secret: secrets.STRAVA_EMAIL,secrets.STRAVA_PASSWORD
  2. Execute in the root directory:
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.

image

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.

Coros

Get your Coros data

Enter the following command in the terminal

python run_page/coros_sync.py 'your coros account' 'your coros password'

Modify run_data_sync.yml env.RUN_TYPE: coros

Set the Coros account information in github action

  • configure the COROS_ACCOUNT , COROS_PASSWORD

    github-action

Total Data Analysis

Running data display
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

server(recommendation vercel)

Use Vercel to deploy
  1. vercel connects to your GitHub repo.

image

  1. import repo

image

  1. Awaiting completion of deployment
  2. Visits
Use Cloudflare to deploy
  1. Login to Cloudflare dashboard.

  2. Click Workers & Pages on the left side.

  3. Click Create application and select Pages tab, connect your GitHub account and select running_page Repo, then click Begin setup.

  4. Scroll down to Build settings, choose Create React App from Framework preset, and set Build output directory to dist.

  5. Scroll down, click Environment variables (advanced), then add a variable like the below:

    Variable name = PYTHON_VERSION, Value = 3.11

  6. Click Save and Deploy

Deploy to GitHub Pages
  1. Go to repository's Settings -> GitHub Pages -> Source, choose GitHub Actions

  2. Go to the repository's Actions -> Workflows -> All Workflows, choose Run Data Sync from the left panel, and click Run workflow.

  • The Run Data Sync will update data and then trigger the Publish GitHub Pages workflow
  • Make sure the workflow runs without errors.
  1. Open your website to check on the results
  • note if the website doesn't reflect the latest data, please refresh it by F5.
  • Some browsers (e.g. Chrome) won't refresh if there is a cache, you then need to use Ctrl+F5 (Windows) or Shift+Cmd+r (Mac) to force clearing the cache and reload the page.
  1. make sure you have write permissions in Workflow permissions settings.

  2. 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:

  • Rename your forked running_page repository to xxx.github.io, where xxx is your GitHub username
  • Modify the Build module in gh-pages.yml, remove ${{ github.event.repository.name }} and change to run: PATH_PREFIX=/ pnpm build
  • In src/static/site-metadata.ts, set siteUrl: '' or your custom domain URL

GitHub Actions

Modifying information in GitHub Actions

Actions source code The following steps need to be taken

  1. change to your app type and info

image

  1. Add your secret in repo Settings > Secrets (add only the ones you need).

image

  1. My secret is as follows

image

  1. Go to repository's Settings -> Code and automation -> Actions ->General, Scroll to the bottom, find Workflow permissions, choose the first option Read and write permissions, click Save.

Shortcuts

Automate with iOS Shortcuts

Take the keep app as an example. Close the app after running, and then automatically trigger Actions to update the data.

  1. Get actions id (need to apply token)
curl https://api.github.com/repos/yihong0618/running_page/actions/workflows -H "Authorization: token d8xxxxxxxxxx" # change to your config
get-action-id
  1. Binding shortcut instruction

    1. Get it via icloud running-page-shortcuts-template

    2. Modify the dictionary parameters in the following figure

  2. Automation

Storing Data Files in GitHub Cache

Storing Data Files in GitHub Cache

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.

Fit file

supported manufacturer:

  • Garmin
  • magene

TODO

  • 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

Contribution

  • 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 .)

Special thanks

Recommended Forks

Support

Just enjoy it~

Raycast Extension

FAQ