Index: ow/models/user.py
===================================================================
--- ow/models/user.py	(revision aa6dcaf57b89932ac36aa1a2f4348657dcc13339)
+++ ow/models/user.py	(revision 04c882dbb6a6a21c6e6c84e0dbfb4ddf31faefa4)
@@ -405,5 +405,12 @@
             'distance': Decimal(0),
             'elevation': Decimal(0),
+            'max_time': timedelta(0),
+            'max_time_wid': None,
+            'max_distance': Decimal(0),
+            'max_distance_wid': None,
+            'max_elevation': Decimal(0),
+            'max_elevation_wid': None
         }
+
         if self.activity_sports:
             sport = sport or self.favorite_sport
@@ -411,7 +418,21 @@
                 if workout.sport == sport:
                     if year is None or workout.start.year == year:
+                        wid = str(workout.workout_id)
+                        time = workout.duration or timedelta(0)
+                        distance = workout.distance or Decimal(0)
+                        elevation = workout.uphill or Decimal(0)
                         totals['workouts'] += 1
-                        totals['time'] += workout.duration or timedelta(0)
-                        totals['distance'] += workout.distance or Decimal(0)
-                        totals['elevation'] += workout.uphill or Decimal(0)
+                        totals['time'] += time
+                        totals['distance'] += distance
+                        totals['elevation'] += elevation
+                        if time > totals['max_time']:
+                            totals['max_time'] = time
+                            totals['max_time_wid'] = wid
+                        if distance > totals['max_distance']:
+                            totals['max_distance'] = distance
+                            totals['max_distance_wid'] = wid
+                        if elevation > totals['max_elevation']:
+                            totals['max_elevation'] = elevation
+                            totals['max_elevation_wid'] = wid
+
         return totals
Index: ow/static/css/main.css
===================================================================
--- ow/static/css/main.css	(revision aa6dcaf57b89932ac36aa1a2f4348657dcc13339)
+++ ow/static/css/main.css	(revision 04c882dbb6a6a21c6e6c84e0dbfb4ddf31faefa4)
@@ -1490,4 +1490,17 @@
   color: #151515;
 }
+.profile-data li a {
+  color: #EE4056;
+  text-decoration: none;
+}
+.profile-data li a:hover {
+  color: #151515;
+}
+.profile-data li a:active,
+.profile-data li a:focus {
+  outline: 0;
+  border: none;
+  -moz-outline-style: none;
+}
 .profile-bio {
   margin: 0.5em 0;
Index: ow/static/less/pages/profile.less
===================================================================
--- ow/static/less/pages/profile.less	(revision aa6dcaf57b89932ac36aa1a2f4348657dcc13339)
+++ ow/static/less/pages/profile.less	(revision 04c882dbb6a6a21c6e6c84e0dbfb4ddf31faefa4)
@@ -90,4 +90,16 @@
 			color: @color-main;
 		}
+                a {
+                    color: @color-app;
+                    text-decoration: none;
+                    &:hover {
+	                color: @color-main;
+                    }
+                    &:active, &:focus {
+                        outline: 0;
+                        border: none;
+                        -moz-outline-style: none;
+                    }
+                }
 	}
 }
Index: ow/templates/profile.pt
===================================================================
--- ow/templates/profile.pt	(revision aa6dcaf57b89932ac36aa1a2f4348657dcc13339)
+++ ow/templates/profile.pt	(revision 04c882dbb6a6a21c6e6c84e0dbfb4ddf31faefa4)
@@ -253,4 +253,36 @@
                         <tal:t i18n:translate="">m</tal:t>
                       </li>
