Connect Garmin
Sign in to Garmin Connect once. Run315 keeps the session token only — your password is never stored.
Start list
Projections update on every sync
| Race | Date | Result | Projected | Gap |
|---|---|---|---|---|
| Club parkrun | 2026-09-05 | 19:29 | 19:37 | −0:08 |
| Riverside Half | 2026-07-13 | 1:37:22 | 1:36:00 | +1:22 |
| Spring 10K | 2026-06-01 | 42:31 | 42:00 | +0:31 |
Calibrated on 3 past results: you have run slower than projected by 1.1% on average, so projections are adjusted +0.6%.
This week
Since Monday 07 Sep
This morning
2026-09-06 · High confidence
Train as planned, and keep the easy running properly easy. Based on HRV, resting heart rate, sleep quality and training load.
Heat
0 hot runs in the last fortnight
Nothing recent in the heat. A hot race would cost you more than the pace adjustment on this page suggests.
Ten to fourteen days of running in the heat produces real adaptation, most of it in the first week, and it fades within a few weeks of stopping. This is bookkeeping on your exposure, not a measurement of your blood plasma.
How hard you train
Last 12 weeks · Pyramidal · PI 4.4
Pyramidal: 89% easy, tapering through 3% moderate to 8% hard. A broad base with a point on it -- blunter than polarised, and it works, particularly early in a build.
intvl · territory
Fitness and freshness
Last 180 days
If you raced today
| Distance | Projected | Pace |
|---|---|---|
| 5K | 19:10 | 3:50 /km |
| 10K | 41:52 | 4:11 /km |
| 15K | 1:06:07 | 4:24 /km |
| 10 mi | 1:11:35 | 4:27 /km |
| Half marathon | 1:37:07 | 4:36 /km |
| Marathon | 3:32:07 | 5:02 /km |
| 50K | 4:16:49 | 5:08 /km |
Efforts driving the model
| Distance | Time | Pace | Ago |
|---|---|---|---|
| 5.00 km | 19:23 | 3:53 /km | 142d |
| 11.83 km | 48:47 | 4:07 /km | 5d |
| 13.13 km | 59:29 | 4:32 /km | 44d |
Fatigue exponent 1.127 — you fade more than average over distance.
Your pace curve
Measured inside runs
Personal records
Last 180 days
| Distance | Best | Pace | Set |
|---|---|---|---|
| 0.40 km | 1:27 | 3:38 /km | 2026-04-22 |
| 0.80 km | 2:54 | 3:38 /km | 2026-04-22 |
| 1.00 km | 3:45 | 3:45 /km | 2026-04-22 |
| 1.61 km | 6:14 | 3:53 /km | 2026-04-18 |
| 3.00 km | 11:38 | 3:53 /km | 2026-04-18 |
| 5.00 km | 19:23 | 3:53 /km | 2026-04-18 |
| 10.00 km | 41:19 | 4:08 /km | 2026-09-02 |
| 15.00 km | 1:10:16 | 4:41 /km | 2026-09-06 |
| 16.09 km | 1:15:37 | 4:42 /km | 2026-09-06 |
| 21.10 km | 1:40:04 | 4:45 /km | 2026-09-06 |
Your training paces
From today's fitness
| Type | Pace range |
|---|---|
| Easy Most of your week. Conversational. |
5:35–6:14 /km |
| Marathon Race-pace work for the long stuff. |
4:35–4:51 /km |
| Threshold Tempo and cruise intervals. ~1 hour race effort. |
4:16–4:27 /km |
| Interval VO2max work. 3-5 minute reps. |
4:00–4:12 /km |
| Repetition Speed and economy. 200-600m reps. |
3:46–3:58 /km |
Anchored on 4:22 /km, the pace your curve says you could hold for an hour.
Heart rate zones
On threshold 175 bpm
| Zone | Range |
|---|---|
| Z1 Recovery | under 142 bpm |
| Z2 Aerobic | 142–158 bpm |
| Z3 Tempo | 158–164 bpm |
| Z4 Threshold | 164–175 bpm |
| Z5 VO2max | 175–201 bpm |
Coach review
Have Claude read your load, your best efforts and your race calendar, then say what to change over the next four weeks.
Cowork with an agent
Hand your load, best efforts and races to an agent through a folder on this device — CoworkSyncHub, Claude Desktop, or a person. Nothing is uploaded and no key is needed.
Training log
Last 26 weeks · darker is a harder day
Recent activity
| Date | Activity | Distance | Time | Pace / speed | HR |
|---|---|---|---|---|---|
| 06 Sep | Run · running | 25.45 km | 2:01:20 | 4:46 /km | 147 |
| 05 Sep | Run · running | 5.00 km | 19:29 | 3:54 /km | 182 |
| 03 Sep | Bike · cycling | 50.05 km | 1:45:20 | 28.5 km/h | 128 |
| 03 Sep | Run · running | 8.67 km | 43:11 | 4:59 /km | 145 |
| 02 Sep | Run · running | 11.83 km | 48:47 | 4:07 /km | 170 |
| 01 Sep | Run · running | 8.19 km | 40:35 | 4:57 /km | 140 |
| 30 Aug | Run · running | 19.55 km | 1:33:57 | 4:48 /km | 148 |
| 29 Aug | Run · running | 12.20 km | 54:01 | 4:26 /km | 162 |
| 27 Aug | Bike · cycling | 48.88 km | 1:51:45 | 26.2 km/h | 123 |
| 27 Aug | Run · running | 10.01 km | 49:51 | 4:59 /km | 139 |
| 26 Aug | Run · running | 10.76 km | 44:43 | 4:09 /km | 171 |
| 25 Aug | Run · running | 8.04 km | 40:05 | 4:59 /km | 144 |
| 23 Aug | Run · running | 20.19 km | 1:37:34 | 4:50 /km | 151 |
| 22 Aug | Run · running | 11.71 km | 52:06 | 4:27 /km | 168 |
| 20 Aug | Bike · cycling | 49.43 km | 1:40:39 | 29.5 km/h | 129 |
, so #frozen-note // does not exist yet while this script is being parsed. addEventListener('DOMContentLoaded', function () { if (document.getElementById('frozen-note')) return; // the static demo reports nothing try { var ids = JSON.parse(document.getElementById('portal-runs').textContent || '[]'); var secs = JSON.parse(document.getElementById('portal-run-mins').textContent || '[]'); var seenKey = 'run315-portal-seen'; var seen = JSON.parse(localStorage.getItem(seenKey) || '[]'); var k = 'portal-activity', log = JSON.parse(localStorage.getItem(k) || '[]'); var added = 0; for (var i = 0; i < ids.length; i++) { if (seen.indexOf(ids[i]) >= 0) continue; seen.push(ids[i]); log.push([Math.round(Date.now() / 1000), 'Run315', 'cardio', Math.max(1, Math.round((secs[i] || 0) / 600))]); added++; } if (added) { localStorage.setItem(k, JSON.stringify(log.slice(-2000))); localStorage.setItem(seenKey, JSON.stringify(seen.slice(-500))); } } catch (e) { /* quota or private mode - ignore */ } }); , so the check has to wait for the parsed document. addEventListener('DOMContentLoaded', function () { try { var dm = ['standalone', 'minimal-ui', 'fullscreen', 'window-controls-overlay']; if (!document.getElementById('frozen-note') && (navigator.standalone || dm.some(function (m) { return matchMedia('(display-mode: ' + m + ')').matches; }))) { var pk = 'portal-installed', reg = JSON.parse(localStorage.getItem(pk) || '{}'); reg.Run315 = Date.now(); localStorage.setItem(pk, JSON.stringify(reg)); } } catch (e) { /* private mode - ignore */ } }); // Installable, and readable on the train. See templates/sw.js. if ('serviceWorker' in navigator) { addEventListener('load', function () { navigator.serviceWorker.register('/Run315/sw.js'); }); }