diff --git a/src/assets/images/spoke_logo.png b/src/assets/images/spoke_logo.png
new file mode 100755
index 0000000000000000000000000000000000000000..f331e87ddbc8e429207dcd2879c2670419041cac
Binary files /dev/null and b/src/assets/images/spoke_logo.png differ
diff --git a/src/assets/stylesheets/spoke.scss b/src/assets/stylesheets/spoke.scss
index 037f6dadd90e5e68c9f28dd4085d4022ee81ec10..fa551e1fe1a834fbafba9efdb62e2653d13b0c86 100644
--- a/src/assets/stylesheets/spoke.scss
+++ b/src/assets/stylesheets/spoke.scss
@@ -1,6 +1,7 @@
 @import 'shared';
 @import 'loader';
 
+$spoke-action-color: #2F80ED;
 $breakpoint: 1280px;
 
 body {
@@ -23,13 +24,12 @@ body {
 :local(.ui) {
   display: flex;
   flex-direction: column;
-  height: calc(100vh);
 }
 
 :local(.content) {
   display: flex;
-  height: 100%;
   flex-direction: column;
+  height: calc(100vh);
 }
 
 :local(.header) {
@@ -52,19 +52,53 @@ body {
 :local(.hero-pane) {
   display: flex;
   height: 100%;
+  position: relative;
 
   @media(max-width: $breakpoint) {
     flex-direction: column;
   }
 }
 
+:local(.spoke-logo) {
+  position: relative;
+
+  img {
+    width: 400px;
+  }
+}
+
+:local(.primary-tagline) {
+  position: absolute;
+  right: 6px;
+  bottom: -8px;
+  font-weight: bold;
+  font-size: 1.7em;
+}
+
+:local(.secondary-tagline) {
+  font-weight: lighter;
+  font-size: 1.5em;
+  text-align: center;
+  margin-top: 48px;
+
+  a {
+    color: white;
+  }
+}
+
 :local(.hero-message) {
   width: 600px;
-  background-color: red;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  height: 100%;
 
   @media(max-width: $breakpoint) {
     order: 2;
     width: 100%;
+    margin: 32px 0;
+    height: auto;
   }
 }
 
@@ -78,7 +112,11 @@ body {
   flex: 1;
 
   @media(max-width: $breakpoint) {
-    height: auto;
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    top: 0;
+    left: 0;
     margin: 0px
   }
 }
@@ -98,3 +136,26 @@ body {
 
   z-index: -1;
 }
+
+:local(.download-button) {
+  @extend %action-button;
+  @extend %wide-button;
+  background-color: $spoke-action-color;
+  margin-top: 64px;
+}
+
+:local(.play-button) {
+  @extend %action-button;
+  background-color: $darker-grey;
+  margin: auto;
+  margin-top: 64px;
+  padding: 0px 82px;
+}
+
+:local(.browse-versions) {
+  color: $grey-text;
+  margin-top: 12px;
+  display: block;
+  text-align: center;
+  width: 100%;
+}
diff --git a/src/assets/translations.data.json b/src/assets/translations.data.json
index 6213bc174429e46a1ac7f770f64a56a907de3449..886537883c73ea6b2f7cf398387af6d4065714ae 100644
--- a/src/assets/translations.data.json
+++ b/src/assets/translations.data.json
@@ -87,6 +87,14 @@
     "link.cancel": "cancel",
     "invite.enter_via": "Enter via ",
     "invite.and_enter_code": " with code:",
-    "invite.or_visit": "or visit"
+    "invite.or_visit": "or visit",
+    "spoke.primary_tagline": "make your space",
+    "spoke.secondary_tagline": "Create 3D social scenes for ",
+    "spoke.download_win": "Download for Windows",
+    "spoke.download_macos": "Download for Mac",
+    "spoke.download_linux": "Download for Linux",
+    "spoke.download_unavailable": "View Releases",
+    "spoke.browse_all_versions": "Browse All Versions",
+    "spoke.play_button": "Watch the Video"
   }
 }
diff --git a/src/spoke.js b/src/spoke.js
index 684e595628cacd02bfc38f637ed20afd0f49e1e0..1689fbd153446242e2f23c856c701587d3a3dfef 100644
--- a/src/spoke.js
+++ b/src/spoke.js
@@ -3,8 +3,9 @@ import React, { Component } from "react";
 //import PropTypes from "prop-types";
 //import classNames from "classnames";
 import { playVideoWithStopOnBlur } from "./utils/video-utils.js";
-import { IntlProvider, /*FormattedMessage, */ addLocaleData } from "react-intl";
+import { IntlProvider, FormattedMessage, addLocaleData } from "react-intl";
 import styles from "./assets/stylesheets/spoke.scss";
+import spokeLogo from "./assets/images/spoke_logo.png";
 
 //const qs = new URLSearchParams(location.search);
 
@@ -20,22 +21,90 @@ addLocaleData([...en]);
 class SpokeLanding extends Component {
   static propTypes = {};
 
-  state = {};
+  state = { downloadLinkForCurrentPlatform: {} };
 
   constructor(props) {
     super(props);
+    this.state = { platform: "win" };
   }
 
   componentDidMount() {
     this.loadVideo();
+    this.fetchReleases();
   }
 
+  tryGetJson = async request => {
+    const text = await request.text();
+    try {
+      return JSON.parse(text);
+    } catch (e) {
+      console.log(`JSON error parsing response from ${request.url} "${text}"`, e);
+    }
+  };
+
+  getDownloadUrlForPlatform = (assets, platform) => {
+    return assets.find(asset => asset.name.includes(platform)).downloadUrl;
+  };
+
+  fetchReleases = async () => {
+    // Read-only, public access token.
+    const token = "de8cbfb4cc0281c7b731c891df431016c29b0ace";
+    const result = await fetch("https://api.github.com/graphql", {
+      timeout: 5000,
+      method: "POST",
+      headers: { authorization: `bearer ${token}` },
+      body: JSON.stringify({
+        query: `
+          {
+            repository(owner: "mozillareality", name: "spoke") {
+          releases(
+                orderBy: { field: CREATED_AT, direction: DESC },
+                first: 5
+              ) {
+                nodes {
+                  isPrerelease,
+                  isDraft,
+                  tag { name },
+                  releaseAssets(last: 3) {
+                    nodes { name, downloadUrl }
+                  }
+                },
+                pageInfo { endCursor, hasNextPage }
+              }
+            }
+          }
+        `
+      })
+    }).then(this.tryGetJson);
+
+    if (!result || !result.data) {
+      this.setState({ platform: "unavailable" });
+      return;
+    }
+
+    const releases = result.data.repository.releases;
+    const release = releases.nodes.find(release => /*!release.isPrerelease && */ !release.isDraft);
+
+    if (!release) {
+      this.setState({ platform: "unavailable" });
+      return;
+    }
+
+    this.setState({
+      downloadLinkForCurrentPlatform: this.getDownloadUrlForPlatform(release.releaseAssets.nodes, this.state.platform)
+    });
+  };
+
   loadVideo() {
     const videoEl = document.querySelector("#preview-video");
     playVideoWithStopOnBlur(videoEl);
   }
 
   render() {
+    const platform = this.state.platform;
+    const releasesLink = "https://github.com/MozillaReality/Spoke/releases";
+    const downloadLink = platform === "unavailable" ? releasesLink : this.state.downloadLinkForCurrentPlatform;
+
     return (
       <IntlProvider locale={lang} messages={messages}>
         <div className={styles.ui}>
@@ -54,7 +123,31 @@ class SpokeLanding extends Component {
           </div>
           <div className={styles.content}>
             <div className={styles.heroPane}>
-              <div className={styles.heroMessage}>Message</div>
+              <div className={styles.heroMessage}>
+                <div className={styles.spokeLogo}>
+                  <img src={spokeLogo} />
+                  <div className={styles.primaryTagline}>
+                    <FormattedMessage id="spoke.primary_tagline" />
+                  </div>
+                </div>
+                <div className={styles.secondaryTagline}>
+                  <FormattedMessage id="spoke.secondary_tagline" />
+                  <a href="/">Hubs</a>
+                </div>
+                <div className={styles.actionButtons}>
+                  <a href={downloadLink} className={styles.downloadButton}>
+                    <FormattedMessage id={"spoke.download_" + this.state.platform} />
+                  </a>
+                  {platform !== "unavailable" && (
+                    <a href={releasesLink} className={styles.browseVersions}>
+                      <FormattedMessage id="spoke.browse_all_versions" />
+                    </a>
+                  )}
+                  <button className={styles.playButton} onClick={() => this.setState({ playVideo: true })}>
+                    <FormattedMessage id="spoke.play_button" />
+                  </button>
+                </div>
+              </div>
               <div className={styles.heroVideo}>
                 <video playsInline muted loop autoPlay className={styles.previewVideo} id="preview-video">
                   <source