+                      <li><span i18n:translate="">Single workout records:</span></li>
+                      <li>
+                        <span>
+                          <tal:t i18n:translate="">Farthest distance</tal:t>
+                        </span>
+                        <a href="" tal:attributes="href request.resource_url(context[sport_totals['max_distance_wid']])">
+                          <tal:w tal:replace="round(sport_totals['max_distance'])"></tal:w>
+                          <tal:t i18n:translate="">km</tal:t>
+                        </a>
+                      </li>
+                      <li>
+                        <span>
+                          <tal:t i18n:translate="">Longer workout</tal:t>
+                        </span>
+                        <a href="" tal:attributes="href request.resource_url(context[sport_totals['max_time_wid']])">
+                          <tal:hms tal:define="hms timedelta_to_hms(sport_totals['max_time'])">
+                            <tal:h tal:content="str(hms[0]).zfill(2)"></tal:h>
+                            <tal:t i18n:translate="">hours</tal:t>,
+                            <tal:h tal:content="str(hms[1]).zfill(2)"></tal:h>
+                            <tal:t i18n:translate="">min.</tal:t>
+                          </tal:hms>
+                        </a>
+                      </li>
+                      <li>
+                        <span>
+                          <tal:t i18n:translate="">Higher elevation gain</tal:t>
+                        </span>
+                        <a href="" tal:attributes="href request.resource_url(context[sport_totals['max_elevation_wid']])">
+                          <tal:w tal:replace="round(sport_totals['max_elevation'])"></tal:w>
+                          <tal:t i18n:translate="">m</tal:t>
+                        </a>
+                      </li>
                     </ul>
                   </div>
@@ -290,4 +322,36 @@
                     <tal:w tal:replace="round(sport_totals['elevation'])"></tal:w>
                     <tal:t i18n:translate="">m</tal:t>
+                  </li>
+                  <li><span i18n:translate="">Single workout records:</span></li>
+                  <li>
+                    <span>
+                      <tal:t i18n:translate="">Farthest distance</tal:t>
+                    </span>
+                    <a href="" tal:attributes="href request.resource_url(context[sport_totals['max_distance_wid']])">
+                      <tal:w tal:replace="round(sport_totals['max_distance'])"></tal:w>
+                      <tal:t i18n:translate="">km</tal:t>
+                    </a>
+                  </li>
+                  <li>
+                    <span>
+                      <tal:t i18n:translate="">Longer workout</tal:t>
+                    </span>
+                    <a href="" tal:attributes="href request.resource_url(context[sport_totals['max_time_wid']])">
+                      <tal:hms tal:define="hms timedelta_to_hms(sport_totals['max_time'])">
+                        <tal:h tal:content="str(hms[0]).zfill(2)"></tal:h>
+                        <tal:t i18n:translate="">hours</tal:t>,
+                        <tal:h tal:content="str(hms[1]).zfill(2)"></tal:h>
+                        <tal:t i18n:translate="">min.</tal:t>
+                      </tal:hms>
+                    </a>
+                  </li>
+                  <li>
+                    <span>
+                      <tal:t i18n:translate="">Higher elevation gain</tal:t>
+                    </span>
+                    <a href="" tal:attributes="href request.resource_url(context[sport_totals['max_elevation_wid']])">
+                      <tal:w tal:replace="round(sport_totals['max_elevation'])"></tal:w>
+                      <tal:t i18n:translate="">m</tal:t>
+                    </a>
                   </li>
                 </ul>
Index: ow/tests/models/test_user.py
===================================================================
--- ow/tests/models/test_user.py	(revision aa6dcaf57b89932ac36aa1a2f4348657dcc13339)
+++ ow/tests/models/test_user.py	(revision 04c882dbb6a6a21c6e6c84e0dbfb4ddf31faefa4)
@@ -659,4 +659,10 @@
             'distance': Decimal(0),
             'elevation': Decimal(0),
+            'max_time': timedelta(0),
+            'max_time_wid': None,
+            'max_distance': Decimal(0),
+            'max_distance_wid': None,
+            'max_elevation': Decimal(0),
+            'max_elevation_wid': None
         }
         # add a cycling workout happening now
@@ -665,7 +671,8 @@
             start=datetime.now(timezone.utc),
             duration=timedelta(minutes=120),
-            distance=66,
-        )
-        root['john'].add_workout(workout)
+            distance=Decimal(66),
+        )
+        root['john'].add_workout(workout)
+        cycling_wid = workout.workout_id
         # only one workout, one sport, so the default will show totals
         # for that sport
@@ -675,4 +682,10 @@
             'distance': Decimal(66),
             'elevation': Decimal(0),
+            'max_time': timedelta(minutes=120),
+            'max_time_wid': cycling_wid,
+            'max_distance': Decimal(66),
+            'max_distance_wid': cycling_wid,
+            'max_elevation': Decimal(0),
+            'max_elevation_wid': None
         }
         # Add a running workout
