This repo contains the website for Race Condition Running http://raceconditionrunning.com/
You should use virtual environments to isolate dependencies for Python.
uv
is a great way to simplify dependency
and virtual environment management, and it enables you to use per-project
Python versions.
- Install
uv
. Runuv help
to make sure your installation was successful. - Run:
uv sync
andbundle install
. - Install
entr
, either via running:brew install entr
(for macOS) orsudo apt install entr
.
After you've installed the Python (uv sync
),
Ruby (bundle install
) dependencies and entr
(see section above for commands),
run:
make serve
From the root of this directory.
A successful deployment will serve a local instance of raceconditionrunning.github.io
on http://localhost:4000.
The live site is built and deployed by a GitHub action and served by GitHub pages.
Schedules are YAML files stored in the _data/schedules/
directory. Each schedule contains a list of plans. Check out the long-run scheduler if you'd like to automatically generate a schedule.
A plan represents a long run that may be broken into multiple legs. While uncommon, there can be multiple distinct plans on the same day.
Each plan is a dictionary containing:
date
- Date inYYYY-MM-DD
formatplan
- List of leg dictionaries (see below)highlight_image
- (Optional) Absolute path to an image displayed inline with the plannotes
- (Optional) String displayed as a note for the plan
Each leg in a plan's plan
list contains:
time
- Start time in 24-hour format (HH:MM
)route
ORroute_id
- Route information (see Route Options below)
You can specify routes in two ways:
Option 1: Reference existing route
route_id
- String key matching a route in_data/routes.yml
Option 2: Inline route definition
route
- Dictionary containing:name
- Route name (string)map
- Web map URL (string)distance_mi
- Distance in miles (float)
Both plans and individual legs can include a cancelled
key:
- Any value (including empty string) causes strikethrough display
- The value content is shown as the cancellation reason
Add a GPX file to the routes/_gpx/
directory. The build will fail with a descriptive error if any route doesn't meet the minimum formatting requirements which get checked by _bin/make_routes_table.py
.
- The file's
<gpx>
tag must include the RCR extension:<gpx xmlns="http://www.topografix.com/GPX/1/1" version="1.1" creator="Race Condition Running" xmlns:rcr="http://raceconditionrunning.com/extensions">
<name>
- lowercase, hyphenated name of the route. Ends withloop
if the route is a loop orob
if the route is an out-and-back.<desc>
- The presentation name of the route, e.g. "Lake Union Loop".- You must include an
<extensions>
tag in the<metadata>
section, with<rcr:last_updated>YYYY-MM-DD</rcr:last_updated>
.
Before you commit changes to a route, run make normalize-routes-in-place
to ensure the route is formatted correctly.
To supply elevation data, run make replace-route-elevations
and make normalize-routes-in-place
.
If your route starts or ends at a new location, add a new feature to the routes/locations.json
file.
Here are the concrete steps for making and adding routes to the repo:
-
Make a new route via OnTheGoMap. Please be careful when making them, pay attention, think carefully whether the route is actually runnable and safe. For example, if a route involves running alongside traffic (i.e., on the shoulder of a road) for long stretches, it is likely not very safe. Use Street View on Google Maps to help scope out a run.
-
Go to the hamburger menu at the top-right corner of OnTheGoMap and select "Export as GPX". Save the "shortened link" of the route for later use in Step 4 for
rcr:map
). -
Move the GPX file to
routes/_gpx
and give it a name based on its type (e.g., out-and-back, point-to-point, loop, etc.) and where it starts and what main areas it goes through. If the route is a loop, put-loop
and if it is an out-and-back, put-ob
at the end. -
Edit the GPX (which is just XML) like so: from any existing route in
routes/_gpx
, take all the content down to the<trkseg>
tag and replace all the content in the original GPX file up until the start of<trkseg>
with it. Then modify the fields specific to the route. This includes:- metadata
name
(same as GPX file name) - metadata
desc
- metadata
link
includingtext
- Only
rcr:map
andrcr:last_updated
underextensions
- track
name
(same as GPX file name) - track
desc
- metadata
-
Run
./_bin/gpx-inplace-fixup.sh routes/_gpx/recently-added-route.gpx
to add elevation data to the route. Make sure you have python installed since this script invokes other python scripts. -
Follow the instructions for
Building and Developing Locally
. Then runmake serve
to check that it works locally and the site looks right. -
If you are making more than one route, commit and push once for batching. The CI build is somewhat slow.
_bin/mkical.py
generates an iCalendar file for the current schedule.- Routes are in
_data/routes.yml
. - The current schedule is in
_data/schedule.yml
. This is a symlink to the current season's schedule in_data/schedules/
. - To create a new brunch review, add a new file to the
_brunch-reviews
folder.
Use ImageMagick to compress images. Converting to high quality AVIF with a max edge length of 2000 works well:
mogrify -quality 90 -resize 2000x2000 -format avif -auto-orient *.jpg