diff --git a/app/actions/actionTypes.js b/app/actions/actionTypes.js
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e100419e518f3617d26997f4d136a736fa5c4f2e 100644
--- a/app/actions/actionTypes.js
+++ b/app/actions/actionTypes.js
@@ -0,0 +1,4 @@
+export const ADD_URL = "ADD_URL"
+export const DELETE_ROUTE = "DELETE_ROUTE"
+export const CLEAR_ROUTE = "CLEAR_ROUTE"
+export const UPDATE_URL= "UPDATE_URL"
diff --git a/app/actions/index.js b/app/actions/index.js
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..51c5460424205213c15e42069d6f0ae2fe6bfd19 100644
--- a/app/actions/index.js
+++ b/app/actions/index.js
@@ -0,0 +1,30 @@
+import * as at from './actionTypes'
+
+// export const ADD_URL = "ADD_URL"
+// export const DELETE_ROUTE = "DELETE_ROUTE"
+// export const CLEAR_ROUTE = "CLEAR_ROUTE"
+// export const UPDATE_URL= "UPDATE_URL"
+
+export const mkAddUrl = (url) => ({
+  type: at.ADD_URL,
+  payload: url
+})
+    
+
+export const mkDeleteRoute = (i) => ({
+  type: at.DELETE_ROUTE,
+  payload: i
+})
+  
+export const mkClearRoute = (i) => ({
+  type: at.CLEAR_ROUTE,
+  payload: i
+})
+
+export const mkUpdateRoute = (i, url) => ({
+  type: at.CLEAR_ROUTE,
+  payload: {
+    index: i,
+    url: url
+  }
+})
diff --git a/app/components/App.jsx b/app/components/App.jsx
index bace1f305a016fa13d44e6084842cb06d17675e9..21d6274cc0845892fdc145d0effb6e19b37a1b1d 100644
--- a/app/components/App.jsx
+++ b/app/components/App.jsx
@@ -1,11 +1,11 @@
 import React from 'react'
-import OutputPanel from './OutputPanel'
-import InputPanel from './InputPanel'
+import OutputPanel from './../containers/OutputPanel'
+import InputPanel from './../containers/InputPanel'
 
 const App = () => (
   <div>
-    <InputPanel routes={[["a", "b", "c"], [], ["1", "2", "4"]]}/>
-    <OutputPanel url="https://example.com" stops={["x", "y", "z"]} />
+    <InputPanel />
+    <OutputPanel />
   </div>
 )
 
diff --git a/app/components/InputPanel.jsx b/app/components/InputPanel.jsx
index a49340fc4a5ffa37598ff8e903eaba483cf26327..2f3fda7c83e6f6f7f1a96ced7402716abc575c65 100644
--- a/app/components/InputPanel.jsx
+++ b/app/components/InputPanel.jsx
@@ -2,12 +2,12 @@ import React from 'react';
 import PropTypes from 'prop-types'
 import RouteTile from './RouteTile'
 
-const InputPanel = ({routes}) => (
+const InputPanel = ({routes, onAdd}) => (
   <div>
     {routes.map((stops, i) => (
       <RouteTile key={i} stops={stops} />
     ))}
-    <RouteTile stops={[]} noStopsText="Add a link to a partial route" />
+    <RouteTile onAdd={onAdd} stops={[]} />
   </div>
 )
 
diff --git a/app/components/OutputPanel.jsx b/app/components/OutputPanel.jsx
index 977b101694d12586fefd3bcbf3d535a2b1b47f7c..257261207606d329fa73b1a1cfe7b3e6c8178be6 100644
--- a/app/components/OutputPanel.jsx
+++ b/app/components/OutputPanel.jsx
@@ -1,17 +1,16 @@
 import React from 'react'
 import PropTypes from 'prop-types'
 import RouteTile from './RouteTile'
+import { buildUrl } from '../helpers'
 
-const OutputPanel = ({url, stops}) => (
+const OutputPanel = ({stops}) => (
   <div>
     <h2>Complete Route</h2>
-    <RouteTile url={url} stops={stops}
-      noStopsText="Add links to partial routes on the left" />
+    <RouteTile url={buildUrl(stops)} stops={stops} />
   </div>
 )
 
 OutputPanel.propTypes = {
-  url: PropTypes.string.isRequired,
   stops: PropTypes.arrayOf(PropTypes.string).isRequired
 }
 
diff --git a/app/components/RouteTile.jsx b/app/components/RouteTile.jsx
index 9cde62ade52e143de2e7b50c5e36911ae514c217..321995f9f388cfde5fe96677f8471868ebe34544 100644
--- a/app/components/RouteTile.jsx
+++ b/app/components/RouteTile.jsx
@@ -1,11 +1,21 @@
 import React from 'react'
 import PropTypes from 'prop-types'
 
-const RouteTile = ({stops, url}) => (
-  stops.length == 0 ?
+const RouteTile = ({stops, onAdd, url}) => {
+  let input
+
+  return stops.length == 0 ?
   <div>
-      <input type="text" />
-      <input type="button" value="+" />
+      <form onSubmit={(e) => {
+        e.preventDefault()
+        if (input.value.trim() == "") {
+          return
+        }
+        onAdd(input.value.trim())
+      }}>
+        <input type="text" ref={node => {input = node}} />
+        <input type="submit" value="+" />
+      </form>
   </div>
   :
   <div>
@@ -18,11 +28,12 @@ const RouteTile = ({stops, url}) => (
       ))}
     </ul>
   </div>
-)
+}
 
 RouteTile.propTypes = {
   stops: PropTypes.arrayOf(PropTypes.string).isRequired,
-  url: PropTypes.string
+  url: PropTypes.string,
+  onAdd: PropTypes.func.isRequired
 }
 
 export default RouteTile