@@ -681,7 +694,8 @@
             start=datetime(2018, 11, 25, 10, 00, tzinfo=timezone.utc),
             duration=timedelta(minutes=45),
-            distance=5,
-        )
-        root['john'].add_workout(workout)
+            distance=Decimal(5),
+        )
+        root['john'].add_workout(workout)
+        running_wid = workout.workout_id
         # the favorite sport is running now
         assert root['john'].sport_totals() == {
@@ -690,4 +704,10 @@
             'distance': Decimal(5),
             'elevation': Decimal(0),
+            'max_time': timedelta(minutes=45),
+            'max_time_wid': running_wid,
+            'max_distance': Decimal(5),
+            'max_distance_wid': running_wid,
+            'max_elevation': Decimal(0),
+            'max_elevation_wid': None,
         }
         # but we can get the totals for cycling too
@@ -697,4 +717,10 @@
             'distance': Decimal(66),
             'elevation': Decimal(0),
+            'max_time': timedelta(minutes=120),
+            'max_time_wid': cycling_wid,
+            'max_distance': Decimal(66),
+            'max_distance_wid': cycling_wid,
+            'max_elevation': Decimal(0),
+            'max_elevation_wid': None
         }
         # adding a new cycling workout, in a different year
@@ -703,7 +729,9 @@
             start=datetime(2017, 11, 25, 10, 00, tzinfo=timezone.utc),
             duration=timedelta(minutes=60),
-            distance=32,
-        )
-        root['john'].add_workout(workout)
+            distance=Decimal(32),
+            uphill=Decimal(430)
+        )
+        root['john'].add_workout(workout)
+        second_cycling_wid = workout.workout_id
         # now cycling is the favorite sport
         assert root['john'].sport_totals() == {
@@ -711,5 +739,11 @@
             'time': timedelta(minutes=180),
             'distance': Decimal(98),
-            'elevation': Decimal(0),
+            'elevation': Decimal(430),
+            'max_time': timedelta(minutes=120),
+            'max_time_wid': cycling_wid,
+            'max_distance': Decimal(66),
+            'max_distance_wid': cycling_wid,
+            'max_elevation': Decimal(430),
+            'max_elevation_wid': second_cycling_wid
         }
         # but we can get running stats too
@@ -719,4 +753,10 @@
             'distance': Decimal(5),
             'elevation': Decimal(0),
+            'max_time': timedelta(minutes=45),
+            'max_time_wid': running_wid,
+            'max_distance': Decimal(5),
+            'max_distance_wid': running_wid,
+            'max_elevation': Decimal(0),
+            'max_elevation_wid': None,
         }
         # there are no running activities for 2016
@@ -726,4 +766,10 @@
             'distance': Decimal(0),
             'elevation': Decimal(0),
+            'max_time': timedelta(0),
+            'max_time_wid': None,
+            'max_distance': Decimal(0),
+            'max_distance_wid': None,
+            'max_elevation': Decimal(0),
+            'max_elevation_wid': None
         }
         # and not activities for cycling in 2016 neither
@@ -733,4 +779,10 @@
             'distance': Decimal(0),
             'elevation': Decimal(0),
+            'max_time': timedelta(0),
+            'max_time_wid': None,
+            'max_distance': Decimal(0),
+            'max_distance_wid': None,
+            'max_elevation': Decimal(0),
+            'max_elevation_wid': None
         }
         # and we can get the separate totals for cycling in different years
@@ -741,4 +793,10 @@
             'distance': Decimal(66),
             'elevation': Decimal(0),
+            'max_time': timedelta(minutes=120),
+            'max_time_wid': cycling_wid,
+            'max_distance': Decimal(66),
+            'max_distance_wid': cycling_wid,
+            'max_elevation': Decimal(0),
+            'max_elevation_wid': None
         }
         assert root['john'].sport_totals('cycling', 2017) == {
@@ -746,4 +804,10 @@
             'time': timedelta(minutes=60),
             'distance': Decimal(32),
-            'elevation': Decimal(0),
-        }
+            'elevation': Decimal(430),
+            'max_time': timedelta(minutes=60),
+            'max_time_wid': second_cycling_wid,
+            'max_distance': Decimal(32),
+            'max_distance_wid': second_cycling_wid,
+            'max_elevation': Decimal(430),
+            'max_elevation_wid': second_cycling_wid
+        }
