diff --git a/app/components/App.jsx b/app/components/App.jsx
index 79466717fda68d52f22d6b805d51a0674a6cee5f..bace1f305a016fa13d44e6084842cb06d17675e9 100644
--- a/app/components/App.jsx
+++ b/app/components/App.jsx
@@ -1,7 +1,12 @@
-import React from 'react';
+import React from 'react'
+import OutputPanel from './OutputPanel'
+import InputPanel from './InputPanel'
 
-export default class App extends React.Component {
-  render() {
-    return (<p>Hello</p>)
-  }
-}
+const App = () => (
+  <div>
+    <InputPanel routes={[["a", "b", "c"], [], ["1", "2", "4"]]}/>
+    <OutputPanel url="https://example.com" stops={["x", "y", "z"]} />
+  </div>
+)
+
+export default App
diff --git a/app/components/InputPanel.jsx b/app/components/InputPanel.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..a49340fc4a5ffa37598ff8e903eaba483cf26327
--- /dev/null
+++ b/app/components/InputPanel.jsx
@@ -0,0 +1,18 @@
+import React from 'react';
+import PropTypes from 'prop-types'
+import RouteTile from './RouteTile'
+
+const InputPanel = ({routes}) => (
+  <div>
+    {routes.map((stops, i) => (
+      <RouteTile key={i} stops={stops} />
+    ))}
+    <RouteTile stops={[]} noStopsText="Add a link to a partial route" />
+  </div>
+)
+
+InputPanel.propTypes = {
+  routes: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)).isRequired
+}
+
+export default InputPanel
diff --git a/app/components/OutputPanel.jsx b/app/components/OutputPanel.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..977b101694d12586fefd3bcbf3d535a2b1b47f7c
--- /dev/null
+++ b/app/components/OutputPanel.jsx
@@ -0,0 +1,18 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import RouteTile from './RouteTile'
+
+const OutputPanel = ({url, stops}) => (
+  <div>
+    <h2>Complete Route</h2>
+    <RouteTile url={url} stops={stops}
+      noStopsText="Add links to partial routes on the left" />
+  </div>
+)
+
+OutputPanel.propTypes = {
+  url: PropTypes.string.isRequired,
+  stops: PropTypes.arrayOf(PropTypes.string).isRequired
+}
+
+export default OutputPanel
diff --git a/app/components/RouteTile.jsx b/app/components/RouteTile.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..9cde62ade52e143de2e7b50c5e36911ae514c217
--- /dev/null
+++ b/app/components/RouteTile.jsx
@@ -0,0 +1,28 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+const RouteTile = ({stops, url}) => (
+  stops.length == 0 ?
+  <div>
+      <input type="text" />
+      <input type="button" value="+" />
+  </div>
+  :
+  <div>
+    { url === undefined && <input type="button" value="-" /> }
+    { url === undefined && <input type="button" value="&#x1F589;" /> }
+    { url !== undefined && <div className="url">{url}</div> }
+    <ul>
+      {stops.map((stop, i) => (
+        <li key={i}>{stop}</li>
+      ))}
+    </ul>
+  </div>
+)
+
+RouteTile.propTypes = {
+  stops: PropTypes.arrayOf(PropTypes.string).isRequired,
+  url: PropTypes.string
+}
+
+export default RouteTile