diff --git a/agenda/__init__.py b/agenda/__init__.py
index 83c93b0..d90359c 100644
--- a/agenda/__init__.py
+++ b/agenda/__init__.py
@@ -16,7 +16,7 @@ import pytz
 import requests
 from dateutil.easter import easter
 
-# from agenda import spacexdata
+from agenda import thespacedevs
 
 warnings.simplefilter(action="ignore", category=FutureWarning)
 
@@ -268,6 +268,8 @@ def get_us_holiday() -> dict[str, date | str]:
 
 def get_data() -> dict[str, str | object]:
     """Get data to display on agenda dashboard."""
+    rocket_dir = os.path.join(data_dir, "thespacedevs")
+
     reply = {
         "now": now,
         "gbpusd": get_gbpusd(),
@@ -285,6 +287,7 @@ def get_data() -> dict[str, str | object]:
         "uk_financial_year_end": uk_financial_year_end(today),
         "xmas_last_posting_dates": xmas_last_posting_dates,
         "xmas_day": xmas_day(today),
+        "rockets": thespacedevs.get_launches(rocket_dir, limit=40),
     }
 
     return reply
diff --git a/agenda/thespacedevs.py b/agenda/thespacedevs.py
new file mode 100644
index 0000000..de2857d
--- /dev/null
+++ b/agenda/thespacedevs.py
@@ -0,0 +1,116 @@
+import json
+import os
+import typing
+from datetime import datetime
+
+import requests
+
+Launch = dict[str, typing.Any]
+Summary = dict[str, typing.Any]
+
+
+def next_launch_api(rocket_dir: str, limit: int = 200) -> list[Launch]:
+    """Get the next upcoming launches from the API."""
+    now = datetime.now()
+    filename = os.path.join(rocket_dir, now.strftime("%Y-%m-%d_%H:%M:%S.json"))
+    url = "https://ll.thespacedevs.com/2.2.0/launch/upcoming/"
+
+    params: dict[str, str | int] = {"limit": limit}
+    r = requests.get(url, params=params)
+    open(filename, "w").write(r.text)
+    data = r.json()
+    return [summarize_launch(launch) for launch in data["results"]]
+
+
+def filename_timestamp(filename: str) -> tuple[datetime, str] | None:
+    """Get datetime from filename."""
+    try:
+        ts = datetime.strptime(filename, "%Y-%m-%d_%H:%M:%S.json")
+    except ValueError:
+        return None
+    return (ts, filename)
+
+
+def format_time(time_str: str, net_precision: str) -> tuple[str, str | None]:
+    """Format time based on precision."""
+    dt = datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%SZ")
+
+    include_time = False
+    # Format the date based on precision
+    if net_precision == "Month":
+        time_format = "%b %Y"
+    if net_precision == "Day":
+        time_format = "%d %b %Y"
+    if net_precision == "Hour":
+        time_format = "%d %b %Y"
+        include_time = True
+    if net_precision == "Minute":
+        time_format = "%d %b %Y"
+        include_time = True
+    elif net_precision == "Second":
+        time_format = "%d %b %Y"
+        include_time = True
+    elif net_precision.startswith("Quarter "):
+        time_format = f"Q{net_precision[-1]} %Y"
+
+    assert time_format
+
+    formatted = dt.strftime(time_format)
+
+    if include_time:
+        return (formatted, dt.strftime("%H:%M"))
+    else:
+        return (formatted, None)
+
+
+launch_providers = {
+    "Indian Space Research Organization": "ISRO",
+    "United Launch Alliance": "ULA",
+    "Payload Aerospace S.L.": "Payload Aerospace",
+    "Russian Federal Space Agency (ROSCOSMOS)": "ROSCOSMOS",
+    "China Aerospace Science and Technology Corporation": "CASC",
+}
+
+
+def summarize_launch(launch: Launch) -> Summary:
+    """Summarize rocket launch."""
+    launch_provider = launch["launch_service_provider"]["name"]
+    launch_provider_abbrev = launch_providers.get(launch_provider)
+
+    t0_date, t0_time = format_time(launch["net"], launch["net_precision"]["name"])
+
+    return {
+        "name": launch["name"],
+        "status": launch["status"]["abbrev"],
+        "t0_date": t0_date,
+        "t0_time": t0_time,
+        "window_start": launch["window_start"],
+        "window_end": launch["window_end"],
+        "launch_provider": launch_provider,
+        "launch_provider_abbrev": launch_provider_abbrev,
+        "launch_provider_type": launch["launch_service_provider"]["type"],
+        "rocket": launch["rocket"]["configuration"]["name"],
+        "mission": launch["mission"]["name"] if launch["mission"] else "N/A",
+        "location": launch["pad"]["location"]["name"],
+        "country_code": launch["pad"]["country_code"],
+    }
+
+
+def get_launches(rocket_dir: str, limit: int = 200) -> list[Summary]:
+    """Get rocket launches with caching."""
+    now = datetime.now()
+    existing = [x for x in (filename_timestamp(f) for f in os.listdir(rocket_dir)) if x]
+
+    existing.sort(reverse=True)
+
+    if not existing or (now - existing[0][0]).seconds > 3600:  # one hour
+        try:
+            return next_launch_api(rocket_dir, limit=limit)
+        except ValueError:
+            print("*** SpaceX next launch error ***")
+
+    f = existing[0][1]
+
+    filename = os.path.join(rocket_dir, f)
+    data = json.load(open(filename))
+    return [summarize_launch(launch) for launch in data["results"]]
diff --git a/templates/index.html b/templates/index.html
index 58963a7..91ced63 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -78,40 +78,26 @@
     <p>{{ market }}</p>
   {% endfor %}
 
-  {#
-  <h3>SpaceX launches</h3>
+  <h3>Rocket launches</h3>
   <table class="table table-hover">
-  {% for launch in spacex %}
+  {% for launch in rockets %}
     <tr>
-      {% if launch["date_precision"] == "day" %}
-        <td>
-          {{ days(launch["when"].date()) }}
-        </td>
-        <td class="text-end">
-          {{ launch["when"].strftime("%a, %d %b") }}
-        </td>
-        <td>
-        </td>
-      {% else %}
-        <td>
-          {{ days_hours(launch["when"]) }}
-        </td>
-        <td class="text-end">
-          {{ launch["when"].strftime("%a, %d %b") }}
-        </td>
-        <td>
-          {{ launch["when"].strftime("%H:%M") }}
-        </td>
-      {% endif %}
-      <td>{{ launch["name"] }}</td>
-      <td>{{ launch["rocket"] }}</td>
-      <td>{{ launch["payloads"] | join(" + ") }}</td>
-      <td>{{ launch["date_precision"] }}</td>
-    </tr>
+      <td class="text-nowrap text-end">{{ launch.t0_date }}
+
+        {% if launch.t0_time %}<br/>{{ launch.t0_time }}{% endif %}</td>
+      <td class="text-nowrap">{{ launch.status }}</td>
+      <td>{{ launch.rocket }}<br>{{launch.mission }}</td>
+      <td>
+        {% if launch.launch_provider_abbrev %}
+        <abbr title="{{ launch.launch_provider }}">{{ launch.launch_provider_abbrev }}</abbr>
+        {% else %}
+        {{ launch.launch_provider }}
+        {% endif %}
+        ({{ launch.launch_provider_type }})</td>
+      <td>{{ launch.location }}</td>
   {% endfor %}
   </div>
   </table>
-  #}
 
 </body>
 </html>