diff --git a/app/containers/InputPanel.js b/app/containers/InputPanel.js
new file mode 100644
index 0000000000000000000000000000000000000000..a099b82ed978c0be83482e51642d5ccba41bae42
--- /dev/null
+++ b/app/containers/InputPanel.js
@@ -0,0 +1,14 @@
+import { connect } from 'react-redux'
+import * as at from '../actions/actionTypes'
+import InputPanel from '../components/InputPanel'
+import { mkAddUrl } from '../actions'
+
+const mapStateToProps = state => {
+  return { routes: state.routes }
+}
+
+const mapDispatchToProps = dispatch => ({
+  onAdd: (url) => dispatch(mkAddUrl(url))
+})
+
+export default connect(mapStateToProps, mapDispatchToProps)(InputPanel)
diff --git a/app/containers/OutputPanel.js b/app/containers/OutputPanel.js
new file mode 100644
index 0000000000000000000000000000000000000000..d40dca7f0c63a2c998060d731936644d3f4c285f
--- /dev/null
+++ b/app/containers/OutputPanel.js
@@ -0,0 +1,11 @@
+import { connect } from 'react-redux'
+import * as at from '../actions/actionTypes'
+import OutputPanel from '../components/OutputPanel'
+
+const mapStateToProps = state => {
+  return {
+      stops: [].concat.apply([], state.routes)
+    }
+}
+
+export default connect(mapStateToProps)(OutputPanel)
diff --git a/app/helpers/index.js b/app/helpers/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..87918fc57c1f335299a8b4845411e51ca1e08dbd
--- /dev/null
+++ b/app/helpers/index.js
@@ -0,0 +1,24 @@
+
+
+/*
+https://www.google.com/maps/dir/53.1518753,12.4661154/52.1956608,9.1839549/51.9431347,12.9028906/@51.1758057,10.4541194,6z/data=!4m2!4m1!3e0
+
+*/
+export const extractStops = (url) => {
+  const route = url.split("@")[0]
+  const match = route.match("^https?://(www\.)?google.[a-z]+/maps/dir/")
+  if (match === null) {
+    return []
+  }
+  const prefix = match[0]
+  let stops = route.slice(match[0].length).split("/")
+  if (stops[stops.length - 1] == "") {
+    stops.pop()
+  }
+  
+  return stops
+}
+
+export const buildUrl = (stops) => {
+  return "https://www.google.com/maps/dir/" + stops.join("/") + "/"
+}
diff --git a/app/initialize.jsx b/app/initialize.jsx
index 908910839bcf2941a0d5a96eb3d0a448e0f58234..bafa261fd4365dcb1a9dcc4ad507c2648aeaf0bf 100644
--- a/app/initialize.jsx
+++ b/app/initialize.jsx
@@ -3,15 +3,17 @@ import React from 'react';
 import { Provider } from 'react-redux';
 import { createStore } from 'redux';
 import App from './components/App';
+import reducer from './reducers'
 
 // const store = createStore(counterApp, module.hot && module.hot.data && (module.hot.data.counter || 0));
+const store = createStore(reducer,  window.__REDUX_DEVTOOLS_EXTENSION__() && window.__REDUX_DEVTOOLS_EXTENSION__())
 
 const load = () => {
   ReactDOM.render(
-    //<Provider store={store}>
+    <Provider store={store}>
       <App />
-    //</Provider>
-    , document.querySelector('#react-root')
+    </Provider>,
+    document.querySelector('#react-root')
   );
 };
 
diff --git a/app/reducers/index.js b/app/reducers/index.js
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3e8b77664680ddb3a8063889fb463e2734893914 100644
--- a/app/reducers/index.js
+++ b/app/reducers/index.js
@@ -0,0 +1,19 @@
+import * as at from '../actions/actionTypes'
+import { extractStops } from '../helpers'
+
+
+const initialState = {
+  routes: [],
+}
+
+const reducer = (state = initialState, action) => {
+  switch (action.type) {
+    case at.ADD_URL:
+      return {routes: state.routes.concat([extractStops(action.payload)])}
+
+    default:
+      return state
+  }
+}
+
+export default reducer