diff --git a/.eslintrc b/.eslintrc
index 6620eb90f2e54e6dd1eaf5bcc6f92396d0f5d31a..2a0497b593fb60dcd4dd91632ac94f98cb5fabce 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,5 +1,22 @@
 // Use this file as a starting point for your project's .eslintrc.
 // Copy this file, and add rule overrides as needed.
 {
-  "extends": ["standard", "standard-react"]
+  "extends": [
+    "airbnb",
+    "standard",
+    "standard-react"
+  ],
+  "parser": "babel-eslint",
+  "react/sort-comp": [1, {
+    "order": [
+      "constructor",
+      "lifecycle",
+      "everything-else",
+      "render"
+    ]
+  }],
+  "env": {
+    "es6": true,
+    "browser": true
+  }
 }
diff --git a/.gitignore b/.gitignore
index 10a8b909518f233620d978087555e52b48124e4b..0e92e2df7c1766a1fded8cd713bf147a35047171 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 .env.*
 .DS_Store
 _build/*
+__snapshots__/
 api/db/*
 api/db/*
 coverage
@@ -11,4 +12,3 @@ public/assets/*
 public/uploads/*
 pubsweet.log
 uploads/*
-__snapshots__/
\ No newline at end of file
diff --git a/.nvmrc b/.nvmrc
index 1e8b314962144c26d5e0e50fd29d2ca327864913..fbf1779b2046961c349259c48897ce0c399d41cf 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-6
+7.9
diff --git a/README.md b/README.md
index f550d9166d4020bb550ce43dde8761e5a4d18497..2a05ca07bfd73975678a0d6e17a9f50c87e5bded 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,18 @@
-## Overview  
+## Overview
 
 Editoria is a book production platform, built with [Pubsweet](https://gitlab.coko.foundation/pubsweet/) and [Substance](http://substance.io/).  
-This application is being developed by the [Coko Foundation](https://coko.foundation/), for the [University of California Press](http://www.ucpress.edu/).
+This application is being developed by the [Coko Foundation](https://coko.foundation/), for the [University of California Press](http://www.ucpress.edu/).  
 <br>
 
-## Installation  
+## Requirements
+
+Node >= 7.6  
+Npm >= 3  
+<br>
+
+Pubsweet >= 0.3.2  
+
+## Installation
 
 First you need to clone this repository on your machine.  
 ```git clone git@gitlab.coko.foundation:yannisbarlas/editoria.git```  
@@ -16,7 +24,7 @@ Once you have, navigate to the project's root directory.
 ```cd editoria```  
 <br>
 
-This application is being developed with node 6 in mind.  
+This application requires node 7.6 or greater.  
 If you use nvm for managing different node versions, the project includes an ```.nvmrc``` file that you can take advantage of.  
 <br>
 
@@ -34,7 +42,7 @@ Create a database.
 If you want to create a database for a development environment, simply pass the ```--dev``` option to the above command.  
 ```pubsweet setupdb ./ --dev```  
 
-Follow the instructions, create the administrator user and name your book.  
+Follow the instructions, create the administrator user and name your first book.  
 <br>
 
 Once that is done, you can run the app like so:  
@@ -43,16 +51,13 @@ Or if you want the development environment:
 ```pubsweet run --dev```  
 <br>
 
-## Set up  
+## Set up
 
 Log in as an administrator, and click on the "Teams" link in the navigation bar.  
 <br>
 
-Create 3 teams:  
-- Name the first "Production Editor", give it a type of "Production Editor all" and choose your book from the Collection dropdown.  
-- Name the second "Copy Editors", give it a type of "Copy Editor update" and choose your book from the Collection dropdown.  
-- Name the third "Authors", give it a type of "Author update" and choose your book from the Collection dropdown.  
-<br>
-
 You can now assign different users to different roles.  
 If a user is a production editor, the user can then also edit user roles for all other users.  
+<br>
+
+You're good to go!  
diff --git a/app/.eslintrc b/app/.eslintrc
deleted file mode 100644
index bb57155c6b64077529267cf5e0430a45dfae3e8b..0000000000000000000000000000000000000000
--- a/app/.eslintrc
+++ /dev/null
@@ -1,6 +0,0 @@
-// Use this file as a starting point for your project's .eslintrc.
-// Copy this file, and add rule overrides as needed.
-
-{
-  "extends": ["standard", "standard-react"]
-}
diff --git a/app/app.js b/app/app.js
index 310ce71ce1e2e32f1f3bedbbc7b0fdab85630db4..dc28d425fe02bdcb81eafbfaa16540dc12be9589 100644
--- a/app/app.js
+++ b/app/app.js
@@ -1,8 +1,8 @@
 import React from 'react'
 import ReactDOM from 'react-dom'
 
-import configureStore from 'pubsweet-frontend/src/store/configureStore'
-import Root from 'pubsweet-frontend/src/components/Root'
+import configureStore from 'pubsweet-client/src/store/configureStore'
+import Root from 'pubsweet-client/src/components/Root'
 
 import { AppContainer } from 'react-hot-loader'
 import { browserHistory } from 'react-router'
@@ -21,8 +21,8 @@ ReactDOM.render(
 )
 
 if (module.hot) {
-  module.hot.accept('pubsweet-frontend/src/components/Root', () => {
-    const NextRoot = require('pubsweet-frontend/src/components/Root').default
+  module.hot.accept('pubsweet-client/src/components/Root', () => {
+    const NextRoot = require('pubsweet-client/src/components/Root').default
 
     ReactDOM.render(
       <AppContainer>
diff --git a/app/components/BookBuilder/BookBuilder.jsx b/app/components/BookBuilder/BookBuilder.jsx
index f4e9fad8c14da13100d4e4612282551a68f42056..b994575fac4b6ebaa718ccb3b968033c014f89bf 100644
--- a/app/components/BookBuilder/BookBuilder.jsx
+++ b/app/components/BookBuilder/BookBuilder.jsx
@@ -3,46 +3,49 @@ import React from 'react'
 import { bindActionCreators } from 'redux'
 import { connect } from 'react-redux'
 
-import * as Actions from 'pubsweet-frontend/src/actions'
+// TODO -- clean up this import
+import Actions from 'pubsweet-client/src/actions'
 import Division from './Division'
-import Modal from '../utils/Modal'
+import TeamManagerModal from './TeamManager/TeamManagerModal'
 import styles from './styles/bookBuilder.local.scss'
 
-// import { fragmentsOfCollection } from 'pubsweet-core/app/helpers/Utils'
-
 export class BookBuilder extends React.Component {
   constructor (props) {
     super(props)
 
     this._toggleTeamManager = this._toggleTeamManager.bind(this)
-    // this.enableActions = false
 
     this._getRoles = this._getRoles.bind(this)
     this._isProductionEditor = this._isProductionEditor.bind(this)
-    this._setProductionEditor = this._setProductionEditor.bind(this)
+    this.setProductionEditor = this.setProductionEditor.bind(this)
 
     this.state = {
       outerContainer: {},
-      productionEditor: null,
       showTeamManager: false
     }
   }
 
   componentWillMount () {
-    const { getUsers, getTeams, getCollections, getFragments } = this.props.actions
-
-    // console.log(this.props.actions)
+    const {
+      getCollections,
+      getFragments,
+      getTeams,
+      getUsers
+    } = this.props.actions
 
     getUsers().then(
       () => getTeams()
     ).then(
       () => {
-        this._setProductionEditor()
         return getCollections()
       }
     ).then(
-      // TODO: This will have to work for multiple collections
-      (result) => getFragments(result.collections[0])
+      () => {
+        const { book } = this.props
+
+        this.setProductionEditor()
+        getFragments(book)
+      }
     )
   }
 
@@ -53,19 +56,45 @@ export class BookBuilder extends React.Component {
     this.setState({ outerContainer: this.refs.outerContainer })
   }
 
-  // temporary HACK to add production editor to collection
-  _setProductionEditor () {
-    const { book, teams, users } = this.props
+  setProductionEditor () {
+    const { actions, book, teams, users } = this.props
+    const { updateCollection } = actions
 
     const productionEditorsTeam = _.find(teams, function (t) {
       return t.teamType.name === 'Production Editor' && t.object.id === book.id
     })
 
+    if (!productionEditorsTeam) return
+
     const productionEditors = _.filter(users, function (u) {
       return _.includes(productionEditorsTeam.members, u.id)
     })
 
-    this.setState({ productionEditor: productionEditors[0].username })
+    let patch
+
+    if (_.isEmpty(productionEditors)) {
+      // production editor is already set to null
+      if (book.productionEditor === null) return
+
+      patch = {
+        id: book.id,
+        productionEditor: null
+      }
+
+      return updateCollection(patch)
+    }
+
+    const currentEditor = book.productionEditor
+    const foundEditor = productionEditors[0] || null
+
+    if (currentEditor === foundEditor) return
+
+    patch = {
+      id: book.id,
+      productionEditor: _.pick(foundEditor, ['id', 'username'])
+    }
+
+    updateCollection(patch)
   }
 
   _toggleTeamManager () {
@@ -110,9 +139,32 @@ export class BookBuilder extends React.Component {
     return pass
   }
 
+  renderTeamManagerModal () {
+    if (!this._isProductionEditor()) return null
+
+    const { outerContainer, showTeamManager } = this.state
+
+    if (!showTeamManager) return null
+    if (_.isEmpty(outerContainer)) return null
+
+    const { actions, teams, users } = this.props
+    const { updateTeam } = actions
+
+    return (
+      <TeamManagerModal
+        container={outerContainer}
+        show={showTeamManager}
+        teams={teams}
+        toggle={this._toggleTeamManager}
+        updateTeam={updateTeam}
+        users={users}
+      />
+    )
+  }
+
   render () {
-    const { book, chapters, teams, users } = this.props
-    const { createFragment, deleteFragment, ink, updateFragment, updateTeam } = this.props.actions
+    const { book, chapters } = this.props
+    const { createFragment, deleteFragment, ink, updateFragment } = this.props.actions
     const { outerContainer } = this.state
     const roles = this._getRoles()
 
@@ -145,7 +197,8 @@ export class BookBuilder extends React.Component {
       )
     }
 
-    const productionEditor = this.state.productionEditor || 'unassigned'
+    const productionEditor = _.get(book, 'productionEditor.username') || 'unassigned'
+    const teamManagerModal = this.renderTeamManagerModal()
 
     return (
       <div className='bootstrap modal pubsweet-component pubsweet-component-scroll'>
@@ -157,7 +210,7 @@ export class BookBuilder extends React.Component {
             <h1>{this.props.book.title}</h1>
 
             <div className={styles.productionEditorContainer}>
-              <span>Production Editor: &nbsp; {productionEditor} </span>
+              <span>Production Editor: &nbsp; { productionEditor } </span>
               {teamManagerButton}
               <div className={styles.separator} />
             </div>
@@ -208,32 +261,21 @@ export class BookBuilder extends React.Component {
           </div>
         </div>
 
-        <Modal
-          title='Editoria Team Manager'
-          action='EditoriaTeamManager'
-          show={this.state.showTeamManager}
-          toggle={this._toggleTeamManager}
-          container={outerContainer}
-          size='large'
-          teams={teams}
-          users={users}
-          updateTeam={updateTeam}
-        />
-
+        { teamManagerModal }
       </div>
     )
   }
 }
 
 BookBuilder.propTypes = {
+  actions: React.PropTypes.object.isRequired,
   book: React.PropTypes.object.isRequired,
   chapters: React.PropTypes.array.isRequired,
-  actions: React.PropTypes.object.isRequired,
-  error: React.PropTypes.string,
-  // userRoles: React.PropTypes.array,
+  // error: React.PropTypes.string,
   teams: React.PropTypes.array,
   users: React.PropTypes.array,
   user: React.PropTypes.object
+  // userRoles: React.PropTypes.array,
 }
 
 function mapStateToProps (state, ownProps) {
diff --git a/app/components/BookBuilder/BookList.jsx b/app/components/BookBuilder/BookList.jsx
deleted file mode 100644
index 8e35d61961447603c26b0376a1fed2ab89971167..0000000000000000000000000000000000000000
--- a/app/components/BookBuilder/BookList.jsx
+++ /dev/null
@@ -1,110 +0,0 @@
-import React from 'react'
-import { bindActionCreators } from 'redux'
-import { connect } from 'react-redux'
-import { Modal } from 'react-bootstrap'
-import { LinkContainer } from 'react-router-bootstrap'
-import * as Actions from 'pubsweet-frontend/src/actions'
-import styles from './styles/bookList.local.scss'
-
-export class BookList extends React.Component {
-  constructor (props) {
-    super(props)
-
-    this._toggleModal = this._toggleModal.bind(this)
-
-    this.state = {
-      showModal: false
-    }
-  }
-
-  _toggleModal () {
-    this.setState({
-      showModal: !this.state.showModal
-    })
-  }
-
-  render () {
-    const { book } = this.props
-    const { showModal } = this.state
-    let bookTitle = book ? book.title : 'Fetching...'
-    let bookId = book ? book.id : ''
-
-    return (
-      <div className={styles.bookList + ' bootstrap'}>
-        <div className='container col-lg-offset-2 col-lg-8'>
-
-          <div className='col-lg-12'>
-            <h1 className={styles.bookTitle}>
-              Books
-              <div className={styles.addBookBtn} onClick={this._toggleModal}>
-                <a>add book</a>
-              </div>
-            </h1>
-          </div>
-
-          <div className='col-lg-12'>
-            <div className={styles.bookContainer}>
-              <h2>{bookTitle}</h2>
-              <LinkContainer to={`/books/${bookId}/book-builder`}>
-                <a href='#'
-                  className={styles.editBook}
-                  onClick={this._toggleModal} >
-                  Edit
-                </a>
-              </LinkContainer>
-            </div>
-
-          </div>
-        </div>
-
-        <Modal
-          className='modal'
-          show={showModal}
-          onHide={this._toggleModal}
-          container={this}
-        >
-
-          <Modal.Header>
-            <Modal.Title>
-              Create a new book
-            </Modal.Title>
-          </Modal.Header>
-
-          <Modal.Body>
-            This feature is currently disabled.
-          </Modal.Body>
-
-          <Modal.Footer>
-            <a className='modal-button modal-discard'
-              onClick={this._toggleModal}>
-              Close
-            </a>
-          </Modal.Footer>
-
-        </Modal>
-
-      </div>
-    )
-  }
-}
-
-BookList.propTypes = {
-  book: React.PropTypes.object
-}
-
-function mapStateToProps (state) {
-  return {
-    book: state.collections[0]
-  }
-}
-
-function mapDispatchToProps (dispatch) {
-  return {
-    actions: bindActionCreators(Actions, dispatch)
-  }
-}
-
-export default connect(
-  mapStateToProps,
-  mapDispatchToProps
-)(BookList)
diff --git a/app/components/BookBuilder/Chapter.jsx b/app/components/BookBuilder/Chapter.jsx
index 91d47a39496c65a98b2b9be818f6d930c9a5ca7d..982dc297a1130fdf1978461e1f821f2ae8c59c79 100644
--- a/app/components/BookBuilder/Chapter.jsx
+++ b/app/components/BookBuilder/Chapter.jsx
@@ -19,9 +19,9 @@ export class Chapter extends React.Component {
     }
   }
 
-  update (changedChapter) {
+  update (patch) {
     const { book, update } = this.props
-    update(book, changedChapter)
+    update(book, patch)
   }
 
   toggleUpload () {
diff --git a/app/components/BookBuilder/Chapter/AlignmentBox.jsx b/app/components/BookBuilder/Chapter/AlignmentBox.jsx
index 19d98f0a2eb75991d0425ab169bb0fcf56b98861..f67dc8575013c0b18ca38a286833947bd09e52bc 100644
--- a/app/components/BookBuilder/Chapter/AlignmentBox.jsx
+++ b/app/components/BookBuilder/Chapter/AlignmentBox.jsx
@@ -14,8 +14,14 @@ class AlignmentBox extends React.Component {
 
     if (!includes(['left', 'right'], position)) return
 
-    chapter.alignment[position] = !chapter.alignment[position]
-    update(chapter)
+    const patch = {
+      alignment: chapter.alignment,
+      id: chapter.id
+    }
+
+    patch.alignment[position] = !chapter.alignment[position]
+
+    update(patch)
   }
 
   render () {
diff --git a/app/components/BookBuilder/Chapter/ChapterButtons.jsx b/app/components/BookBuilder/Chapter/ChapterButtons.jsx
index 1baf83b451be9ffb94969c1c3bc4f7319eb1904f..efa0f27790c6dc5ac394e42afd019351d7673aeb 100644
--- a/app/components/BookBuilder/Chapter/ChapterButtons.jsx
+++ b/app/components/BookBuilder/Chapter/ChapterButtons.jsx
@@ -114,15 +114,19 @@ class ChapterButtons extends React.Component {
     const { showDeleteModal } = this.state
     const toggle = this.toggleDeleteModal
 
-    const deleteModal = (
-      <DeleteModal
-        chapter={chapter}
-        container={modalContainer}
-        remove={remove}
-        show={showDeleteModal}
-        toggle={toggle}
-      />
-    )
+    let deleteModal = null
+
+    if (showDeleteModal) {
+      deleteModal = (
+        <DeleteModal
+          chapter={chapter}
+          container={modalContainer}
+          remove={remove}
+          show={showDeleteModal}
+          toggle={toggle}
+        />
+      )
+    }
 
     return (
       <a id='bb-delete' onClick={toggle} >
diff --git a/app/components/BookBuilder/Chapter/FirstRow.jsx b/app/components/BookBuilder/Chapter/FirstRow.jsx
index cd65fb71fadcbbd19629f2c05bea24531719a1e0..10263639b390ed05a1e7c065ab5305f941d8c8c4 100644
--- a/app/components/BookBuilder/Chapter/FirstRow.jsx
+++ b/app/components/BookBuilder/Chapter/FirstRow.jsx
@@ -25,13 +25,22 @@ class ChapterFirstRow extends React.Component {
 
   onSaveRename (title) {
     const { chapter, update } = this.props
-
     title = title.trim()
-    if (title.length === 0) return this.setState({ isRenameEmpty: true })
+
+    if (title.length === 0) {
+      return this.setState({
+        isRenameEmpty: true
+      })
+    }
+
     this.setState({ isRenameEmpty: false })
 
-    chapter.title = title
-    update(chapter)
+    const patch = {
+      id: chapter.id,
+      title: title
+    }
+    update(patch)
+
     this.setState({ isRenamingTitle: false })
   }
 
diff --git a/app/components/BookBuilder/Chapter/ProgressItem.jsx b/app/components/BookBuilder/Chapter/ProgressItem.jsx
index 6ec269ae7a405b60e51b4ecdc6335e194316935d..58de092a972090881fc53f694239bd9cded72212 100644
--- a/app/components/BookBuilder/Chapter/ProgressItem.jsx
+++ b/app/components/BookBuilder/Chapter/ProgressItem.jsx
@@ -48,8 +48,13 @@ export class ProgressItem extends React.Component {
     position += 1                      // move up a level
     if (position >= len) position = 0  // or cycle back to the beginning
 
-    chapter.progress[type] = position
-    update(chapter)
+    const patch = {
+      id: chapter.id,
+      progress: chapter.progress
+    }
+
+    patch.progress[type] = position
+    update(patch)
 
     this.setState({ showModal: false })
   }
@@ -57,7 +62,6 @@ export class ProgressItem extends React.Component {
   canChange () {
     const { type, roles, chapter } = this.props
 
-    console.log('can change', includes(roles, 'admin'))
     if (includes(roles, 'admin') || includes(roles, 'production-editor')) return true
 
     const isActive = (chapter.progress[type] === 1)
diff --git a/app/components/BookBuilder/Chapter/SecondRow.jsx b/app/components/BookBuilder/Chapter/SecondRow.jsx
index f07d399c5a19f8db4c34c71c235eb126c20c1bd2..5d479711ff9a96fa9939b3ace81c9b34107a6d46 100644
--- a/app/components/BookBuilder/Chapter/SecondRow.jsx
+++ b/app/components/BookBuilder/Chapter/SecondRow.jsx
@@ -20,6 +20,7 @@ class ChapterSecondRow extends React.Component {
             accept='.docx'
             chapter={chapter}
             convertFile={convertFile}
+            modalContainer={outerContainer}
             title=' '
             toggleUpload={toggleUpload}
             type='file'
diff --git a/app/components/BookBuilder/Chapter/UploadButton.jsx b/app/components/BookBuilder/Chapter/UploadButton.jsx
index 3b233bee1fd04fd125b0a9c8b21e7ed7d72a2fe9..cdb280d4baaafb536e54f060a0ad2db309f849ee 100644
--- a/app/components/BookBuilder/Chapter/UploadButton.jsx
+++ b/app/components/BookBuilder/Chapter/UploadButton.jsx
@@ -1,28 +1,36 @@
 import React from 'react'
+
+import UploadWarningModal from './UploadWarningModal'
 import styles from '../styles/bookBuilder.local.scss'
 
 export class UploadButton extends React.Component {
   constructor (props) {
     super(props)
+
     this.handleFileUpload = this.handleFileUpload.bind(this)
+    this.onClick = this.onClick.bind(this)
+    this.toggleModal = this.toggleModal.bind(this)
+
+    this.state = {
+      showModal: false
+    }
   }
 
   handleFileUpload (event) {
     event.preventDefault()
 
     const file = event.target.files[0]
-    const {
-      chapter,
-      convertFile,
-      toggleUpload,
-      update
-    } = this.props
+    const { chapter, convertFile, toggleUpload, update } = this.props
 
     toggleUpload()
 
     convertFile(file).then(response => {
-      chapter.source = response.converted
-      update(chapter)
+      const patch = {
+        id: chapter.id,
+        source: response.converted
+      }
+
+      update(patch)
       toggleUpload()
     }).catch((error) => {
       console.error('INK error', error)
@@ -30,10 +38,30 @@ export class UploadButton extends React.Component {
     })
   }
 
-  render () {
+  toggleModal () {
+    this.setState({
+      showModal: !this.state.showModal
+    })
+  }
+
+  onClick () {
+    if (!this.isLocked()) return
+    this.toggleModal()
+  }
+
+  isLocked () {
+    const { chapter } = this.props
+
+    if (chapter.lock === null) return false
+    return true
+  }
+
+  renderInput () {
+    if (this.isLocked()) return null
+
     const { accept, title, type } = this.props
 
-    const input = (
+    return (
       <input
         accept={accept}
         onChange={this.handleFileUpload}
@@ -41,14 +69,47 @@ export class UploadButton extends React.Component {
         type={type}
       />
     )
+  }
+
+  renderModal () {
+    if (!this.isLocked()) return null
+
+    const { showModal } = this.state
+    const { chapter, modalContainer } = this.props
+    const type = chapter.subCategory
+
+    return (
+      <UploadWarningModal
+        container={modalContainer}
+        show={showModal}
+        toggle={this.toggleModal}
+        type={type}
+      />
+    )
+  }
+
+  render () {
+    const input = this.renderInput()
+    const modal = this.renderModal()
+
+    // TODO -- refactor with chapter buttons lock
+    let buttonStyle = {}
+    if (this.isLocked()) {
+      buttonStyle = {
+        'opacity': '0.3'
+      }
+    }
 
     return (
       <div
         className={styles.btnFile}
         id='bb-upload'
+        onClick={this.onClick}
+        style={buttonStyle}
       >
         Upload Word
         { input }
+        { modal }
       </div>
     )
   }
@@ -58,6 +119,7 @@ UploadButton.propTypes = {
   accept: React.PropTypes.string.isRequired,
   chapter: React.PropTypes.object.isRequired,
   convertFile: React.PropTypes.func.isRequired,
+  modalContainer: React.PropTypes.object.isRequired,
   title: React.PropTypes.string.isRequired,
   toggleUpload: React.PropTypes.func.isRequired,
   type: React.PropTypes.string.isRequired,
diff --git a/app/components/BookBuilder/Chapter/UploadWarningModal.jsx b/app/components/BookBuilder/Chapter/UploadWarningModal.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..a8fe28fc90ec122a0049bd5601bf358598b2b487
--- /dev/null
+++ b/app/components/BookBuilder/Chapter/UploadWarningModal.jsx
@@ -0,0 +1,40 @@
+import React from 'react'
+
+import AbstractModal from '../../common/AbstractModal'
+
+class UploadWarningModal extends React.Component {
+  renderBody () {
+    const { type } = this.props
+
+    return (
+      <div>
+        You are not allowed to import contents while a { type } is being edited.
+      </div>
+    )
+  }
+
+  render () {
+    const { container, show, toggle } = this.props
+    const body = this.renderBody()
+    const title = 'Import not allowed'
+
+    return (
+      <AbstractModal
+        body={body}
+        container={container}
+        show={show}
+        title={title}
+        toggle={toggle}
+      />
+    )
+  }
+}
+
+UploadWarningModal.propTypes = {
+  container: React.PropTypes.object.isRequired,
+  show: React.PropTypes.bool.isRequired,
+  toggle: React.PropTypes.func.isRequired,
+  type: React.PropTypes.string.isRequired
+}
+
+export default UploadWarningModal
diff --git a/app/components/BookBuilder/Division.jsx b/app/components/BookBuilder/Division.jsx
index 91073891b185e6a8d1855596f681a7b46e6ed800..325c86b88e58a3adb46e464eeab30c6d766f9d65 100644
--- a/app/components/BookBuilder/Division.jsx
+++ b/app/components/BookBuilder/Division.jsx
@@ -61,13 +61,18 @@ export class Division extends React.Component {
     })
 
     _.forEach(chaptersToModify, function (c) {
-      c.index -= 1
-      update(book, c)
+      const patch = {
+        id: c.id,
+        index: (c.index - 1)
+      }
+
+      update(book, patch)
     })
   }
 
   // Reorder chapters
   _onMove (dragIndex, hoverIndex) {
+    // hovering over current position
     if (dragIndex === hoverIndex) { return }
 
     const { book, chapters, update } = this.props
@@ -75,32 +80,52 @@ export class Division extends React.Component {
 
     let toUpdate = []
 
+    // dragging upwards
     if (dragIndex > hoverIndex) {
-      const toModify = _.filter(chapters, function (c) {
+      // find the chapters that changed place
+      const toModify = _.filter(chapters, c => {
         return c.index >= hoverIndex && c.index < dragIndex
       })
-      _.forEach(toModify, function (c) {
-        c.index += 1
-        // update(book, c)
+
+      // build the patches for the chapters' updates
+      const patches = _.map(toModify, chapter => {
+        return {
+          id: chapter.id,
+          index: (chapter.index + 1)
+        }
       })
-      toUpdate = _.union(toUpdate, toModify)
-    } else if (dragIndex < hoverIndex) {
+
+      toUpdate = _.union(toUpdate, patches)
+    }
+
+    // dragging downwards
+    if (dragIndex < hoverIndex) {
+      // TODO -- refactor?
+      // do the same as above
       const toModify = _.filter(chapters, function (c) {
         return c.index <= hoverIndex && c.index > dragIndex
       })
-      _.forEach(toModify, function (c) {
-        c.index -= 1
-        // update(book, c)
+
+      const patches = _.map(toModify, chapter => {
+        return {
+          id: chapter.id,
+          index: (chapter.index - 1)
+        }
       })
-      toUpdate = _.union(toUpdate, toModify)
+
+      toUpdate = _.union(toUpdate, patches)
     }
 
-    dragChapter.index = hoverIndex
-    // update(book, dragChapter)
-    toUpdate.push(dragChapter)
+    // add the dragged chapter to the list of patches that are needed
+    const draggedPatch = {
+      id: dragChapter.id,
+      index: hoverIndex
+    }
+    toUpdate.push(draggedPatch)
 
-    _.forEach(toUpdate, function (chapter) {
-      update(book, chapter)
+    // perform all the updates
+    _.forEach(toUpdate, patch => {
+      update(book, patch)
     })
   }
 
@@ -117,7 +142,7 @@ export class Division extends React.Component {
           chapter={c}
           id={c.id}
           ink={ink}
-          key={c.index}
+          key={c.id}
           move={_onMove}
           no={i}
           outerContainer={outerContainer}
diff --git a/app/components/BookBuilder/TeamManager/AddMember.jsx b/app/components/BookBuilder/TeamManager/AddMember.jsx
index e32a6cd0c0322fdf6aab9c2b60a6d799ac153063..8973a64e4893f4f21e491b8029c535abf1fbe8bc 100644
--- a/app/components/BookBuilder/TeamManager/AddMember.jsx
+++ b/app/components/BookBuilder/TeamManager/AddMember.jsx
@@ -1,5 +1,5 @@
-import React from 'react'
 import { find, union } from 'lodash'
+import React from 'react'
 
 import TextInput from '../../utils/TextInput'
 
diff --git a/app/components/BookBuilder/TeamManager/Group.jsx b/app/components/BookBuilder/TeamManager/Group.jsx
index 4e427bef68f6b6c9be47a7cd26657bd2b657d064..157bc21953df37c509c9cba292e1a92d47c192d5 100644
--- a/app/components/BookBuilder/TeamManager/Group.jsx
+++ b/app/components/BookBuilder/TeamManager/Group.jsx
@@ -1,5 +1,5 @@
-import React from 'react'
 import _ from 'lodash'
+import React from 'react'
 
 import GroupHeader from './GroupHeader'
 import AddMember from './AddMember'
diff --git a/app/components/BookBuilder/TeamManager/Member.jsx b/app/components/BookBuilder/TeamManager/Member.jsx
index 8111d402b77d5e836607ac7dff83272fc30de51a..2ca97d2a5888861a68e80bebee0ac9121dc45bab 100644
--- a/app/components/BookBuilder/TeamManager/Member.jsx
+++ b/app/components/BookBuilder/TeamManager/Member.jsx
@@ -1,5 +1,5 @@
-import React from 'react'
 import { without } from 'lodash'
+import React from 'react'
 
 import styles from '../styles/teamManager.local.scss'
 
diff --git a/app/components/BookBuilder/TeamManager/MemberList.jsx b/app/components/BookBuilder/TeamManager/MemberList.jsx
index 32580d3022676c046a162faf56fcc9e95371d4ea..13a1ea2feccfdcdddf1fbacd591da2714e0f2fe4 100644
--- a/app/components/BookBuilder/TeamManager/MemberList.jsx
+++ b/app/components/BookBuilder/TeamManager/MemberList.jsx
@@ -1,4 +1,5 @@
 import React from 'react'
+
 import Member from './Member'
 import styles from '../styles/teamManager.local.scss'
 
diff --git a/app/components/BookBuilder/TeamManager/TeamManagerModal.jsx b/app/components/BookBuilder/TeamManager/TeamManagerModal.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..6d4d529e0a54a662b89b0e75d27b77b8c577d684
--- /dev/null
+++ b/app/components/BookBuilder/TeamManager/TeamManagerModal.jsx
@@ -0,0 +1,46 @@
+import React from 'react'
+
+import AbstractModal from '../../common/AbstractModal'
+import TeamManager from './TeamManager'
+
+class TeamManagerModal extends React.Component {
+  renderBody () {
+    const { teams, users, updateTeam } = this.props
+
+    return (
+      <TeamManager
+        teams={teams}
+        users={users}
+        updateTeam={updateTeam}
+      />
+    )
+  }
+
+  render () {
+    const { container, show, toggle } = this.props
+    const body = this.renderBody()
+
+    return (
+      <AbstractModal
+        body={body}
+        cancelText='Close'
+        container={container}
+        show={show}
+        size='large'
+        title='Editoria Team Manager'
+        toggle={toggle}
+      />
+    )
+  }
+}
+
+TeamManagerModal.propTypes = {
+  container: React.PropTypes.object.isRequired,
+  show: React.PropTypes.bool.isRequired,
+  teams: React.PropTypes.array.isRequired,
+  toggle: React.PropTypes.func.isRequired,
+  users: React.PropTypes.array,
+  updateTeam: React.PropTypes.func.isRequired
+}
+
+export default TeamManagerModal
diff --git a/app/components/BookBuilder/styles/bookBuilder.local.scss b/app/components/BookBuilder/styles/bookBuilder.local.scss
index 0db957f9eda107fb2d028eaba16d2a3c3a735d5a..465dbb4a81f729fce58dc20550dba31dc2cb7ae5 100644
--- a/app/components/BookBuilder/styles/bookBuilder.local.scss
+++ b/app/components/BookBuilder/styles/bookBuilder.local.scss
@@ -338,39 +338,42 @@ $white: #fff;
       border-bottom:2px solid;
       border-color:$light-grey;;
     }
+
     .secondLineContainer {
       padding-top:1%;
+
       .btnFile {
-        position: relative;
-        top:3px;
+        background-color: $light-grey;
+        color: #fff;
+        cursor: pointer;
         overflow: hidden;
-        background-color:$light-grey;
-        cursor:pointer;
+        position: relative;
         text-align: center;
-        color: #fff;
+        top: 3px;
         width: 75%;
-        // padding-top: 4px;
-        // padding-bottom: 4px;
       }
+
       .btnFile input[type=file] {
-        position: absolute;
-        top: 0;
-        right: 0;
-        left: 0;
-        min-width: 100%;
-        min-height: 100%;
+        border: none !important;
+        color: #fff;
         cursor: pointer;
+        display: block;
         filter: alpha(opacity=0);
+        left: 0;
+        min-height: 100%;
+        min-width: 100%;
         opacity: 0;
         outline: none;
-        color:#fff;
         padding: 10px;
-        border:none!important;
-        display: block;
+        position: absolute;
+        right: 0;
+        top: 0;
       }
+
       .btnFile:hover input[type=file] {
         font-size: 260px;
       }
+
       .secondActions {
        float:left;
         padding-left: 2%;
diff --git a/app/components/Dashboard/AddBookModal.jsx b/app/components/Dashboard/AddBookModal.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..a89e55b2114243f51ab92a749bbafa096344def9
--- /dev/null
+++ b/app/components/Dashboard/AddBookModal.jsx
@@ -0,0 +1,113 @@
+import React from 'react'
+
+import AbstractModal from '../common/AbstractModal'
+import styles from './dashboard.local.scss'
+
+class AddBookModal extends React.Component {
+  constructor (props) {
+    super(props)
+
+    this.handleKeyOnInput = this.handleKeyOnInput.bind(this)
+    this.onInputChange = this.onInputChange.bind(this)
+    this.onCreate = this.onCreate.bind(this)
+
+    this.state = { error: false }
+  }
+
+  componentDidUpdate () {
+    const { show } = this.props
+    if (show) this.inputRef.focus()
+  }
+
+  handleKeyOnInput (event) {
+    if (event.charCode !== 13) return
+    this.onCreate()
+  }
+
+  onCreate () {
+    const { create, toggle } = this.props
+
+    const input = this.inputRef
+    const newTitle = input.value.trim()
+
+    if (newTitle.length === 0) {
+      return this.setState({
+        error: true
+      })
+    }
+
+    create(newTitle)
+    toggle()
+  }
+
+  onInputChange () {
+    const { error } = this.state
+    if (!error) return
+    this.setState({ error: false })
+  }
+
+  renderBody () {
+    const error = this.renderError()
+    const message = (
+      <div style={{'paddingBottom': 4}} >
+        Enter the title of the new book <br />
+      </div>
+    )
+
+    return (
+      <div>
+        { message }
+        { error }
+
+        <input
+          className={styles['add-book-input']}
+          name='title'
+          onChange={this.onInputChange}
+          onKeyPress={this.handleKeyOnInput}
+          placeholder='eg. My new title'
+          ref={(item) => { this.inputRef = item }}
+          type='text'
+        />
+      </div>
+    )
+  }
+
+  renderError () {
+    const { error } = this.state
+
+    const el = (
+      <div className='error' >
+        New book title cannot be empty
+      </div>
+    )
+
+    const res = error ? el : null
+    return res
+  }
+
+  render () {
+    const { container, show, toggle } = this.props
+    const body = this.renderBody()
+
+    return (
+      <AbstractModal
+        body={body}
+        container={container}
+        show={show}
+        successAction={this.onCreate}
+        successText='Add'
+        title='Add a new book'
+        toggle={toggle}
+      />
+    )
+  }
+}
+
+AddBookModal.propTypes = {
+  create: React.PropTypes.func.isRequired,
+  container: React.PropTypes.object.isRequired,
+  show: React.PropTypes.bool.isRequired,
+  toggle: React.PropTypes.func.isRequired
+}
+
+export default AddBookModal
diff --git a/app/components/Dashboard/Book.jsx b/app/components/Dashboard/Book.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..5ee0de25b1ef2b24b7cf65d594c67382cd9024fa
--- /dev/null
+++ b/app/components/Dashboard/Book.jsx
@@ -0,0 +1,198 @@
+import React from 'react'
+import { Link } from 'react-router'
+
+import RemoveBookModal from './RemoveBookModal'
+import styles from './dashboard.local.scss'
+
+// TODO -- Book and Chapter should both extend a common component
+class Book extends React.Component {
+  constructor (props) {
+    super(props)
+
+    this.handleKeyOnInput = this.handleKeyOnInput.bind(this)
+    this.onClickRename = this.onClickRename.bind(this)
+    this.onClickSave = this.onClickSave.bind(this)
+    this.removeBook = this.removeBook.bind(this)
+    this.renameBook = this.renameBook.bind(this)
+    this.toggleModal = this.toggleModal.bind(this)
+
+    this.state = {
+      isRenaming: false,
+      showModal: false
+    }
+  }
+
+  componentDidUpdate () {
+    const { isRenaming } = this.state
+    if (isRenaming) this.renameTitle.focus()
+  }
+
+  toggleModal () {
+    this.setState({
+      showModal: !this.state.showModal
+    })
+  }
+
+  handleKeyOnInput (event) {
+    if (event.charCode !== 13) return
+    this.renameBook()
+  }
+
+  onClickSave () {
+    this.renameBook()
+  }
+
+  renameBook () {
+    const { book, edit } = this.props
+
+    const patch = {
+      id: book.id,
+      title: this.renameTitle.value
+    }
+
+    edit(patch)
+    this.setState({
+      isRenaming: false
+    })
+  }
+
+  onClickRename () {
+    this.setState({
+      isRenaming: true
+    })
+  }
+
+  removeBook () {
+    const { book, remove } = this.props
+    remove(book)
+  }
+
+  renderTitle () {
+    const { book } = this.props
+    const { isRenaming } = this.state
+
+    if (isRenaming) {
+      return (
+        <input
+          defaultValue={book.title}
+          name='renameTitle'
+          onKeyPress={this.handleKeyOnInput}
+          ref={(el) => { this.renameTitle = el }}
+        />
+      )
+    }
+
+    return (
+      <h2 onDoubleClick={this.onClickRename} >
+        { book.title }
+      </h2>
+    )
+  }
+
+  // TODO -- edit, rename and remove should be reusable components
+  renderEdit () {
+    const { book } = this.props
+
+    return (
+      <Link
+        className={styles.editBook}
+        to={`/books/${book.id}/book-builder`}
+      >
+        Edit
+      </Link>
+    )
+  }
+
+  renderRename () {
+    const { isRenaming } = this.state
+
+    if (isRenaming) {
+      return (
+        <a
+          className={styles.editBook}
+          href='#'
+          onClick={this.onClickSave}
+        >
+          Save
+        </a>
+      )
+    }
+
+    return (
+      <a
+        className={styles.editBook}
+        href='#'
+        onClick={this.onClickRename}
+      >
+        Rename
+      </a>
+    )
+  }
+
+  renderRemove () {
+    return (
+      <a
+        className={styles.editBook}
+        href='#'
+        onClick={this.toggleModal}
+      >
+        Remove
+      </a>
+    )
+  }
+
+  renderButtons () {
+    const rename = this.renderRename()
+    const edit = this.renderEdit()
+    const remove = this.renderRemove()
+
+    return (
+      <div className={styles.bookActions}>
+        { rename }
+        { edit }
+        { remove }
+      </div>
+    )
+  }
+
+  renderRemoveModal () {
+    const { book, container } = this.props
+    const { showModal } = this.state
+    if (!showModal) return null
+
+    return (
+      <RemoveBookModal
+        book={book}
+        container={container}
+        remove={this.removeBook}
+        show={showModal}
+        toggle={this.toggleModal}
+      />
+    )
+  }
+
+  render () {
+    const { book } = this.props
+
+    const title = this.renderTitle(book)
+    const buttons = this.renderButtons(book)
+    const removeModal = this.renderRemoveModal()
+
+    return (
+      <div className={styles.bookContainer}>
+        { title }
+        { buttons }
+        { removeModal }
+      </div>
+    )
+  }
+}
+
+Book.propTypes = {
+  book: React.PropTypes.object.isRequired,
+  container: React.PropTypes.object.isRequired,
+  edit: React.PropTypes.func.isRequired,
+  remove: React.PropTypes.func.isRequired
+}
+
+export default Book
diff --git a/app/components/Dashboard/BookList.jsx b/app/components/Dashboard/BookList.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..84230dd235a544ab8d06064a398cad4b1becd769
--- /dev/null
+++ b/app/components/Dashboard/BookList.jsx
@@ -0,0 +1,55 @@
+import { isEmpty, map, reverse, sortBy } from 'lodash'
+import React from 'react'
+
+import Book from './Book'
+import styles from './dashboard.local.scss'
+
+class BookList extends React.Component {
+  renderBookList () {
+    const { books, container, edit, remove } = this.props
+    if (!books) return 'Fetching...'
+
+    if (isEmpty(books)) {
+      return (
+        <div className={styles['booklist-empty']}>
+          There are no books to display.
+        </div>
+      )
+    }
+
+    const items = reverse(sortBy(books, 'created'))
+
+    const bookComponents = map(items, book => {
+      return (
+        <Book
+          book={book}
+          container={container}
+          edit={edit}
+          key={book.id}
+          remove={remove}
+        />
+      )
+    })
+
+    return bookComponents
+  }
+
+  render () {
+    const bookList = this.renderBookList()
+
+    return (
+      <div className='col-lg-12'>
+        { bookList }
+      </div>
+    )
+  }
+}
+
+BookList.propTypes = {
+  books: React.PropTypes.array.isRequired,
+  container: React.PropTypes.object.isRequired,
+  edit: React.PropTypes.func.isRequired,
+  remove: React.PropTypes.func.isRequired
+}
+
+export default BookList
diff --git a/app/components/Dashboard/Dashboard.jsx b/app/components/Dashboard/Dashboard.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..563df6ab8adadc212b303424604473d56e324bed
--- /dev/null
+++ b/app/components/Dashboard/Dashboard.jsx
@@ -0,0 +1,213 @@
+import { each, filter, isEmpty } from 'lodash'
+// TODO -- clean up this import
+import Actions from 'pubsweet-client/src/actions'
+import React from 'react'
+import { bindActionCreators } from 'redux'
+import { connect } from 'react-redux'
+
+import AddBookModal from './AddBookModal'
+import BookList from './BookList'
+import DashboardHeader from './DashboardHeader'
+import { teamTypes } from '../utils/config'
+import styles from './dashboard.local.scss'
+
+export class Dashboard extends React.Component {
+  constructor (props) {
+    super(props)
+
+    this.createBook = this.createBook.bind(this)
+    this.createTeamsForBook = this.createTeamsForBook.bind(this)
+    this.editBook = this.editBook.bind(this)
+    this.findBooksWithNoTeams = this.findBooksWithNoTeams.bind(this)
+    this.removeBook = this.removeBook.bind(this)
+    this.removeTeamsForBook = this.removeTeamsForBook.bind(this)
+    this.toggleModal = this.toggleModal.bind(this)
+
+    this.state = {
+      showModal: false
+    }
+  }
+
+  /*
+    Get books and teams.
+    Make sure all books have teams associated with them.
+  */
+  componentWillMount () {
+    const { actions } = this.props
+    const { getCollections, getTeams } = actions
+
+    getCollections().then(
+      () => getTeams()
+    ).then(
+      () => this.findBooksWithNoTeams()
+    )
+  }
+
+  /*
+    Toggle showing 'add book' modal
+  */
+  toggleModal () {
+    this.setState({
+      showModal: !this.state.showModal
+    })
+  }
+
+  /*
+    Create a new book with the given title.
+    Once you have the new book's db id, make the teams for it as well.
+  */
+  createBook (newTitle) {
+    const { createCollection } = this.props.actions
+
+    const book = {
+      title: newTitle || 'Untitled'
+    }
+
+    createCollection(book).then(res => {
+      const createdBook = res.collection
+      this.createTeamsForBook(createdBook)
+    })
+  }
+
+  /*
+    Edit a book's properties.
+  */
+  editBook (patch) {
+    const { updateCollection } = this.props.actions
+    updateCollection(patch)
+  }
+
+  /*
+    Remove the given book.
+    Also remove all teams associated with it.
+  */
+  removeBook (book) {
+    const { deleteCollection } = this.props.actions
+
+    deleteCollection(book).then(res => {
+      this.removeTeamsForBook(book)
+    })
+  }
+
+  /*
+    Find all books that have no teams associated with them.
+    If one is found, make the teams for it.
+    This will most likely only happen once:
+      # The first time the app is run, on the collection created by
+      # the command 'pubsweet setupdb'.
+  */
+  // TODO -- refactor so that less operations run most of the time
+  findBooksWithNoTeams () {
+    const { books, teams } = this.props
+
+    each(books, book => {
+      const teamsForBook = filter(teams, t => {
+        return t.object.id === book.id
+      })
+
+      if (isEmpty(teamsForBook)) {
+        this.createTeamsForBook(book)
+      }
+    })
+  }
+
+  /*
+    Create the teams found in the config file for the given book.
+    This should run either when a new book is created,
+    or when a book with no teams associated with it is found.
+  */
+  createTeamsForBook (book) {
+    const { createTeam } = this.props.actions
+
+    each(teamTypes, teamType => {
+      // TODO -- Review the idea that the name needs to be plural for some teams
+      const name = (teamType.name === 'Production Editor')
+      ? teamType.name
+      : teamType.name + 's'
+
+      const newTeam = {
+        members: [],
+        name: name,
+        object: {
+          id: book.id,
+          type: 'collection'
+        },
+        teamType: teamType
+      }
+
+      createTeam(newTeam)
+    })
+  }
+
+  /*
+    Delete all teams associated with the given book.
+    This should only run after a book is deleted.
+  */
+  removeTeamsForBook (book) {
+    const { actions, teams } = this.props
+    const { deleteTeam } = actions
+
+    const teamsToDelete = filter(teams, team => {
+      return team.object.id === book.id
+    })
+
+    each(teamsToDelete, team => {
+      deleteTeam(team)
+    })
+  }
+
+  render () {
+    const { books } = this.props
+    const { showModal } = this.state
+
+    const className = styles.bookList +
+      ' bootstrap pubsweet-component pubsweet-component-scroll'
+
+    return (
+      <div className={className}>
+        <div className='container col-lg-offset-2 col-lg-8'>
+
+          <DashboardHeader toggle={this.toggleModal} />
+
+          <BookList
+            books={books}
+            container={this}
+            edit={this.editBook}
+            remove={this.removeBook}
+          />
+        </div>
+
+        <AddBookModal
+          container={this}
+          create={this.createBook}
+          show={showModal}
+          toggle={this.toggleModal}
+        />
+      </div>
+    )
+  }
+}
+
+Dashboard.propTypes = {
+  actions: React.PropTypes.object.isRequired,
+  books: React.PropTypes.arrayOf(React.PropTypes.object),  // TODO -- ??
+  teams: React.PropTypes.arrayOf(React.PropTypes.object)
+}
+
+function mapStateToProps (state, { params }) {
+  return {
+    books: state.collections,
+    teams: state.teams
+  }
+}
+
+function mapDispatchToProps (dispatch) {
+  return {
+    actions: bindActionCreators(Actions, dispatch)
+  }
+}
+
+export default connect(
+  mapStateToProps,
+  mapDispatchToProps
+)(Dashboard)
diff --git a/app/components/Dashboard/DashboardHeader.jsx b/app/components/Dashboard/DashboardHeader.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..0ae63e3fed9906e546a5c847fe8ecbc3fbe1041e
--- /dev/null
+++ b/app/components/Dashboard/DashboardHeader.jsx
@@ -0,0 +1,31 @@
+import React from 'react'
+
+import styles from './dashboard.local.scss'
+
+class DashboardHeader extends React.Component {
+  render () {
+    const { toggle } = this.props
+
+    return (
+      <div className='col-lg-12'>
+        <h1 className={styles.bookTitle}>
+          Books
+
+          <div
+            className={styles.addBookBtn}
+            onClick={toggle}
+          >
+            <a>add book</a>
+          </div>
+
+        </h1>
+      </div>
+    )
+  }
+}
+
+DashboardHeader.propTypes = {
+  toggle: React.PropTypes.func.isRequired
+}
+
+export default DashboardHeader
diff --git a/app/components/Dashboard/RemoveBookModal.jsx b/app/components/Dashboard/RemoveBookModal.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..a1f1e1e6c739870d88ca80f19248fab821361e7a
--- /dev/null
+++ b/app/components/Dashboard/RemoveBookModal.jsx
@@ -0,0 +1,46 @@
+import React from 'react'
+
+import AbstractModal from '../common/AbstractModal'
+
+class RemoveBookModal extends React.Component {
+  renderBody () {
+    const { book } = this.props
+
+    return (
+      <span>
+        Are you sure you want to permanently delete { book.title }?
+      </span>
+    )
+  }
+
+  render () {
+    const { container, remove, show, toggle } = this.props
+
+    const title = 'Delete Book'
+    const successText = 'Delete'
+
+    const body = this.renderBody()
+
+    return (
+      <AbstractModal
+        body={body}
+        container={container}
+        show={show}
+        successAction={remove}
+        successText={successText}
+        title={title}
+        toggle={toggle}
+      />
+    )
+  }
+}
+
+RemoveBookModal.propTypes = {
+  book: React.PropTypes.object.isRequired,
+  container: React.PropTypes.object.isRequired,
+  remove: React.PropTypes.func.isRequired,
+  show: React.PropTypes.bool.isRequired,
+  toggle: React.PropTypes.func.isRequired
+}
+
+export default RemoveBookModal
diff --git a/app/components/BookBuilder/styles/bookList.local.scss b/app/components/Dashboard/dashboard.local.scss
similarity index 57%
rename from app/components/BookBuilder/styles/bookList.local.scss
rename to app/components/Dashboard/dashboard.local.scss
index 656213a3aa4427f13e44a7acfc626e110cb4e75e..3a7a399945a8923f526b6be23f197ea3b587f79a 100644
--- a/app/components/BookBuilder/styles/bookList.local.scss
+++ b/app/components/Dashboard/dashboard.local.scss
@@ -1,20 +1,28 @@
 $primary-color: #515253;
 
+$black: #000;
+$dark-grey: #fff;
+$grey: #808080;
+$maroon: #502424;
+$medium-grey: #838587;
+
 .bookList {
   .bookTitle {
     border-bottom: .1em solid;
     position: relative;
   }
 
-  h1, .h1 {
-    font-weight: 500;
-    font-style: italic;
+  h1,
+  .h1 {
     font-size: 48px;
+    font-style: italic;
+    font-weight: 500;
     line-height: 56px;
     margin: 0;
   }
 
-  h2, .h2 {
+  h2,
+  .h2 {
     color: $primary-color;
     font-size: 32px;
     font-style: italic;
@@ -24,9 +32,9 @@ $primary-color: #515253;
   }
 
   .addBookBtn {
-    background-color: grey;
-    border: 1px solid grey;
-    color: #fff;
+    background-color: $grey;
+    border: 1px solid $grey;
+    color: $dark-grey;
     cursor: pointer;
     float: right;
     font-size: 16px;
@@ -36,40 +44,65 @@ $primary-color: #515253;
     text-align: center;
 
     &:hover {
-      border: 1px solid #000;
+      border: 1px solid $black;
     }
+
     a {
-      color: #fff;
-      text-decoration: none;
-      position: relative;
       bottom: 14px;
+      color: $dark-grey;
+      position: relative;
+      text-decoration: none;
+
       &:hover {
+        cursor: pointer;
         text-decoration: none;
-        cursor:pointer;
       }
     }
   }
 
   .bookContainer {
-    border-bottom: 1px solid #838587;
+    border-bottom: 1px solid $medium-grey;
     margin-top: 3em;
     padding-bottom: 0;
-    padding-left: 2em;
+    padding-left: 1em;
     padding-top: 0;
+    position: relative;
+  }
+
+  .bookActions {
+    bottom: 0;
+    position: absolute;
+    right: 13px;
   }
 
   .editBook {
-    color: #838587;
-    text-decoration: none;
+    color: $medium-grey;
+    display: inline-block;
     font-style: italic;
     font-weight: 500;
-    right: 13px;
-    display: block;
-    bottom: 0;
-    position: absolute;
+    margin-left: 13px;
+    text-decoration: none;
+
     &:hover {
-      color:#502424;
+      color: $maroon;
+      text-decoration: none;
+    }
+
+    &:link {
+      color: $medium-grey;
       text-decoration: none;
     }
   }
+
+  .booklist-empty {
+    padding-top: 15px;
+  }
+
+  .add-book-input {
+    width: 400px;
+
+    &:placeholder-shown {
+      font-size: 13px;
+    }
+  }
 }
diff --git a/app/components/Navigation/Navigation.jsx b/app/components/Navigation/Navigation.jsx
index 673ecb095546fcd633d8ddf4174572276ddb8a0e..013e3aad55b467238e8e965e874fc5e6da0fab70 100644
--- a/app/components/Navigation/Navigation.jsx
+++ b/app/components/Navigation/Navigation.jsx
@@ -3,7 +3,7 @@ import { browserHistory } from 'react-router'
 import { LinkContainer } from 'react-router-bootstrap'
 import { Navbar, Nav, NavItem, NavbarBrand } from 'react-bootstrap'
 
-import Authorize from 'pubsweet-frontend/src/helpers/Authorize'
+import Authorize from 'pubsweet-client/src/helpers/Authorize'
 import NavbarUser from 'pubsweet-component-navigation/NavbarUser'
 
 export default class Navigation extends React.Component {
diff --git a/app/components/SimpleEditor/ContainerEditor.js b/app/components/SimpleEditor/ContainerEditor.js
index e124656032bf8d768371d3a6be4e4443bcfe84d5..ad3241bda9012258f818ad6c8c47554a0fb0bcd6 100644
--- a/app/components/SimpleEditor/ContainerEditor.js
+++ b/app/components/SimpleEditor/ContainerEditor.js
@@ -45,6 +45,7 @@ class ContainerEditor extends SubstanceContainerEditor {
       this.addTargetToLinks()
     }
 
+    // TODO -- this.props.history is deprecated and gives a warning
     if (this.props.history) {
       this.props.history.listenBefore((location, callback) => {
         const commandStates = this.getCommandStates()
diff --git a/app/components/SimpleEditor/SimpleEditor.jsx b/app/components/SimpleEditor/SimpleEditor.jsx
index dd008f79880634143663094f6a6fb5c041258aa8..3492ac3b9d8db4b71a19b5b44aef8b5918663489 100644
--- a/app/components/SimpleEditor/SimpleEditor.jsx
+++ b/app/components/SimpleEditor/SimpleEditor.jsx
@@ -62,8 +62,13 @@ export default class SimpleEditor extends React.Component {
 
   updateTrackChangesStatus () {
     const { fragment, update } = this.props
-    fragment.trackChanges = !fragment.trackChanges
-    update(fragment)
+
+    const patch = {
+      id: fragment.id,
+      trackChanges: !fragment.trackChanges
+    }
+
+    update(patch)
   }
 
   save (source, changes, callback) {
@@ -212,8 +217,8 @@ export default class SimpleEditor extends React.Component {
 }
 
 SimpleEditor.propTypes = {
-  book: React.PropTypes.object.isRequired,
-  canEdit: React.PropTypes.bool, // needed?
+  book: React.PropTypes.object,
+  // canEdit: React.PropTypes.bool, // needed?
   fragment: React.PropTypes.object,
   history: React.PropTypes.object.isRequired,
   onSave: React.PropTypes.func.isRequired,
diff --git a/app/components/SimpleEditor/SimpleEditorWrapper.jsx b/app/components/SimpleEditor/SimpleEditorWrapper.jsx
index cba0a6169c6b7c29dc6c00639491e344e3d3e12d..180008ea2620a14443f48c2ba418cd4bec363881 100644
--- a/app/components/SimpleEditor/SimpleEditorWrapper.jsx
+++ b/app/components/SimpleEditor/SimpleEditorWrapper.jsx
@@ -3,7 +3,7 @@ import React from 'react'
 import { connect } from 'react-redux'
 import { bindActionCreators } from 'redux'
 
-import * as Actions from 'pubsweet-frontend/src/actions'
+import Actions from 'pubsweet-client/src/actions'
 
 import SimpleEditor from './SimpleEditor'
 
@@ -19,8 +19,10 @@ export class SimpleEditorWrapper extends React.Component {
   componentWillMount () {
     const { getCollections, getFragments } = this.props.actions
 
-    getCollections().then(result => {
-      getFragments(result.collections[0])
+    // TODO: might not need to fetch all the collections?
+    getCollections().then(() => {
+      const { book } = this.props
+      getFragments(book)
     })
 
     const { user } = this.props
@@ -71,26 +73,31 @@ export class SimpleEditorWrapper extends React.Component {
 
   save (source, callback) {
     const { fragment } = this.props
-    fragment.source = source
 
-    return this.update(fragment)
+    const patch = {
+      id: fragment.id,
+      source: source
+    }
+
+    return this.update(patch)
   }
 
-  update (newChapter) {
+  update (patch) {
     const { book } = this.props
     const { updateFragment } = this.props.actions
-    return updateFragment(book, newChapter)
+
+    return updateFragment(book, patch)
   }
 }
 
 // TODO -- review required props
 SimpleEditorWrapper.propTypes = {
   actions: React.PropTypes.object.isRequired,
-  book: React.PropTypes.object.isRequired,
+  book: React.PropTypes.object,
   fragment: React.PropTypes.object,
   history: React.PropTypes.object.isRequired,
-  user: React.PropTypes.object.isRequired,
-  update: React.PropTypes.func
+  user: React.PropTypes.object.isRequired
+  // update: React.PropTypes.func
 }
 
 const mapStateToProps = (state, ownProps) => {
diff --git a/app/components/SimpleEditor/elements/track_change/TrackChangeComponent.js b/app/components/SimpleEditor/elements/track_change/TrackChangeComponent.js
index 6a0d7224e23824273116e564d6faf57ef0ca0709..2abef42b437266a6e8acc4b781ebfc5e259b2bb4 100644
--- a/app/components/SimpleEditor/elements/track_change/TrackChangeComponent.js
+++ b/app/components/SimpleEditor/elements/track_change/TrackChangeComponent.js
@@ -3,7 +3,8 @@ import { AnnotationComponent } from 'substance'
 class TrackChangeComponent extends AnnotationComponent {
 
   didMount () {
-    this.context.editorSession.onUpdate('document', this.onTrackChangesUpdated, this)
+    const { editorSession } = this.context
+    editorSession.onUpdate('document', this.onTrackChangesUpdated, this)
   }
 
   render ($$) {
diff --git a/app/components/common/AbstractModal.jsx b/app/components/common/AbstractModal.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..0efa66c387f537c33bbe78b256f7df024161cd7e
--- /dev/null
+++ b/app/components/common/AbstractModal.jsx
@@ -0,0 +1,104 @@
+import React from 'react'
+import { Modal } from 'react-bootstrap'
+
+export class AbstractModal extends React.Component {
+  constructor (props) {
+    super(props)
+    this.performAction = this.performAction.bind(this)
+  }
+
+  performAction () {
+    const { successAction } = this.props
+    successAction()
+  }
+
+  renderHeader () {
+    const { title } = this.props
+
+    return (
+      <Modal.Header>
+        <Modal.Title>
+          { title }
+        </Modal.Title>
+      </Modal.Header>
+    )
+  }
+
+  renderBody () {
+    const { body } = this.props
+
+    return (
+      <Modal.Body>
+        { body }
+      </Modal.Body>
+    )
+  }
+
+  renderFooter () {
+    const { cancelText, successAction, successText, toggle } = this.props
+
+    const successButton = (
+      <a
+        className='modal-button bb-modal-act'
+        onClick={this.performAction}
+      >
+        { successText }
+      </a>
+    )
+
+    const success = successAction ? successButton : null
+
+    return (
+      <Modal.Footer>
+        <div className='modal-buttons-container'>
+
+          <a className='modal-button modal-discard bb-modal-cancel'
+            onClick={toggle}>
+            { cancelText || 'Cancel' }
+          </a>
+
+          { success }
+
+        </div>
+      </Modal.Footer>
+    )
+  }
+
+  render () {
+    const { container, size, show, toggle } = this.props
+
+    const header = this.renderHeader()
+    const body = this.renderBody()
+    const footer = this.renderFooter()
+
+    return (
+      <Modal
+        bsSize={size || null}
+        className='modal'
+        container={container}
+        onHide={toggle}
+        show={show}
+      >
+
+        { header }
+        { body }
+        { footer }
+
+      </Modal>
+    )
+  }
+}
+
+AbstractModal.propTypes = {
+  body: React.PropTypes.object,
+  cancelText: React.PropTypes.string,
+  container: React.PropTypes.object.isRequired,
+  show: React.PropTypes.bool.isRequired,
+  size: React.PropTypes.string,
+  successAction: React.PropTypes.func,
+  successText: React.PropTypes.string,
+  title: React.PropTypes.string.isRequired,
+  toggle: React.PropTypes.func.isRequired
+}
+
+export default AbstractModal
diff --git a/app/components/utils/Modal.jsx b/app/components/utils/Modal.jsx
index 82162fe3c2bb771fded56df3b5731eca2586db68..e69251f194d78c254b3865176b7296c72c5d32d9 100644
--- a/app/components/utils/Modal.jsx
+++ b/app/components/utils/Modal.jsx
@@ -1,3 +1,5 @@
+// TODO -- deprecate this in favor of abstract modal
+
 import React from 'react'
 import { Modal } from 'react-bootstrap'
 import TeamManager from '../BookBuilder/TeamManager/TeamManager'
diff --git a/app/components/utils/config.js b/app/components/utils/config.js
index 59ce4b32dfc1034030075c5896532d7a79926924..5da4c9929dd36d3aae31275b44aad93e8e96eeac 100644
--- a/app/components/utils/config.js
+++ b/app/components/utils/config.js
@@ -1,3 +1,6 @@
+/* global CONFIG */
+const teamTypes = CONFIG.authsome.teams
+
 const chapter = {
   dropdownValues: {
     front: [
@@ -23,4 +26,4 @@ const chapter = {
   }
 }
 
-export { chapter }
+export { chapter, teamTypes }
diff --git a/app/routes.jsx b/app/routes.jsx
index 2f2b463f197b0b904b5d3c582f4e8e1fe28e06f1..48cecfd80c93567b11b2b93908affeadfb7ffe1e 100644
--- a/app/routes.jsx
+++ b/app/routes.jsx
@@ -1,7 +1,7 @@
 import React from 'react'
 import { Redirect, Route } from 'react-router'
 
-import { requireAuthentication } from 'pubsweet-frontend/src/components/AuthenticatedComponent'
+import { requireAuthentication } from 'pubsweet-client/src/components/AuthenticatedComponent'
 
 // Manage
 import Manage from 'pubsweet-component-manage/Manage'
@@ -11,13 +11,15 @@ import Blog from 'pubsweet-component-blog/Blog'
 
 // Editoria
 import BookBuilder from './components/BookBuilder/BookBuilder'
-import BookList from './components/BookBuilder/BookList'
+import Dashboard from './components/Dashboard/Dashboard'
 import SimpleEditorWrapper from './components/SimpleEditor/SimpleEditorWrapper'
 
 // Authentication
 import Login from 'pubsweet-component-login/Login'
 import Signup from 'pubsweet-component-signup/Signup'
 
+// FIXME: this shouldn't be using the collection as the object
+
 const AuthenticatedManage = requireAuthentication(
   Manage, 'create', (state) => state.collections[0]
 )
@@ -36,7 +38,7 @@ export default (
     <Redirect from='/manage/posts' to='books' />
 
     <Route path='/' component={AuthenticatedManage}>
-      <Route path='books' component={BookList} />
+      <Route path='books' component={Dashboard} />
       <Route path='blog' component={Blog} />
       <Route path='books/:id/book-builder' component={BookBuilder} />
       <Route path='books/:bookId/fragments/:fragmentId' component={SimpleEditorWrapper} />
diff --git a/config/dev.js b/config/dev.js
index 09589eb13e5d7184649f912af5b74b7ae69d0508..1f19acc0205273a13a1bbf3a0f4340b6cea9b10e 100644
--- a/config/dev.js
+++ b/config/dev.js
@@ -10,15 +10,16 @@ module.exports = {
   pubsweet: {
     components: universal.components
   },
-  'pubsweet-backend': {
+  'pubsweet-client': {
+    theme: universal.theme,
+    routes: 'app/routes.jsx',
+    navigation: 'app/components/Navigation/Navigation.jsx'
+  },
+  'pubsweet-component-ink-backend': universal.inkBackend,
+  'pubsweet-server': {
     dbPath: path.join(__dirname, '..', 'api', 'db'),
     secret: process.env.PUBSWEET_SECRET,
     API_ENDPOINT: '/api'
   },
-  'pubsweet-component-ink-backend': universal.inkBackend,
-  'pubsweet-frontend': {
-    theme: universal.theme,
-    routes: 'app/routes.jsx',
-    navigation: 'app/components/Navigation/Navigation.jsx'
-  }
+  'validations': universal.validations
 }
diff --git a/config/production.js b/config/production.js
index 0d1a71d53bb45803fe8492eadef21fa5698a2883..b70b54bd9794f7a3390402d557ae638d59bac5de 100644
--- a/config/production.js
+++ b/config/production.js
@@ -10,15 +10,16 @@ module.exports = {
   pubsweet: {
     components: universal.components
   },
-  'pubsweet-backend': {
+  'pubsweet-client': {
+    theme: universal.theme,
+    routes: 'app/routes.jsx',
+    navigation: 'app/components/Navigation/Navigation.jsx'
+  },
+  'pubsweet-component-ink-backend': universal.inkBackend,
+  'pubsweet-server': {
     dbPath: path.join(__dirname, '..', 'api', 'db'),
     secret: '71dcce42-2245-4944-925b-0a62b83425ce',
     API_ENDPOINT: '/api'
   },
-  'pubsweet-component-ink-backend': universal.inkBackend,
-  'pubsweet-frontend': {
-    theme: universal.theme,
-    routes: 'app/routes.jsx',
-    navigation: 'app/components/Navigation/Navigation.jsx'
-  }
+  'validations': universal.validations
 }
diff --git a/config/universal.js b/config/universal.js
index c714b5492835ba0f60b9c2f714c7063efeead8b9..ab3a727918e586a7125c21236f7cdfb351fb3d1b 100644
--- a/config/universal.js
+++ b/config/universal.js
@@ -1,3 +1,4 @@
+const Joi = require('joi')
 const editoriaMode = require('../app/authsome_editoria')
 
 const inkUsername = process.env.INK_USERNAME
@@ -30,5 +31,26 @@ module.exports = {
       permissions: 'update'
     }
   },
-  theme: 'ThemeEditoria'
+  theme: 'ThemeEditoria',
+  validations: {
+    collection: {
+      productionEditor: Joi.object().allow(null)
+    },
+    fragment: {
+      alignment: Joi.object(),
+      author: Joi.string().allow(''),
+      book: Joi.string().guid().required(),
+      comments: Joi.object(),
+      division: Joi.string(),
+      index: Joi.number(),
+      kind: Joi.string(),
+      lock: Joi.object().allow(null),
+      progress: Joi.object(),
+      source: Joi.string().allow(''),
+      status: Joi.string(),
+      subCategory: Joi.string(),
+      title: Joi.string(),
+      trackChanges: Joi.boolean()
+    }
+  }
 }
diff --git a/package.json b/package.json
index 8dabd90b41bb78ed4f39f3e3372f5d7d3e78416f..58d46d362b7ec2b6dc9b268595516b35c7fa8c21 100644
--- a/package.json
+++ b/package.json
@@ -2,62 +2,67 @@
   "name": "editoria",
   "description": "A new pubsweet app",
   "dependencies": {
-    "authsome": "^0.0.4",
-    "autobind-decorator": "^1.3.4",
-    "babel-core": "^6.14.0",
-    "babel-loader": "^6.2.5",
-    "babel-plugin-transform-decorators-legacy": "^1.3.4",
-    "babel-preset-es2015": "^6.14.0",
-    "babel-preset-es2015-native-modules": "^6.9.4",
-    "babel-preset-react": "^6.11.1",
-    "babel-preset-stage-2": "^6.13.0",
-    "bootstrap-sass": "^3.3.7",
-    "copy-webpack-plugin": "^4.0.1",
-    "css-loader": "^0.25.0",
+    "autobind-decorator": "1.4.0",
+    "babel-plugin-transform-decorators-legacy": "1.3.4",
+    "babel-preset-es2015-native-modules": "6.9.4",
+    "babel-preset-stage-2": "6.24.1",
+    "copy-webpack-plugin": "4.0.1",
+    "css-loader": "0.25.0",
+    "extract-text-webpack-plugin": "2.1.0",
+    "file-loader": "0.9.0",
+    "font-awesome": "4.7.0",
+    "html-webpack-plugin": "2.28.0",
+    "json-loader": "0.5.4",
+    "lodash": "4.17.4",
+    "pubsweet-client": "0.9.1",
+    "pubsweet-component-blog": "0.1.5",
+    "pubsweet-component-ink-backend": "0.0.6",
+    "pubsweet-component-ink-frontend": "0.0.3",
+    "pubsweet-component-login": "0.2.3",
+    "pubsweet-component-manage": "0.1.5",
+    "pubsweet-component-navigation": "0.2.2",
+    "pubsweet-component-signup": "0.1.3",
+    "pubsweet-component-teams-manager": "0.1.3",
+    "pubsweet-component-theme-editoria": "git+https://gitlab.coko.foundation/yannisbarlas/pubsweet-component-theme-editoria.git",
+    "pubsweet-component-users-manager": "0.1.3",
+    "pubsweet-server": "0.8.1",
+    "pubsweet-theme-plugin": "0.0.1",
+    "react": "15.5.4",
+    "react-bootstrap": "0.30.10",
+    "react-dnd": "2.3.0",
+    "react-dnd-html5-backend": "2.3.0",
+    "react-dom": "15.5.4",
+    "react-redux": "5.0.4",
+    "react-router": "2.8.1",
+    "react-router-bootstrap": "0.23.2",
+    "redux": "3.6.0",
+    "sass-loader": "4.1.1",
+    "script-loader": "0.7.0",
+    "string-replace-loader": "1.2.0",
+    "style-loader": "0.13.2",
+    "substance": "1.0.0-beta.6.5",
+    "url-loader": "0.5.8",
+    "webpack": "2.4.1",
+    "webpack-dev-middleware": "1.10.2",
+    "webpack-hot-middleware": "2.18.0"
+  },
+  "devDependencies": {
+    "babel-eslint": "^7.2.1",
+    "enzyme": "^2.7.1",
+    "enzyme-to-json": "^1.4.5",
     "eslint": "^3.6.0",
+    "eslint-config-airbnb": "^14.1.0",
     "eslint-config-standard": "^6.2.0",
     "eslint-config-standard-react": "^4.2.0",
     "eslint-loader": "^1.6.0",
-    "eslint-plugin-promise": "^2.0.1",
+    "eslint-plugin-import": "^2.2.0",
+    "eslint-plugin-jsx-a11y": "3.0.2",
+    "eslint-plugin-promise": "^3.3.0",
     "eslint-plugin-react": "^6.4.1",
     "eslint-plugin-standard": "^2.0.0",
-    "extract-text-webpack-plugin": "^2.0.0-beta.4",
-    "file-loader": "^0.9.0",
-    "font-awesome": "^4.7.0",
-    "html-webpack-plugin": "^2.24.0",
-    "json-loader": "^0.5.4",
-    "pubsweet-backend": "0.6.0",
-    "pubsweet-component-blog": "0.1.0",
-    "pubsweet-component-ink-backend": "0.0.4-alpha.3",
-    "pubsweet-component-ink-frontend": "0.0.1",
-    "pubsweet-component-login": "0.2.1",
-    "pubsweet-component-manage": "0.1.0",
-    "pubsweet-component-navigation": "0.1.0",
-    "pubsweet-component-signup": "0.1.0",
-    "pubsweet-component-teams-manager": "0.1.1",
-    "pubsweet-component-theme-editoria": "git+https://gitlab.coko.foundation/yannisbarlas/pubsweet-component-theme-editoria.git",
-    "pubsweet-component-users-manager": "0.1.0",
-    "pubsweet-frontend": "0.7.0",
-    "pubsweet-theme-plugin": "^0.0.1",
-    "react-dnd": "^2.1.4",
-    "react-dnd-html5-backend": "^2.1.2",
-    "react-hot-loader": "^3.0.0-beta.5",
-    "sass-loader": "^4.0.2",
-    "script-loader": "^0.7.0",
-    "string-replace-loader": "^1.0.5",
-    "style-loader": "^0.13.1",
-    "substance": "^1.0.0-beta.5.7",
-    "url-loader": "^0.5.7",
-    "webpack": "^2.1.0-beta.25",
-    "webpack-dev-middleware": "^1.8.4",
-    "webpack-hot-middleware": "^2.13.0"
-  },
-  "devDependencies": {
-    "enzyme": "^2.7.1",
-    "enzyme-to-json": "^1.4.5",
-    "react-addons-test-utils": "^15.4.2",
     "identity-obj-proxy": "^3.0.0",
     "jest": "^18.1.0",
+    "react-addons-test-utils": "^15.4.2",
     "react-test-renderer": "^15.4.2",
     "sinon": "^1.17.7",
     "sinon-as-promised": "^4.0.2"
diff --git a/test/jest.config.js b/test/jest.config.js
index fde58284fe6a2bd43cd38c5741f9b4b17711145d..7c2bd1c3df6d833a2c2839af6b9f41b18d9c0ec0 100644
--- a/test/jest.config.js
+++ b/test/jest.config.js
@@ -1,4 +1,4 @@
-global.CONFIG = { 'pubsweet-backend': '' }
+global.CONFIG = { 'pubsweet-server': '' }
 global.PUBSWEET_COMPONENTS = []
 
 global.mock = {
diff --git a/webpack/babel-includes.js b/webpack/babel-includes.js
index c459384215f365e6891ae6b51c3ef630ac12cedc..0cf6d13a37715dccfa7c42491932ba879c41f768 100644
--- a/webpack/babel-includes.js
+++ b/webpack/babel-includes.js
@@ -1,7 +1,7 @@
 const path = require('path')
 
 var babelIncludes = [
-  new RegExp(path.join(__dirname, '../node_modules/pubsweet-frontend/src')),
+  new RegExp(path.join(__dirname, '../node_modules/pubsweet-client/src')),
   new RegExp(path.join(__dirname, '../app')),
   new RegExp(path.join(__dirname, '../node_modules/pubsweet-.*'))
 ]
diff --git a/webpack/webpack.dev.config.js b/webpack/webpack.dev.config.js
index f187ce07c7e727c0d0a995ba79d7894d00f91d43..6074123277175931f232f8fd7af5206d315fbc43 100644
--- a/webpack/webpack.dev.config.js
+++ b/webpack/webpack.dev.config.js
@@ -18,11 +18,11 @@ module.exports = [
       ]
     },
     output: {
-      path: path.join(__dirname, '..', 'public', 'assets'),
+      path: path.join(__dirname, '..', '_build', 'assets'),
       filename: '[name].js',
       publicPath: '/assets/'
     },
-    devtool: 'inline-source-map',
+    devtool: 'cheap-module-source-map',
     module: {
       rules: require('./common-rules')
     },
@@ -33,7 +33,7 @@ module.exports = [
         path.resolve(__dirname, '..', 'node_modules'),
         'node_modules'
       ],
-      plugins: [new ThemePlugin(config['pubsweet-frontend'].theme)],
+      plugins: [new ThemePlugin(config['pubsweet-client'].theme)],
       extensions: ['.js', '.jsx', '.json', '.scss'],
       enforceExtension: false
     },
@@ -55,6 +55,8 @@ module.exports = [
     ],
     node: {
       fs: 'empty',
+      net: 'empty',
+      dns: 'empty',
       __dirname: true
     }
   }
diff --git a/webpack/webpack.production.config.js b/webpack/webpack.production.config.js
index 9699d4df2be5f77763d7f2edbad28deb1d2deaa3..9b5b3b3dfbfee7757f9f5afab1024e13afe62d1f 100644
--- a/webpack/webpack.production.config.js
+++ b/webpack/webpack.production.config.js
@@ -17,7 +17,7 @@ module.exports = [
       ]
     },
     output: {
-      path: path.join(__dirname, '..', 'public', 'assets'),
+      path: path.join(__dirname, '..', '_build', 'assets'),
       filename: '[name]-[hash].js',
       publicPath: '/assets/'
     },
@@ -32,7 +32,7 @@ module.exports = [
         'node_modules'
       ],
       extensions: ['.js', '.jsx', '.json', '.scss'],
-      plugins: [new ThemePlugin(config['pubsweet-frontend'].theme)]
+      plugins: [new ThemePlugin(config['pubsweet-client'].theme)]
     },
     plugins: [
       new HtmlWebpackPlugin({