diff --git a/app/component-pdf-viewer/client/components/Page.jsx b/app/component-pdf-viewer/client/components/Page.jsx
index d7a30032cd13bee89f78a97664eda1d28a2979c0..5385d11c88e568db0a0b9a1c240342c034ebc004 100755
--- a/app/component-pdf-viewer/client/components/Page.jsx
+++ b/app/component-pdf-viewer/client/components/Page.jsx
@@ -10,7 +10,7 @@ import 'pdfjs-dist/web/pdf_viewer.css'
 import Loading from './Loading'
 
 const PDFPage = styled.div`
-  margin: calc(${th('gridUnit')} / 2) auto;
+  margin: ${th('gridUnit')} auto;
   .page {
     margin 0 auto;
     position: relative;
diff --git a/app/components/App.jsx b/app/components/App.jsx
index 3304c3bcd07834d7315631c5aaff9b55009a9fce..36c55492bcc43abf81574b0882b34b34a106b2fc 100755
--- a/app/components/App.jsx
+++ b/app/components/App.jsx
@@ -34,7 +34,7 @@ const NavSec = styled.div`
   background-color: ${th('colorTextReverse')};
   border-bottom: ${th('borderWidth')} ${th('borderStyle')}
     ${th('colorFurniture')};
-  @media screen and (max-width: 500px) {
+  @media screen and (max-width: 630px) {
     height: calc(${th('gridUnit')} * 9);
   }
 `
diff --git a/app/components/Footer.jsx b/app/components/Footer.jsx
index 88811d5cb052ea18ce6a10d1282ed065e2161ee7..163029e75354801f14ff7920ae26bd71cd60ccca 100644
--- a/app/components/Footer.jsx
+++ b/app/components/Footer.jsx
@@ -8,18 +8,19 @@ const Foot = styled(FlexBar)`
   * {
     font-size: ${th('fontSizeBaseSmall')};
   }
-  @media screen and (max-width: 870px) {
+  @media screen and (max-width: 995px) {
     height: auto;
-  }
-  @media screen and (max-width: 450px) {
     flex-wrap: wrap;
+    z-index: 3;
     & > div:first-child {
       & > div {
+        text-align: center;
         padding-bottom: 0;
       }
       & + div div {
-        text-align: left;
+        text-align: center;
         margin: 0 auto;
+        padding-top: calc(${th('gridUnit')} / 2);
         padding-left: 0;
       }
     }
diff --git a/app/components/ResolveDuplicates.jsx b/app/components/ResolveDuplicates.jsx
index 7974f41c3c8056febdf2bcad73fa1571e25561a1..2fe056b99e6f8cdd6a6dadc64232d5a35429d753 100644
--- a/app/components/ResolveDuplicates.jsx
+++ b/app/components/ResolveDuplicates.jsx
@@ -4,7 +4,7 @@ import { Mutation } from 'react-apollo'
 import styled from 'styled-components'
 import { th } from '@pubsweet/ui-toolkit'
 import { Action, H3, H4, Button, Icon, Link } from '@pubsweet/ui'
-import { B, Buttons, Close, CloseButton, Portal, Notification } from './ui'
+import { B, Buttons, CloseModal, Portal, Notification } from './ui'
 import { States, timeSince } from './dashboard'
 import Citation from './submission-wizard/Citation'
 import { REPLACE_MANUSCRIPT, CHECK_DUPES } from './operations'
@@ -145,9 +145,7 @@ class ResolveDuplicates extends React.Component {
           }
           return (
             <Portal ref={this.setRef} transparent>
-              <Close>
-                <CloseButton onClick={close} />
-              </Close>
+              <CloseModal onClick={close} />
               <Columns>
                 <H3>This manuscript</H3>
                 <H3>Duplicate(s)</H3>
diff --git a/app/components/SubmissionHeader.jsx b/app/components/SubmissionHeader.jsx
index 33a89f094d1b88445430ccf5186fa7c2d02f93e6..36a45b77aed7c205d7ed169578ece06da40075e7 100644
--- a/app/components/SubmissionHeader.jsx
+++ b/app/components/SubmissionHeader.jsx
@@ -17,6 +17,19 @@ const Left = styled.div`
   overflow: hidden;
   text-overflow: ellipsis;
 `
+const FlexDiv = styled.div`
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
+`
+const Progress = styled.span`
+  margin-left: calc(${th('gridUnit')} * 3);
+  font-weight: normal;
+  font-style: italic;
+  color: ${th('colorTextPlaceholder')} &.saved {
+    color: ${th('colorText')};
+  }
+`
 class MailLink extends React.Component {
   state = { show: false }
   render() {
@@ -41,58 +54,85 @@ class MailLink extends React.Component {
   }
 }
 
+let savedTimer
+const addSaved = () => {
+  document.getElementById('progress').classList.add('saved')
+}
+const removeSaved = () => {
+  document.getElementById('progress').classList.remove('saved')
+}
+
 const SubmissionHeader = BaseComponent => ({
   currentUser,
   manuscript,
   children,
+  saved,
   ...props
-}) => (
-  <React.Fragment>
-    <ManuscriptHead>
-      <LeftSide>
-        <Left>
-          {manuscript.id}: <HTMLString string={manuscript.meta.title} />
-        </Left>
-      </LeftSide>
-      <RightSide>
-        <div>
-          {currentUser.admin ? (
-            <React.Fragment>
-              {window.location.pathname ===
-              `/submission/${manuscript.id}/activity` ? (
-                <React.Fragment>
-                  {States.admin[manuscript.status].url !== 'activity' && (
-                    <Link
-                      to={`/submission/${manuscript.id}/${
-                        States.admin[manuscript.status].url
-                      }`}
-                    >
-                      <Icon color="currentColor" size={2.5}>
-                        x-square
-                      </Icon>
-                      Exit activity
-                    </Link>
-                  )}
-                </React.Fragment>
-              ) : (
-                <Link to={`/submission/${manuscript.id}/activity`}>
-                  <Icon color="currentColor" size={2.5}>
-                    check-square
-                  </Icon>
-                  Activity
-                </Link>
-              )}
-            </React.Fragment>
-          ) : (
-            <MailLink currentUser={currentUser} manuscript={manuscript} />
-          )}
-        </div>
-      </RightSide>
-    </ManuscriptHead>
-    <BaseComponent currentUser={currentUser} manuscript={manuscript} {...props}>
-      {children}
-    </BaseComponent>
-  </React.Fragment>
-)
+}) => {
+  if (saved && document.getElementById('progress')) {
+    addSaved()
+  }
+  if (savedTimer) {
+    clearTimeout(savedTimer)
+  }
+  savedTimer = setTimeout(() => {
+    removeSaved()
+  }, 2000)
+  return (
+    <React.Fragment>
+      <ManuscriptHead>
+        <LeftSide>
+          <Left>
+            {manuscript.id}: <HTMLString string={manuscript.meta.title} />
+          </Left>
+        </LeftSide>
+        <RightSide>
+          <FlexDiv>
+            {currentUser.admin ? (
+              <React.Fragment>
+                {window.location.pathname ===
+                `/submission/${manuscript.id}/activity` ? (
+                  <React.Fragment>
+                    {States.admin[manuscript.status].url !== 'activity' && (
+                      <Link
+                        to={`/submission/${manuscript.id}/${
+                          States.admin[manuscript.status].url
+                        }`}
+                      >
+                        <Icon color="currentColor" size={2.5}>
+                          x-square
+                        </Icon>
+                        Exit activity
+                      </Link>
+                    )}
+                  </React.Fragment>
+                ) : (
+                  <Link to={`/submission/${manuscript.id}/activity`}>
+                    <Icon color="currentColor" size={2.5}>
+                      check-square
+                    </Icon>
+                    Activity
+                  </Link>
+                )}
+              </React.Fragment>
+            ) : (
+              <MailLink currentUser={currentUser} manuscript={manuscript} />
+            )}
+            <Progress className="saved" id="progress">
+              Progress saved
+            </Progress>
+          </FlexDiv>
+        </RightSide>
+      </ManuscriptHead>
+      <BaseComponent
+        currentUser={currentUser}
+        manuscript={manuscript}
+        {...props}
+      >
+        {children}
+      </BaseComponent>
+    </React.Fragment>
+  )
+}
 
 export default SubmissionHeader
diff --git a/app/components/SubmissionMutations.jsx b/app/components/SubmissionMutations.jsx
index 9dd0098111e273c5fc3f8378e39721ed4dfe1a18..dacd4455db3fab38d197224cb5e3689a8ade7c07 100644
--- a/app/components/SubmissionMutations.jsx
+++ b/app/components/SubmissionMutations.jsx
@@ -96,7 +96,7 @@ export const ManuscriptMutations = BaseComponent => ({
 export const NoteMutations = BaseComponent => ({
   manuscriptId,
   children,
-  refetch,
+  refetch = [],
   ...props
 }) => (
   <Mutation mutation={UPDATE_NOTE} refetchQueries={() => refetch}>
diff --git a/app/components/activity/ActivityDetails.jsx b/app/components/activity/ActivityDetails.jsx
index b4d93c030ad784550e0d929f6281b7e6f1fd43e2..18e71600861e9ec2d2bd327622dfe878f883f241 100644
--- a/app/components/activity/ActivityDetails.jsx
+++ b/app/components/activity/ActivityDetails.jsx
@@ -4,15 +4,7 @@ import { H2, Button, Action, Link } from '@pubsweet/ui'
 import { th } from '@pubsweet/ui-toolkit'
 import styled from 'styled-components'
 import moment from 'moment'
-import {
-  Buttons,
-  Close,
-  CloseButton,
-  Table,
-  Portal,
-  TextArea,
-  Toggle,
-} from '../ui'
+import { Buttons, CloseModal, Table, Portal, TextArea, Toggle } from '../ui'
 import Mailer from '../mailer'
 import { CREATE_NOTE } from '../operations'
 import EventDescription from './EventDescription'
@@ -99,9 +91,7 @@ const NewNote = ({ close, manuscriptId, message, onChange }) => (
       }
       return (
         <Portal transparent>
-          <Close style={{ margin: 0 }}>
-            <CloseButton onClick={() => close()} />
-          </Close>
+          <CloseModal onClick={() => close()} />
           <H2>Add a note</H2>
           <TextArea
             label="Note (visible only to administrators)"
diff --git a/app/components/activity/ManualCitation.jsx b/app/components/activity/ManualCitation.jsx
index 61f28fba2d35a781b21d1b6a7bbb495a510c337b..3f662997edbf395c7ccd7e977518f44e0e0757f6 100644
--- a/app/components/activity/ManualCitation.jsx
+++ b/app/components/activity/ManualCitation.jsx
@@ -47,7 +47,7 @@ const FPage = props => (
 const LPage = props => (
   <TextField className={props.className} label="Last page" {...props.field} />
 )
-const Elocation = props => (
+const ELocation = props => (
   <TextField className={props.className} label="eLocation" {...props.field} />
 )
 const DOI = props => <TextField label="DOI" {...props.field} />
@@ -109,7 +109,7 @@ const CitationForm = ({ values, errors, touched, ...props }) => (
             className={!values.fpage && values.elocationId && 'current'}
             onClick={e => toggleSwitch(e.currentTarget)}
           >
-            Elocation
+            eLocation
           </Action>
         </SmallToggle>
         <Flex>
@@ -125,7 +125,7 @@ const CitationForm = ({ values, errors, touched, ...props }) => (
           />
           <Field
             className={(!values.elocationId || values.fpage) && 'hidden'}
-            component={Elocation}
+            component={ELocation}
             name="elocationId"
           />
         </Flex>
diff --git a/app/components/activity/MetaEdit.jsx b/app/components/activity/MetaEdit.jsx
index ff0a177161b06f0ee210c904049d48cda646a18a..8d866c8ccb13143ed7bd21fe69648f69897e16a8 100644
--- a/app/components/activity/MetaEdit.jsx
+++ b/app/components/activity/MetaEdit.jsx
@@ -4,7 +4,7 @@ import styled, { withTheme } from 'styled-components'
 import { th } from '@pubsweet/ui-toolkit'
 import { Action, H2, Button, Icon, TextField } from '@pubsweet/ui'
 import { states } from 'config'
-import { Portal, Buttons, Close, CloseButton, Notification } from '../ui'
+import { Portal, Buttons, CloseModal, Notification } from '../ui'
 import { ManuscriptMutations, NoteMutations } from '../SubmissionMutations'
 import ResolveDuplicates from '../ResolveDuplicates'
 import GrantSearch from '../GrantSearch'
@@ -94,9 +94,7 @@ const MetaEdit = withTheme(
     }
     return (
       <Portal style={{ backgroundColor: theme.colorBackground }} transparent>
-        <Close>
-          <CloseButton onClick={close} />
-        </Close>
+        <CloseModal onClick={close} />
         <React.Fragment>
           {(() => {
             switch (toEdit) {
diff --git a/app/components/citation-search/PubMedSearch.jsx b/app/components/citation-search/PubMedSearch.jsx
index 11b5b86906e6be3f4c6afcca582ed12a488fb9e0..ba8932b547a5343275417503c4011a93ced193e3 100755
--- a/app/components/citation-search/PubMedSearch.jsx
+++ b/app/components/citation-search/PubMedSearch.jsx
@@ -8,8 +8,7 @@ import {
   A,
   B,
   Buttons,
-  Close,
-  CloseButton,
+  CloseModal,
   HTMLString,
   Loading,
   LoadingIcon,
@@ -253,11 +252,7 @@ class PubMedSearch extends React.Component {
       <SearchArea>
         {this.state.unmatched && (
           <Portal transparent>
-            <Close>
-              <CloseButton
-                onClick={() => this.setState({ unmatched: false })}
-              />
-            </Close>
+            <CloseModal onClick={() => this.setState({ unmatched: false })} />
             <UnmatchedCitation
               citation={this.handleUnmatched}
               close={() => this.setState({ unmatched: false })}
diff --git a/app/components/dashboard/AdminDashboard.jsx b/app/components/dashboard/AdminDashboard.jsx
index 6e04bc1a841d9ef8eac94ebadfc4424717309a80..3920ccfbda070d34ebb37c5034aa1e8202a20025 100755
--- a/app/components/dashboard/AdminDashboard.jsx
+++ b/app/components/dashboard/AdminDashboard.jsx
@@ -16,8 +16,8 @@ const ListTable = styled(Table)`
   }
 `
 const HelpdeskQueue = {
-  'needs submission review': ['submitted'],
-  'needs xml review': ['xml-qa'],
+  'needs submission QA': ['submitted'],
+  'needs xml QA': ['xml-qa'],
   'xml error reported': ['xml-triage'],
   'needs citation': ['xml-complete'],
 }
diff --git a/app/components/mailer/MailerForm.jsx b/app/components/mailer/MailerForm.jsx
index 66bcb26108c0879a83dbce387219f377af75f67f..1d3c92fb736bfc90a7fad18c469f5a635e5315f5 100644
--- a/app/components/mailer/MailerForm.jsx
+++ b/app/components/mailer/MailerForm.jsx
@@ -4,7 +4,7 @@ import { capitalize } from 'lodash'
 import styled from 'styled-components'
 import { th, override } from '@pubsweet/ui-toolkit'
 import { Button, H2, TextField, CheckboxGroup } from '@pubsweet/ui'
-import { Buttons, TextArea, Portal, Close, CloseButton } from '../ui'
+import { Buttons, TextArea, Portal, CloseModal } from '../ui'
 
 const Recipient = styled.fieldset`
   border: 0;
@@ -48,9 +48,7 @@ const MailerForm = props => {
   })
   return (
     <Portal transparent>
-      <Close style={{ margin: 0 }}>
-        <CloseButton onClick={() => props.close()} />
-      </Close>
+      <CloseModal onClick={() => props.close()} />
       <H2>Send an email</H2>
       <form onSubmit={props.handleSubmit}>
         <Recipient>
diff --git a/app/components/preview-files/FileLightbox.jsx b/app/components/preview-files/FileLightbox.jsx
index 5ae58e2a4d804de1123ee24ee1095baf3120a686..f97caca59dfc353d25d6cc52b4fcb6b4299a63d0 100755
--- a/app/components/preview-files/FileLightbox.jsx
+++ b/app/components/preview-files/FileLightbox.jsx
@@ -4,7 +4,7 @@ import styled from 'styled-components'
 import { Action } from '@pubsweet/ui'
 import { th } from '@pubsweet/ui-toolkit'
 import PDFViewer from '../../component-pdf-viewer'
-import { A, Page, Center, Cover, Close, CloseButton } from '../ui'
+import { A, Page, Center, Cover, CloseModal } from '../ui'
 import { ImageTypes } from './'
 
 const Image = styled.img`
@@ -55,11 +55,7 @@ class FilePreview extends React.Component {
           ReactDOM.createPortal(
             <Cover>
               <Page>
-                <Close>
-                  <CloseButton
-                    onClick={() => this.setState({ preview: null })}
-                  />
-                </Close>
+                <CloseModal onClick={() => this.setState({ preview: null })} />
                 {preview.mimeType === 'application/pdf' ? (
                   <PDF>
                     <PDFViewer url={preview.url} />
diff --git a/app/components/review-wizard/ReviewFooter.jsx b/app/components/review-wizard/ReviewFooter.jsx
index 422971611203ca54da65cb42b8ad56fca28d48c3..64ce885c1e03476ee6af6a621494e2f5d5f553da 100644
--- a/app/components/review-wizard/ReviewFooter.jsx
+++ b/app/components/review-wizard/ReviewFooter.jsx
@@ -1,40 +1,24 @@
 import React from 'react'
 import { withRouter } from 'react-router'
 import { Mutation } from 'react-apollo'
-import styled from 'styled-components'
-import { th } from '@pubsweet/ui-toolkit'
-import { Action, Button, H2, Icon } from '@pubsweet/ui'
-import {
-  PreviewFooter,
-  Notification,
-  Buttons,
-  Portal,
-  Close,
-  CloseButton,
-} from '../ui'
+import { Action, Button, H2, Icon, RadioGroup } from '@pubsweet/ui'
+import { PreviewFooter, Notification, Buttons, Portal, CloseModal } from '../ui'
 import SubmissionCancel from '../SubmissionCancel'
 import { REVIEW_MANUSCRIPT, GET_REVIEWS, CURRENT_REVIEW } from './operations'
 import ReviewInstructions from './ReviewInstructions'
 import ListErrors from './ListErrors'
 import SubmissionError from './SubmissionError'
 
-const SmallAction = styled(Action)`
-  font-size: ${th('fontSizeBaseSmall')};
-  font-weight: 600;
-`
-const showPopup = button => {
-  button.parentNode.nextElementSibling.classList.remove('hidden')
-}
-
 class ReviewFooter extends React.Component {
   state = {
     report: false,
     approve: false,
     cancel: false,
+    radio: '',
   }
   render() {
     const { currentUser, manuscript, previews, review, history } = this.props
-    const { report, approve, cancel } = this.state
+    const { report, approve, cancel, radio } = this.state
     const { annotations } = review || []
     const { status, teams } = manuscript
     const submitter = teams.find(t => t.role === 'submitter').teamMembers[0]
@@ -71,54 +55,59 @@ class ReviewFooter extends React.Component {
                   </Button>
                 )
               } else if (manuscript.status === 'xml-triage') {
+                const options = [
+                  {
+                    value: 'xml-qa',
+                    label: 'XML QA',
+                  },
+                  {
+                    value: 'xml-review',
+                    label: 'Author review',
+                  },
+                  {
+                    value: 'xml-complete',
+                    label: 'PMC (skip review)',
+                  },
+                ]
                 return (
                   <div>
                     <Button
                       onClick={() => this.setState({ approve: true })}
                       primary
                     >
-                      Approve and route
+                      Approve &amp; route
                     </Button>
                     <Button onClick={() => this.setState({ report: true })}>
                       Ask for correction
                     </Button>
                     {approve && (
                       <Portal transparent>
-                        <Close>
-                          <CloseButton
-                            onClick={() => this.setState({ approve: false })}
-                          />
-                        </Close>
+                        <CloseModal
+                          onClick={() => this.setState({ approve: false })}
+                        />
                         <H2>Errors fixed? Send for:</H2>
-                        <Buttons>
-                          <Button onClick={() => setStatus('xml-qa')} primary>
-                            XML QA
-                          </Button>
+                        <RadioGroup
+                          name="setstatus"
+                          onChange={radio => this.setState({ radio })}
+                          options={options}
+                        />
+                        <Buttons right>
                           <Button
+                            disabled={!radio}
                             onClick={async () => {
-                              await setStatus('xml-review')
-                              history.push('/')
+                              await setStatus(radio)
+                              if (radio === 'xml-qa') {
+                                this.setState({ approve: false })
+                              } else {
+                                history.push(
+                                  `/submission/${manuscript.id}/activity`,
+                                )
+                              }
                             }}
                             primary
                           >
-                            Author review
+                            Confirm &amp; send
                           </Button>
-                          <Button
-                            onClick={e => showPopup(e.currentTarget)}
-                            primary
-                          >
-                            PMC (skip review)
-                          </Button>
-                        </Buttons>
-                        <Notification className="hidden" type="warning">
-                          Are you sure you want to skip author review?{' '}
-                          <SmallAction
-                            onClick={() => setStatus('xml-complete')}
-                          >
-                            I&apos;m sure!
-                          </SmallAction>
-                        </Notification>
-                        <Buttons right>
                           <Button
                             onClick={() => this.setState({ approve: false })}
                           >
@@ -166,9 +155,9 @@ class ReviewFooter extends React.Component {
                         <p>
                           {status === 'xml-review'
                             ? `Approve the final web versions of the manuscript for release to Europe PMC now?`
-                            : `Confirm QA has been completed, and approve the web versons of the manuscript?`}
+                            : `Confirm QA has been completed, and approve the web versions of the manuscript?`}
                         </p>
-                        {annotations && (
+                        {annotations && annotations.length > 0 && (
                           <Notification type="warning">
                             {`Errors have been highlighted! Are you sure you want to approve the submission, rather than submitting your error report?`}
                           </Notification>
@@ -197,13 +186,11 @@ class ReviewFooter extends React.Component {
                     )}
                     {report && (
                       <React.Fragment>
-                        {annotations ? (
+                        {annotations && annotations.length > 0 ? (
                           <Portal transparent>
-                            <Close>
-                              <CloseButton
-                                onClick={() => this.setState({ report: false })}
-                              />
-                            </Close>
+                            <CloseModal
+                              onClick={() => this.setState({ report: false })}
+                            />
                             <H2>Send the following errors?</H2>
                             <ListErrors annotations={annotations} />
                             <Buttons right>
diff --git a/app/components/review-wizard/ReviewPage.jsx b/app/components/review-wizard/ReviewPage.jsx
index a716a6d08965079ea27777b8e572d2697685bfc4..9985271ffecd0bb8d2d64852b538dbe3ead94825 100644
--- a/app/components/review-wizard/ReviewPage.jsx
+++ b/app/components/review-wizard/ReviewPage.jsx
@@ -31,10 +31,12 @@ const ReviewPage = ({ match, ...props }) => (
           }
           return (
             <ReviewWithHeader
+              key={`${manuscript.id}${manuscript.status}`}
               manuscript={manuscript}
               match={match}
               reload={() => refetch()}
               review={currentReview}
+              saved={new Date()}
               {...props}
             />
           )
diff --git a/app/components/review-wizard/SubmissionError.jsx b/app/components/review-wizard/SubmissionError.jsx
index bfdd79257515129195da0b5b75cdbc1b34f1f887..3feaea5e6627e06e715a9cc231ca098c7d8aa52a 100644
--- a/app/components/review-wizard/SubmissionError.jsx
+++ b/app/components/review-wizard/SubmissionError.jsx
@@ -2,7 +2,7 @@ import React from 'react'
 import styled from 'styled-components'
 import { th } from '@pubsweet/ui-toolkit'
 import { Action, H2, CheckboxGroup } from '@pubsweet/ui'
-import { Portal, Close, CloseButton, Loading, LoadingIcon, Toggle } from '../ui'
+import { Portal, CloseModal, Loading, LoadingIcon, Toggle } from '../ui'
 import SubmissionErrorReport, {
   adminOptions,
   Fieldset,
@@ -91,9 +91,7 @@ class SubmissionError extends React.Component {
     const html = manuscript.files.find(file => file.type === 'tempHTML')
     return (
       <Portal transparent>
-        <Close style={{ margin: 0 }}>
-          <CloseButton onClick={close} />
-        </Close>
+        <CloseModal onClick={close} />
         <H2>Report Errors</H2>
         <Toggle>
           <Action
diff --git a/app/components/submission-wizard/CreateInfo.jsx b/app/components/submission-wizard/CreateInfo.jsx
index cb8e01234a8de1d40e7c25c09c03d7fa694d84bc..8cf3b2baabea436fe911a230a1b39b24e07d6e34 100755
--- a/app/components/submission-wizard/CreateInfo.jsx
+++ b/app/components/submission-wizard/CreateInfo.jsx
@@ -1,27 +1,26 @@
 import React from 'react'
-import { H3, Link } from '@pubsweet/ui'
+import { H2, H3, Link } from '@pubsweet/ui'
 import { A } from '../ui'
 
 const CreateInfo = ({ currentStep }) => (
   <React.Fragment>
     {currentStep === 0 && (
       <div className="createInfo">
-        <H3>Getting started</H3>
-        <p>
-          {`The first step to submitting a manuscript is to find the manuscript title and citation. We provide a title lookup function which will search Pubmed for a citation. If you can't find the manuscript, enter the information manually.`}
-        </p>
+        <H2>Getting started</H2>
         <H3>What you’ll need to complete the submission</H3>
         <ul>
           <li>Manuscript title</li>
-          <li>Journal name if not in PubMed</li>
+          <li>
+            Journal name, other citation information if not found in PubMed
+          </li>
           <li>Grant numbers</li>
           <li>All manuscript files including supplemental data</li>
         </ul>
         <H3>Overview of the process</H3>
         <ol>
           <li>Submit manuscript</li>
-          <li>Review PDF for completeness</li>
-          <li>Review final web version</li>
+          <li>Review submission for completeness</li>
+          <li>Proof final web version</li>
         </ol>
         <H3>How long it will take</H3>
         <p>
@@ -31,15 +30,15 @@ const CreateInfo = ({ currentStep }) => (
     )}
     {currentStep === 1 && (
       <div className="createInfo">
+        <H2>Preparing files</H2>
         <H3>Which versions of files should I upload?</H3>
         <p>
-          {`Authors can check the `}
+          {`Generally, the accepted peer reviewed version of the manuscript, or the version of record for creative commons licensed articles, should be submitted. Check your journal’s version policy at `}
           <A href="http://www.sherpa.ac.uk/romeo/index.php" target="_blank">
             SHERPA/RoMEO
           </A>
-          {` database for publishers' open access policies.`}
         </p>
-        <H3>How should I label files?</H3>
+        <H3>What is the best way to label files?</H3>
         <p>
           {`The labels are intended to help reviewers put your manuscript together as intended. Provide a label that matches the corresponding file as mentioned in the text.`}
         </p>
@@ -55,33 +54,31 @@ const CreateInfo = ({ currentStep }) => (
     )}
     {currentStep === 2 && (
       <div className="createInfo">
+        <H2>Grants & embargo periods</H2>
         <H3>
           {`What if a grant or project that supported this manuscript is not in the list?`}
         </H3>
         <p>
-          {`If a particular grant or project that you are expecting to see is not listed, please verify that the proper PI surname was entered. You must enter the surname first. In addition to the surname you may enter the initial of the PI&apos;s given name (e.g. 'Smith R', not 'Smith Robert').`}
+          {`If a particular grant or project that you are expecting to see is not listed, please verify that the proper PI name was entered. You should use an initial rather than the full first name, e.g. “R” instead of “Robert”.`}
+        </p>
+        <p>
+          {`If you can’t locate your grant and/or project in the list, click the link above to contact the Helpdesk for help locating your grant. Please provide the grant/contract number, project title, and contact PI's name.`}
         </p>
+        <H3>How to select an embargo period</H3>
         <p>
-          {`If you can’t locate your grant and/or project in the list, contact the Helpdesk to ask for help locating your grant. You'll be asked to provide the grant/contract number, project title, and contact PI's name.`}
+          {`The embargo period lets us know the delay from the time the manuscript is published in the journal until it can be published in Europe PMC. The embargo periods listed are those allowed by your funder. `}
         </p>
-        <H3>Selecting an embargo period</H3>
         <p>
-          {`The embargo period lets us know the delay from the time the manuscript is published in the journal until it can be published in Europe PMC. The embargo periods listed are those allowed by your funder. If there is a conflict between the embargo period required by your journal and those allowed by your funder, please contact the Helpdesk.`}
+          {`If you’re not sure which embargo period to choose, or if there is a conflict between the period required by your journal and those allowed by your funder, please contact the Helpdesk.`}
         </p>
       </div>
     )}
     {currentStep === 3 && (
       <div className="createInfo">
-        <H3>What is a reviewer?</H3>
-        <p>
-          {`The reviewer will have final approval over the web version of this manuscript submission created for Europe PMC. Most commonly, you, the submitter, will also be the reviewer. If you are submitting this manuscript on behalf of someone else, please designate that person as the reviewer.`}
-        </p>
-        <p>
-          {`The designated reviewer must be one of the authors of the manuscript.`}
-        </p>
-        <H3>What if the correct person isn&apos;t listed?</H3>
+        <H2>Selecting a reviewer</H2>
+        <H3>What is the reviewer responsible for?</H3>
         <p>
-          {`The options provided for the reviewer include you and the PIs of your selected grants. If the reviewer should be someone other than you or one of your grant PIs, please select the last option, 'Other reviewer', and enter the person's name and email address in the fields provided.`}
+          {`The reviewer is responsible for approving the final web version of the manuscript which will be released to Europe PMC. The designated reviewer must be one of the authors of the manuscript.`}
         </p>
       </div>
     )}
diff --git a/app/components/submission-wizard/CreatePage.jsx b/app/components/submission-wizard/CreatePage.jsx
index 5f3db840bf135d503d39b048099d928aaae8de4a..7c14004803c30a13064ed6d9c02687af4ee7d67e 100755
--- a/app/components/submission-wizard/CreatePage.jsx
+++ b/app/components/submission-wizard/CreatePage.jsx
@@ -226,7 +226,7 @@ class Created extends React.Component {
         : null
     if (manuscript.status === 'INITIAL') {
       return (
-        <SplitPage>
+        <SplitPage withHeader>
           <StepPanel>
             <div>
               <CreatePageHeader currentStep={currentStep} />
@@ -303,7 +303,9 @@ class Created extends React.Component {
                         : ''
                     }
                   >
-                    {this.state.showSearch ? 'Cancel citation change' : 'Next'}
+                    {(this.state.showSearch && 'Cancel citation change') ||
+                      (currentStep === 3 && 'Save & preview') ||
+                      'Next'}
                   </Button>
                   {!this.state.showSearch && (
                     <Button onClick={this.goPrev}>
@@ -376,6 +378,7 @@ const CreatePage = ({ match, ...props }) => (
         <CreatedWithHeader
           manuscript={data.manuscript}
           match={match}
+          saved={new Date()}
           {...props}
         />
       )
diff --git a/app/components/submission-wizard/Submit.jsx b/app/components/submission-wizard/Submit.jsx
index 29b88bc73d9b3f697e0239993310598e3da1af71..500b642101a4525bbd0834bf91d3da4138193792 100644
--- a/app/components/submission-wizard/Submit.jsx
+++ b/app/components/submission-wizard/Submit.jsx
@@ -5,8 +5,7 @@ import { Button, Action, CheckboxGroup, H1, H2, H3, Icon } from '@pubsweet/ui'
 import {
   Page,
   Buttons,
-  Close,
-  CloseButton,
+  CloseModal,
   PreviewPage,
   PreviewFooter,
   PreviewPanel,
@@ -35,10 +34,9 @@ const Alert = withTheme(({ children, theme }) => (
   </Icon>
 ))
 
-const CloseEdit = styled(Close)`
+const CloseEdit = styled(CloseModal)`
   margin: calc(${th('gridUnit')} * 6) auto calc(${th('gridUnit')} * 2);
 `
-
 const ErrorReport = styled.p`
   white-space: pre-wrap;
   font-style: italic;
@@ -164,11 +162,7 @@ class Submit extends React.Component {
             } else if (editing) {
               return (
                 <Page>
-                  <CloseEdit>
-                    <CloseButton
-                      onClick={() => this.setState({ editing: null })}
-                    />
-                  </CloseEdit>
+                  <CloseEdit onClick={() => this.setState({ editing: null })} />
                   {editing.props['data-upload'] ? (
                     <div>
                       <H2>Files</H2>
@@ -367,9 +361,7 @@ class Submit extends React.Component {
           )}
           {reject && (
             <Portal transparent>
-              <Close style={{ margin: 0 }}>
-                <CloseButton onClick={() => this.setState({ reject: false })} />
-              </Close>
+              <CloseModal onClick={() => this.setState({ reject: false })} />
               {currentUser.admin && status === 'submitted' ? (
                 <SubmissionErrorReport
                   checkedBoxes={checkedBoxes}
diff --git a/app/components/submission-wizard/SubmitPage.jsx b/app/components/submission-wizard/SubmitPage.jsx
index 1a5b3f73e8576adb79864a456d2162e2867f770f..84e98ab4e5f1fae3345b5dd8ad70fcfc5ed93051 100755
--- a/app/components/submission-wizard/SubmitPage.jsx
+++ b/app/components/submission-wizard/SubmitPage.jsx
@@ -10,7 +10,7 @@ import Submit from './Submit'
 const SubmitWithMutations = ManuscriptMutations(Submit)
 const SubmitWithHeader = SubmissionHeader(SubmitWithMutations)
 
-const DupeCheckSubmitPage = ({ manuscript, ...props }) => {
+const DupeCheckSubmitPage = ({ manuscript, saved, ...props }) => {
   const { id, meta } = manuscript
   const { title, articleIds: aids } = meta
   const articleIds = aids ? aids.map(aid => aid.id) : null
@@ -35,6 +35,7 @@ const DupeCheckSubmitPage = ({ manuscript, ...props }) => {
           <SubmitWithHeader
             duplicates={manuscripts}
             manuscript={manuscript}
+            saved={saved}
             {...props}
           />
         )
@@ -62,6 +63,7 @@ const SubmitPage = ({ match, currentUser, ...props }) => (
           <DupeCheckSubmitPage
             currentUser={currentUser}
             manuscript={data.manuscript}
+            saved={new Date()}
             {...props}
           />
         )
@@ -70,6 +72,7 @@ const SubmitPage = ({ match, currentUser, ...props }) => (
         <SubmitWithHeader
           currentUser={currentUser}
           manuscript={data.manuscript}
+          saved={new Date()}
           {...props}
         />
       )
diff --git a/app/components/submission-wizard/SubmitText.jsx b/app/components/submission-wizard/SubmitText.jsx
index c30a7252f6fb0a87a0950ab4a1c7bd5353aca2da..c34599a05f82daf0fb69d757ccc26519088a20d6 100755
--- a/app/components/submission-wizard/SubmitText.jsx
+++ b/app/components/submission-wizard/SubmitText.jsx
@@ -50,7 +50,7 @@ const SubmitText = ({ currentUser, teams, status, history }) => {
                   {`Approve the submission for processing, or reject it to send it back to the submitter with comments. Alternatively, you may edit the manuscript submission yourself.`}
                 </p>
                 <p>
-                  {`You will be responsible for approving the final web version. You must be an author of the manuscript. If you do not meet the requirements to review and approve this manuscript submission, please return the manuscript to the submitter, or contact the helpdesk.`}
+                  {`After processing, you will be responsible for approving the final web version of the submission. You must be an author of the manuscript. If you do not meet the requirements to review and approve this manuscript submission, please return the manuscript to the submitter, or contact the helpdesk.`}
                 </p>
               </React.Fragment>
             )}
diff --git a/app/components/ui/atoms/CloseButton.jsx b/app/components/ui/atoms/CloseButton.jsx
index f9cb28bff07e8484cc462e1ed9b009f65aff2218..51e04ff50b2e93118af47d8bc302074e696f1619 100755
--- a/app/components/ui/atoms/CloseButton.jsx
+++ b/app/components/ui/atoms/CloseButton.jsx
@@ -6,8 +6,11 @@ const Close = styled.p`
   display: flex;
   align-items: center;
   justify-content: flex-end;
+  margin: 0;
+  & + h2 {
+    margin-top: 0;
+  }
 `
-
 const CloseButton = ({ size = 4, ...props }) => (
   <Action {...props}>
     <Icon color="currentColor" size={size}>
@@ -16,4 +19,10 @@ const CloseButton = ({ size = 4, ...props }) => (
   </Action>
 )
 
-export { Close, CloseButton }
+const CloseModal = ({ className, ...props }) => (
+  <Close className={className}>
+    <CloseButton {...props} />
+  </Close>
+)
+
+export { CloseModal, CloseButton }
diff --git a/app/components/ui/atoms/Modal.jsx b/app/components/ui/atoms/Modal.jsx
index f3ef0564a352d8c39ba6548da1af7900c29ff3ee..fb41d8f826453ab60f0f49f445e344b8fe812e23 100644
--- a/app/components/ui/atoms/Modal.jsx
+++ b/app/components/ui/atoms/Modal.jsx
@@ -14,11 +14,6 @@ export const Modal = styled.div`
   max-width: 90%;
   box-sizing: border-box;
   margin: calc(${th('gridUnit')} * 4) auto;
-  & > p:first-child {
-    & + h2 {
-      margin-top: 0;
-    }
-  }
   h2:first-child {
     margin-top: 0;
   }
diff --git a/app/components/ui/atoms/Page.jsx b/app/components/ui/atoms/Page.jsx
index d17b62d260656d24bb8a385418ba7f32a866727d..b18c4364ed03240c691c87680013928ccecd60f2 100755
--- a/app/components/ui/atoms/Page.jsx
+++ b/app/components/ui/atoms/Page.jsx
@@ -10,6 +10,15 @@ const Page = styled.div`
   padding: ${th('gridUnit')} calc(${th('gridUnit')} * 4)
     calc(${th('gridUnit')} * 4);
   box-sizing: border-box;
+  @media screen and (max-width: 995px) {
+    min-height: calc(
+      100vh -
+        (
+          ${th('gridUnit')} *
+            ${props => (props.withHeader ? '31.125' : '23.125')}
+        )
+    );
+  }
 `
 const FlexBar = styled.div`
   display: flex;
diff --git a/app/components/ui/atoms/PreviewPage.jsx b/app/components/ui/atoms/PreviewPage.jsx
index af3d2b73a95aaf188bcbf1b5c34dcd6b394c1858..9add488ac45f99c978a88c8ebabfeb4854e414ee 100755
--- a/app/components/ui/atoms/PreviewPage.jsx
+++ b/app/components/ui/atoms/PreviewPage.jsx
@@ -8,7 +8,9 @@ export const PreviewPage = styled.div`
   background-color: ${th('colorBackground')};
   min-height: calc(100vh - (${th('gridUnit')} * 38));
   box-sizing: border-box;
-
+  @media screen and (max-width: 995px) {
+    min-height: calc(100vh - (${th('gridUnit')} * 39.125));
+  }
   @media screen and (max-width: 870px) {
     flex-wrap: wrap;
     min-height: 0;
diff --git a/app/components/ui/atoms/SplitPage.jsx b/app/components/ui/atoms/SplitPage.jsx
index cf2fa85fc10fe48cd276b1605bd620a32d68bd17..5652305e85c68fe72cc1dff648dabce2bb4df239 100755
--- a/app/components/ui/atoms/SplitPage.jsx
+++ b/app/components/ui/atoms/SplitPage.jsx
@@ -9,19 +9,19 @@ const SplitPage = styled.div`
   min-height: calc(100vh - (${th('gridUnit')} * 28));
   box-sizing: border-box;
 
+  @media screen and (max-width: 995px) {
+    min-height: calc(
+      100vh -
+        (
+          ${th('gridUnit')} *
+            ${props => (props.withHeader ? '31.125' : '23.125')}
+        )
+    );
+  }
   @media screen and (max-width: 870px) {
-    min-height: 0;
     height: auto;
     flex-direction: column-reverse;
     align-items: center;
-    & > div {
-      flex: 1 0 auto;
-      min-height: 0;
-      width: 100%;
-      & > div {
-        max-width: 100%;
-      }
-    }
   }
 `
 const StepPanel = styled.div`
@@ -33,6 +33,13 @@ const StepPanel = styled.div`
     padding: 0 calc(${th('gridUnit')} * 4) calc(${th('gridUnit')} * 4);
     background-color: ${th('colorBackground')};
   }
+  @media screen and (max-width: 870px) {
+    flex: 1 1 auto
+    width: 100%;
+    & > div {
+      max-width: 100%;
+    }
+  }
 `
 const InfoPanel = styled.div`
   flex: 1 1 500px;
@@ -49,10 +56,16 @@ const InfoPanel = styled.div`
   }
 
   @media screen and (max-width: 870px) {
+    min-height: 0;
     box-shadow: 0 2px 2px -2px ${th('colorBorder')};
     border-left: 0;
     border-bottom: ${th('borderWidth')} ${th('borderStyle')}
       ${th('colorBorder')};
+    flex: 0 0 auto;
+    width: 100%;
+    & > div {
+      max-width: 100%;
+    }
 
     .createInfo {
       display: none;
diff --git a/app/components/ui/atoms/index.js b/app/components/ui/atoms/index.js
index 6053415fdd20c2ef941054bffdd6990e15194b32..9ea8eedd4bdc3368d9188835a937e1eac425b941 100755
--- a/app/components/ui/atoms/index.js
+++ b/app/components/ui/atoms/index.js
@@ -1,5 +1,5 @@
 export { LoadingIcon, Loading } from './LoadingIcon'
-export { Close, CloseButton } from './CloseButton'
+export { CloseModal, CloseButton } from './CloseButton'
 export { default as HTMLString } from './HTMLString'
 export { default as Select } from './Select'
 export { default as TextArea } from './TextArea'
diff --git a/server/email/index.js b/server/email/index.js
index 81b90763651b0a0122b676660e63b4d0df7118d5..a3a9836ab0fdbbd6fc28c4d667b635a519921881 100755
--- a/server/email/index.js
+++ b/server/email/index.js
@@ -74,9 +74,9 @@ const errorDevEmail = err => {
   sendMail(dev, subject, html, null, null, system)
 }
 
-const bulkUploaderEmail = (email, message) => {
+const bulkUploaderEmail = (email, message, filename = '') => {
   const html = bulkUploadTemplate(message)
-  const subject = 'Error while processing package'
+  const subject = `Error while processing package ${filename}`
   sendMail(email, subject, html, null, null, system)
 }
 
diff --git a/server/ftp-integration/api.js b/server/ftp-integration/api.js
index 6de13f43e0961a9aa0b92d50bd2f1e9713b8aa84..34a70e7346dada3321a32fa1829f750df7fd9edc 100644
--- a/server/ftp-integration/api.js
+++ b/server/ftp-integration/api.js
@@ -95,8 +95,7 @@ process
     if (err.submitter) {
       bulkUploaderEmail(err.submitter.email, err.message)
     }
-    errorDevEmail(err)
-    logger.error('whoops! there was an error', err.stack)
+    logger.error('Error in ftp-integration (api.js)', err.stack)
     tidyUp(err.filePath, err.tmpPath, err.manId, true)
   })
   .on('unhandledRejection', (reason, promise) => {
@@ -120,7 +119,10 @@ watcher
 watcher
   .on('addDir', path => logger.debug(`Directory ${path} has been added`))
   .on('unlinkDir', path => logger.debug(`Directory ${path} has been removed`))
-  .on('error', error => logger.error(`Watcher error: ${error}`))
+  .on('error', error => {
+    logger.error(`Watcher error: ${error}`)
+    errorDevEmail(`Watcher error: ${error}`)
+  })
   .on('ready', () =>
     logger.info(
       `Initial scan complete. Ready for changes under folder ${rootPath}`,
@@ -166,36 +168,46 @@ function getUser(rootPath, filename) {
 }
 
 function runProcess(packagePath) {
-  logger.info(`Starting Bulk Import Process for ${packagePath}`)
-  // global.globalPath = packagePath
-  const packageName = path.basename(packagePath)
-  getUser(rootPath, packagePath).then(submitter =>
-    authenticate(pubsweetServer, submitter).then(token =>
-      createTempDir().then(tmpPath =>
-        extractFiles(packagePath, tmpPath).then(tmpPath =>
-          parseManifest(tmpPath, packageName, submitter).then(parsedInfo =>
-            parseXml(parsedInfo.metaXml).then(
-              async xmlObj => {
-                // convertFromInk(pubsweetServer, parsedInfo, token).then(
-                //   async convertedManuscript => {
-                const manuscriptDb = await createManuscript(
-                  pubsweetServer,
-                  xmlObj,
-                  parsedInfo,
-                  tmpPath,
-                  submitter,
-                  packageName,
-                  packagePath,
-                )
-                tidyUp(packagePath, tmpPath, manuscriptDb)
-              },
-              // ),
+  try {
+    logger.info(`Starting Bulk Import Process for ${packagePath}`)
+    // global.globalPath = packagePath
+    const packageName = path.basename(packagePath)
+    getUser(rootPath, packagePath).then(submitter =>
+      authenticate(pubsweetServer, submitter).then(token =>
+        createTempDir().then(tmpPath =>
+          extractFiles(packagePath, tmpPath).then(tmpPath =>
+            parseManifest(tmpPath, packageName, submitter).then(parsedInfo =>
+              parseXml(parsedInfo.metaXml).then(
+                async xmlObj => {
+                  // convertFromInk(pubsweetServer, parsedInfo, token).then(
+                  //   async convertedManuscript => {
+                  const manuscriptDb = await createManuscript(
+                    pubsweetServer,
+                    xmlObj,
+                    parsedInfo,
+                    tmpPath,
+                    submitter,
+                    packageName,
+                    packagePath,
+                  )
+                  await tidyUp(packagePath, tmpPath, manuscriptDb)
+                },
+                // ),
+              ),
             ),
           ),
         ),
       ),
-    ),
-  )
+    )
+  } catch (error) {
+    if (error.submitter) {
+      bulkUploaderEmail(error.submitter.email, error.message)
+    }
+    errorDevEmail(`Error with ftp-integration - api.js
+    Error: ${error}`)
+    logger.error('Error with ftp-integration - api.js', error.stack)
+    // await tidyUp(error.filePath, error.tmpPath, error.manId, true)
+  }
 }
 
 function createTempDir() {
@@ -715,7 +727,11 @@ async function createManuscript(
       const { fileURI } = manuscriptFile
 
       if (path.extname(fileURI).startsWith('.doc')) {
-        await xsweetConverter.xsweetConvert(fileURI, manuscriptdb.id)
+        await xsweetConverter.xsweetConvert(
+          fileURI,
+          manuscriptdb.id,
+          submitter.id,
+        )
       }
       await submitManuscript(manuscriptdb, submitter)
     })
diff --git a/server/ftp-integration/taggedXML.js b/server/ftp-integration/taggedXML.js
index e48fd8623ab500c2ec07044c88b7afbc1dfde585..6a5353e3ffce65b78cb1f0cd037c893ba0115944 100644
--- a/server/ftp-integration/taggedXML.js
+++ b/server/ftp-integration/taggedXML.js
@@ -7,7 +7,8 @@ const db = require('../utils/db.js')
 const { execSync } = require('child_process')
 const uuidv4 = require('uuid/v4')
 const config = require('config')
-const manuscriptModel = require('../xpub-model/entities/manuscript/data-access')
+const manuscriptModel = require('../xpub-model/entities/manuscript')
+const { pushXML } = require('../xml-validation')
 
 const ftpTagger = config.get('ftp_tagger')
 const {
@@ -26,7 +27,7 @@ const ignoreNewFolder = `${parentRootPath}/New`
 
 const errorFolder = `${parentRootPath}/Error`
 
-const cmd = `mkdir -p ${rootPath} ${ignoreNewFolder} ${errorFolder}`
+const cmd = `mkdir -p ${rootPath} ${ignoreNewFolder} ${errorFolder}; chmod 777 ${rootPath} ${ignoreNewFolder} ${errorFolder}`
 execSync(cmd)
 
 // chokidar monitors tagged folder
@@ -41,11 +42,7 @@ const watcher = chokidar.watch(`${rootPath}**/*.tar.gz`, {
 
 process
   .on('uncaughtException', err => {
-    if (err.submitter) {
-      bulkUploaderEmail(err.submitter.email, err.message)
-    }
-    errorDevEmail(err)
-    logger.error('whoops! there was an error', err.stack)
+    logger.error('Uncaught exception', err.stack)
   })
   .on('unhandledRejection', reason => {
     logger.error(`Unhandled Rejection at: ${reason.stack || reason}`)
@@ -56,7 +53,10 @@ watcher
   .on('add', path => processFile(path))
   .on('change', path => logger.debug(`File ${path} has been changed`))
   .on('unlink', path => logger.debug(`File ${path} has been removed`))
-  .on('error', error => logger.error(`Watcher error: ${error}`))
+  .on('error', error => {
+    logger.error(`Watcher error: ${error}`)
+    errorDevEmail(`Watcher error: ${error}`)
+  })
   .on('ready', () =>
     logger.info(
       `Initial scan complete. Ready for changes under folder ${rootPath}`,
@@ -74,7 +74,8 @@ async function processFile(path) {
   try {
     logger.info(`Processing tagged XML packages: ${path}`)
 
-    const user = await getUser.getFTPUser(rootPath, path)
+    const user = await getUser.getTaggerUser()
+    const userId = user.id
     const tmpPath = await tar.createTempDir()
     const extractedFilePath = await tar.untar(path, tmpPath)
     const manifestFilename = await files.getManifestFilename(extractedFilePath)
@@ -82,51 +83,63 @@ async function processFile(path) {
       extractedFilePath,
       manifestFilename,
     )
-    const filesArr = await files.checkFiles(filesData, tmpPath, user)
+    const filesArr = await files.checkFiles(filesData, tmpPath, userId)
 
     // delete current existing 'tagging' files
-    await db.deleteTaggingFiles(manuscriptId, user)
+    await db.deleteTaggingFiles(manuscriptId, userId)
 
     // upload to minio
     for (let i = 0; i < filesArr.length; i += 1) {
       const uuid = uuidv4()
-      const minioFileName = `${uuid}${filesArr[i].extension}`
+      filesArr[i].minioFileName = `${uuid}${filesArr[i].extension}`
       files.uploadFileToMinio(
-        minioFileName,
+        filesArr[i].minioFileName,
         filesArr[i].filename,
         filesArr[i].url,
         filesArr[i].mimeType,
       )
-      filesArr[i].filename = minioFileName
     }
 
     const dbFilesArr = filesArr.map(obj => {
-      obj.url = `/download/${obj.filename}`
+      obj.url = `/download/${obj.minioFileName}`
       delete obj.extension
+      delete obj.minioFileName
       return obj
     })
 
     // create rows in 'file' table
     await db.createTaggersFiles(dbFilesArr)
-    await manuscriptModel.updatePdfDepositState(manuscriptId)
+
+    manuscriptModel.update(
+      { id: manuscriptId, pdfDepositState: 'WAITING_FOR_PDF_CONVERSION' },
+      userId,
+    )
     await files.renameFile(path)
 
-    logger.info('Uploading to Minio and the database has been completed.')
+    // generate HTML and nxml files from xml
+    const xmlFile = dbFilesArr.find(file => file.mimeType === 'application/xml')
+    if (typeof xmlFile !== 'undefined') {
+      await pushXML(xmlFile.url, manuscriptId, userId)
+    }
+    logger.info(
+      'Uploading of taggers files to Minio and the database has been completed.',
+    )
 
-    const manuscriptObj = await manuscriptModel.getManuscriptById(manuscriptId)
+    const manuscriptObj = await manuscriptModel.findById(manuscriptId, userId)
 
     // send email to taggers
     processedTaggerEmail(
       ftpTagger.email,
       manuscriptId,
-      manuscriptObj[0]['meta,title'],
+      manuscriptObj.meta.title,
       `${path}`,
     )
     // clean up tmp folder
     await files.tidyUp(tmpPath)
   } catch (err) {
     logger.error('Error', err.message)
-    bulkUploaderEmail(ftpTagger.email, `${path}`)
+    const filename = path.split('/').pop()
+    bulkUploaderEmail(ftpTagger.email, path, filename)
     files.moveErroneousFile(path, errorFolder)
     logger.error('File has been moved to the Error folder')
   }
diff --git a/server/ftp-integration/toTaggers.js b/server/ftp-integration/toTaggers.js
index f982a465150eab6660e7e8f96ae53368b7801c01..3d74b85c514987dea2196b3443a6f44b92eff325 100755
--- a/server/ftp-integration/toTaggers.js
+++ b/server/ftp-integration/toTaggers.js
@@ -35,25 +35,31 @@ module.exports = app => {
 
 // noinspection JSAnnotator
 async function createPackageForTaggers(manid) {
-  const datedFolder = dateFormat(new Date(), 'yyyy-mm-dd')
-  logger.info(`Sending package ${manid} to tagger FTP location.`)
-  const manuscript = await getManuscript(manid)
-  const tmpPath = await createTempDir(manuscript)
-  await writeFiles(tmpPath, manuscript)
-  await createMetadataXML(tmpPath, manuscript)
-  await createManifest(tmpPath, manuscript)
-  await compress(tmpPath, manuscript, datedFolder)
-
-  taggerEmail(
-    ftpTagger.email,
-    manuscript.id,
-    manuscript['meta,title'],
-    `ftp://${process.env.PUBSWEET_HOST}/New/${datedFolder}/${
-      manuscript.id
-    }.tar.gz`,
-  )
-
-  await tidyUp(tmpPath)
+  try {
+    const datedFolder = dateFormat(new Date(), 'yyyy-mm-dd')
+    logger.info(`Sending package ${manid} to tagger FTP location.`)
+    const manuscript = await getManuscript(manid)
+    const tmpPath = await createTempDir(manuscript)
+    await writeFiles(tmpPath, manuscript)
+    await createMetadataXML(tmpPath, manuscript)
+    await createManifest(tmpPath, manuscript)
+    await compress(tmpPath, manuscript, datedFolder)
+
+    taggerEmail(
+      ftpTagger.email,
+      manuscript.id,
+      manuscript['meta,title'],
+      `ftp://${process.env.PUBSWEET_HOST}/New/${datedFolder}/${
+        manuscript.id
+      }.tar.gz`,
+    )
+
+    await tidyUp(tmpPath)
+  } catch (error) {
+    logger.error('Error', error.message)
+    errorDevEmail(`Error when creating package for manuscript Id: ${manid}
+    Error: ${error}`)
+  }
 }
 
 function getManuscript(manId) {
@@ -300,8 +306,7 @@ function compress(tmpPath, manuscript, datedFolder) {
 
 process
   .on('uncaughtException', err => {
-    errorDevEmail(err)
-    logger.error('whoops! there was an error', err.stack)
+    logger.error('Error', err.stack)
     // tidyUp()
   })
   .on('unhandledRejection', reason => {
diff --git a/server/utils/db.js b/server/utils/db.js
index f8dbaf3e63249efefffd028bc41a63a09c98219b..fb822067c71cdf64f70ece74ef553acf6afdb795 100644
--- a/server/utils/db.js
+++ b/server/utils/db.js
@@ -16,6 +16,7 @@ module.exports.createTaggersFiles = async function createTaggersFiles(
 module.exports.upsertFileUrl = async function upsertFileUrl(
   filesArr,
   manuscriptId,
+  userId,
 ) {
   const existingFiles = await FileModel.selectByManIdConvertedFiles(
     manuscriptId,
@@ -29,7 +30,8 @@ module.exports.upsertFileUrl = async function upsertFileUrl(
       file => file.type === fileTypesArr[i],
     )
     if (existingFile) {
-      const filedb = await FileModel.updateFileUrl(existingFile.id, newFile.url)
+      existingFile.url = newFile.url
+      const filedb = await FileModel.update(existingFile, userId)
       logger.info(filedb)
     } else {
       const filedb = await new FileModel(newFile).save({
@@ -43,12 +45,14 @@ module.exports.upsertFileUrl = async function upsertFileUrl(
 module.exports.upsertHtmlPrevFile = async function upsertHtmlPrevFile(
   newFile,
   manuscriptId,
+  userId,
 ) {
   const existingFiles = await FileModel.selectByManuscriptId(manuscriptId)
 
   const existingFile = existingFiles.find(file => file.type === 'source')
   if (existingFile) {
-    const filedb = await FileModel.updateFileUrl(existingFile.id, newFile.url)
+    existingFile.url = newFile.url
+    const filedb = await FileModel.update(existingFile, userId)
     logger.info(filedb)
   } else {
     const filedb = await new FileModel(newFile).save({
@@ -60,7 +64,7 @@ module.exports.upsertHtmlPrevFile = async function upsertHtmlPrevFile(
 
 module.exports.deleteTaggingFiles = async function deleteTaggingFiles(
   manuscriptId,
-  user,
+  userId,
 ) {
   const manFiles = await FileModel.selectByManuscriptId(manuscriptId)
   const submissionFilesTypes = ['manuscript', 'figure', 'table', 'supplement']
@@ -69,7 +73,7 @@ module.exports.deleteTaggingFiles = async function deleteTaggingFiles(
   )
   // delete tagging files
   for (let i = 0; i < taggingFiles.length; i += 1) {
-    await FileModel.deleteById(taggingFiles[i].id, user.userId)
+    await FileModel.deleteById(taggingFiles[i].id, userId)
   }
   logger.info(`${taggingFiles.length} files deleted.`)
 }
diff --git a/server/utils/files.js b/server/utils/files.js
index 5d67d88274a6cc61f680d92bc6d4d0b8c296cda7..c08fd51585faae47466b2eec16d3cc88fa85a76d 100644
--- a/server/utils/files.js
+++ b/server/utils/files.js
@@ -64,7 +64,7 @@ module.exports.getManifestFileData = function getManifestFileData(
   })
 }
 
-module.exports.checkFiles = function checkFiles(files, tmpPath, user) {
+module.exports.checkFiles = function checkFiles(files, tmpPath, userId) {
   return new Promise((resolve, reject) => {
     const filesArr = []
     for (let i = 0; i < files.length; i += 1) {
@@ -95,7 +95,7 @@ module.exports.checkFiles = function checkFiles(files, tmpPath, user) {
         size: fileSizeInBytes,
         url: file,
         label: fileLabel,
-        updatedBy: user.userId,
+        updatedBy: userId,
       })
     }
     resolve(filesArr)
diff --git a/server/utils/user.js b/server/utils/user.js
index e25e841c9572c3c07db036f75744df741049d4f5..1aab21d736447a67b890f581f9e9827abce522a2 100644
--- a/server/utils/user.js
+++ b/server/utils/user.js
@@ -1,31 +1,12 @@
 const rfr = require('rfr')
-const config = require('config')
 
-const Identity = rfr('server/xpub-model/entities/identity/data-access')
 const User = rfr('server/xpub-model/entities/user/data-access')
-const ftpUsers = config.get('users')
 
-module.exports.getFTPUser = function getFTPUser(rootPath, filename) {
+module.exports.getTaggerUser = function getTaggerUser() {
   return new Promise((resolve, reject) => {
-    const userName = 'taggers'
-
-    Identity.findByFieldEager(
-      'meta',
-      `{"ftpUserName": "${userName}"}`,
-      '[user]',
-    )
-      .then(identityDb => {
-        const user = ftpUsers.find(user =>
-          user.identities
-            .filter(identity => identity.meta)
-            .find(identity => identity.meta.ftpUserName === userName),
-        )
-        const identity = user.identities
-          .filter(identity => identity.meta)
-          .find(identity => identity.meta.ftpUserName === userName)
-        /* eslint-disable dot-notation */
-        identity['userId'] = identityDb[0].userId
-        resolve(identity)
+    User.findByEmail('taggers@internal.ebi.ac.uk')
+      .then(user => {
+        resolve(user)
       })
       .catch(error => reject(error))
   })
diff --git a/server/xml-validation/index.js b/server/xml-validation/index.js
index 52e50f57c837d477fcf4f58d04fbee77c217c4d5..9184821b3a5e3c290204ee6b1c69afcdfef0eb55 100755
--- a/server/xml-validation/index.js
+++ b/server/xml-validation/index.js
@@ -5,11 +5,10 @@ const xslt4node = require('xslt4node')
 const fs = require('fs')
 const uuidv4 = require('uuid/v4')
 const tar = require('../utils/unTar.js')
-const getUser = require('../utils/user.js')
 const files = require('../utils/files.js')
 const db = require('../utils/db.js')
 const logger = require('@pubsweet/logger')
-const Manuscript = require('../xpub-model/entities/manuscript/data-access')
+const Manuscript = require('../xpub-model/entities/manuscript')
 const File = require('../xpub-model/entities/file/data-access')
 const config = require('config')
 
@@ -18,9 +17,9 @@ const { url } = config['epmc-email']
 xslt4node.addLibrary('./saxon9he.jar')
 xslt4node.addOptions('-Xmx1g')
 
-// pushXML(`/download/7742e570-3458-11e9-9868-95e725ed2ade.xml`, 'EMS90000')
+// pushXML(`/download/67551d6c-6ef0-446d-a04b-1d98dbc05915.xml`, 'EMS90000')
 
-module.exports.pushXML = async function pushXML(fileUrl, manuscriptId) {
+module.exports.pushXML = async function pushXML(fileUrl, manuscriptId, userId) {
   try {
     const downloadUrl = url + fileUrl.replace(/^\/+/g, '') // remove leading slash
     const xml = await files.fetchFile(downloadUrl)
@@ -57,7 +56,10 @@ module.exports.pushXML = async function pushXML(fileUrl, manuscriptId) {
           errString += `\n\n`
         }
       })
-      await Manuscript.updateErrorMsg(manuscriptId, errString)
+      Manuscript.update(
+        { id: manuscriptId, formState: errString, status: 'xml-triage' },
+        userId,
+      )
       logger.error(errString)
     } else {
       const nxml = await transformXML(
@@ -80,7 +82,10 @@ module.exports.pushXML = async function pushXML(fileUrl, manuscriptId) {
             errString += `\n\n`
           }
         })
-        await Manuscript.updateErrorMsg(manuscriptId, errString)
+        Manuscript.update(
+          { id: manuscriptId, formState: errString, status: 'xml-triage' },
+          userId,
+        )
         logger.error(errString)
       } else {
         // Check NXML against the stylechecker
@@ -99,7 +104,6 @@ module.exports.pushXML = async function pushXML(fileUrl, manuscriptId) {
 
           const tmpPath = await tar.createTempDir()
           const filesArr = []
-          const user = await getUser.getAdminUser()
 
           // now we will transform the nXML into HTML:
           const html = await transformXML(
@@ -115,10 +119,18 @@ module.exports.pushXML = async function pushXML(fileUrl, manuscriptId) {
           fs.writeFileSync(`${tmpPath}/${manuscriptId}.nxml`, nxml)
 
           filesArr.push(
-            getFileInfo(`${tmpPath}/${manuscriptId}.html`, manuscriptId, user),
+            getFileInfo(
+              `${tmpPath}/${manuscriptId}.html`,
+              manuscriptId,
+              userId,
+            ),
           )
           filesArr.push(
-            getFileInfo(`${tmpPath}/${manuscriptId}.nxml`, manuscriptId, user),
+            getFileInfo(
+              `${tmpPath}/${manuscriptId}.nxml`,
+              manuscriptId,
+              userId,
+            ),
           )
           const uuid = uuidv4()
 
@@ -137,11 +149,19 @@ module.exports.pushXML = async function pushXML(fileUrl, manuscriptId) {
             return obj
           })
 
-          await db.upsertFileUrl(dbFilesArr, manuscriptId)
-          await Manuscript.updatePdfDepositState(manuscriptId)
-          await Manuscript.clearFormState(manuscriptId)
+          await db.upsertFileUrl(dbFilesArr, manuscriptId, userId)
+
+          Manuscript.update(
+            { id: manuscriptId, pdfDepositState: 'WAITING_FOR_PDF_CONVERSION' },
+            userId,
+          )
+
+          Manuscript.update({ id: manuscriptId, formState: null }, userId)
+
           await files.tidyUp(tmpPath)
-          logger.info('Uploading to Minio and the database has been completed.')
+          logger.info(
+            'Uploading of nxml and html files to Minio and the database has been completed.',
+          )
         } else {
           let styleErrString = `Style Errors: <br/><br/>`
           styleErrors.forEach((err, i) => {
@@ -150,18 +170,28 @@ module.exports.pushXML = async function pushXML(fileUrl, manuscriptId) {
               styleErrString += `<br/><br/>`
             }
           })
-          await Manuscript.updateErrorMsg(manuscriptId, styleErrString)
+          Manuscript.update(
+            {
+              id: manuscriptId,
+              formState: styleErrString,
+              status: 'xml-triage',
+            },
+            userId,
+          )
           logger.error(styleErrString)
         }
       }
     }
   } catch (err) {
-    await Manuscript.updateErrorMsg(manuscriptId, err.message)
+    Manuscript.update(
+      { id: manuscriptId, formState: err.message, status: 'xml-triage' },
+      userId,
+    )
     logger.error(err.message)
   }
 }
 
-function getFileInfo(filepath, manuscriptId, user) {
+function getFileInfo(filepath, manuscriptId, userId) {
   const filename = filepath.substring(filepath.lastIndexOf('/') + 1)
   const fileExt = path.extname(filepath)
   const fileSize = fs.statSync(filepath).size
@@ -180,7 +210,7 @@ function getFileInfo(filepath, manuscriptId, user) {
     extension: fileExt,
     mimeType: `${mime.contentType(fileExt)}`,
     manuscriptId,
-    updatedBy: user.id,
+    updatedBy: userId,
   }
   return fileInfo
 }
diff --git a/server/xml-validation/xsl/nxml2html.xsl b/server/xml-validation/xsl/nxml2html.xsl
index bc0f0cc58d7ec9074b596bb17e1a52e748b0d9b4..89f20a397f695e921974586d25349c36d0c0529a 100755
--- a/server/xml-validation/xsl/nxml2html.xsl
+++ b/server/xml-validation/xsl/nxml2html.xsl
@@ -23,7 +23,7 @@
     </xsl:choose>
   </xsl:template>
   
-  <xsl:variable name="emsid" select="substring-after(//article-meta/article-id[@pub-id-type = 'manuscript'], 'ukpmcpa')"/>
+  <xsl:variable name="emsid" select="concat('EMS', substring-after(//article-meta/article-id[@pub-id-type = 'manuscript'], 'ukpmcpa'))"/>
 
   <xsl:template match="/">
     <!--<html>
diff --git a/server/xpub-model/entities/file/data-access.js b/server/xpub-model/entities/file/data-access.js
index 884622172f29f4eaac06089e7b173eb26c12a809..ca35af629f95c5b630db5f25be5f4655b63169fd 100644
--- a/server/xpub-model/entities/file/data-access.js
+++ b/server/xpub-model/entities/file/data-access.js
@@ -87,13 +87,6 @@ class File extends EpmcBaseModel {
     return rows.map(rowToEntity)
   }
 
-  static async updateFileUrl(id, fileurl) {
-    const fileUpdated = File.query()
-      .patch({ url: fileurl })
-      .where('id', id)
-    return fileUpdated
-  }
-
   static async selectAll() {
     const rows = await runQuery(
       buildQuery
diff --git a/server/xpub-model/entities/manuscript/data-access.js b/server/xpub-model/entities/manuscript/data-access.js
index 66b8876331d5cd53522c1235614458d1aa581856..6aabd6641081cdae49bc62ec17e4332332dddd7b 100644
--- a/server/xpub-model/entities/manuscript/data-access.js
+++ b/server/xpub-model/entities/manuscript/data-access.js
@@ -521,27 +521,6 @@ class Manuscript extends EpmcBaseModel {
       .returning('*')
   }
 
-  static async updateErrorMsg(id, errorMsg) {
-    const manuscriptUpdated = await Manuscript.query()
-      .patch({ formState: errorMsg, status: 'xml-triage' })
-      .where('id', id)
-    return manuscriptUpdated
-  }
-
-  static async updatePdfDepositState(id) {
-    const manuscriptUpdated = await Manuscript.query()
-      .patch({ pdfDepositState: 'WAITING_FOR_PDF_CONVERSION' })
-      .where('id', id)
-    return manuscriptUpdated
-  }
-
-  static async clearFormState(id) {
-    const manuscriptUpdated = await Manuscript.query()
-      .patch({ formState: '' })
-      .where('id', id)
-    return manuscriptUpdated
-  }
-
   static async isAdmin(user) {
     const Team = require('../team/')
     const roles = await Team.selectByUserId(user)
diff --git a/server/xpub-model/entities/manuscript/index.js b/server/xpub-model/entities/manuscript/index.js
index e5cf4f7b5fc45ab272415500c3ef769aba6c82df..25eeb10cf007a8f5a52b9b9545aff7c232545691 100755
--- a/server/xpub-model/entities/manuscript/index.js
+++ b/server/xpub-model/entities/manuscript/index.js
@@ -77,14 +77,22 @@ const Manuscript = {
       logger.error(error)
       return {
         manuscript: null,
-        errors: [{ message: `No active manuscript with ID: ${id}` }],
+        errors: [
+          {
+            message: `No active manuscript with ID: ${id}. Please ensure EMSIDs begin with 'EMS' and PMCIDs begin with 'PMC'`,
+          },
+        ],
       }
     }
     return {
       manuscript,
       errors: manuscript
         ? null
-        : [{ message: `No manuscript found with ID: ${id}` }],
+        : [
+            {
+              message: `No manuscript found with ID: ${id}. Please ensure EMSIDs begin with 'EMS' and PMCIDs begin with 'PMC'`,
+            },
+          ],
     }
   },
 
diff --git a/server/xpub-model/entities/team/data-access.js b/server/xpub-model/entities/team/data-access.js
index 939006c22ce3af09827a815e11e423ad9dc26d57..b4be60f968ba75a60499806e0a1bce52774be542 100755
--- a/server/xpub-model/entities/team/data-access.js
+++ b/server/xpub-model/entities/team/data-access.js
@@ -16,8 +16,8 @@ class Team extends EpmcBaseModel {
   // static idColumn = ['article_id', 'member_id'];
 
   static get idColumn() {
-    // return ['manuscript_id', 'user_id', 'role_name']
-    return 'id'
+    return ['manuscript_id', 'user_id', 'role_name']
+    // return 'id'
   }
 
   /*
diff --git a/server/xpub-server/entities/file/resolvers.js b/server/xpub-server/entities/file/resolvers.js
index 3f8502501e29ebf7bc9849045a52ed160b290ecd..373f5512da40ef06cde76bcdcbce8ebce2d824e8 100644
--- a/server/xpub-server/entities/file/resolvers.js
+++ b/server/xpub-server/entities/file/resolvers.js
@@ -42,7 +42,7 @@ const resolvers = {
     async convertXML(_, { id }, { user }) {
       try {
         const xmlFile = await FileManager.find(id)
-        await pushXML(xmlFile.url, xmlFile.manuscriptId)
+        await pushXML(xmlFile.url, xmlFile.manuscriptId, user)
       } catch (error) {
         logger.error(error)
         return false
diff --git a/server/xpub-server/entities/file/uploadFiles.js b/server/xpub-server/entities/file/uploadFiles.js
index f22b1e52408b9c33fa17ea5c116c673f0d2dea81..aae7b20aee050eafbcf0ca1feafd3effa25ad4d2 100644
--- a/server/xpub-server/entities/file/uploadFiles.js
+++ b/server/xpub-server/entities/file/uploadFiles.js
@@ -84,7 +84,6 @@ async function uploadFiles(_, { id, files, type = '' }, { user }) {
       const savedFile = await file.save()
       logger.debug('savedFile: ', savedFile)
       savedFiles.push(savedFile)
-      // xsweetConvert()
     }),
   )
 
diff --git a/server/xsweet-conversion/index.js b/server/xsweet-conversion/index.js
index 38bfed8a71c085de8b4568ab02c1ec8414c7491f..70244cd2adb1b3e4b2ab9db30c19fb4d38091404 100644
--- a/server/xsweet-conversion/index.js
+++ b/server/xsweet-conversion/index.js
@@ -22,6 +22,7 @@ xsweetConvert(
 module.exports.xsweetConvert = async function xsweetConvert(
   fileUrl,
   manuscriptId,
+  userId,
 ) {
   const options = {
     method: 'POST',
@@ -62,7 +63,7 @@ module.exports.xsweetConvert = async function xsweetConvert(
         fileInfo.url = `/download/${uuid}${fileInfo.extension}`
         delete fileInfo.extension
 
-        await db.upsertHtmlPrevFile(fileInfo, manuscriptId)
+        await db.upsertHtmlPrevFile(fileInfo, manuscriptId, userId)
         logger.info('HTML converted file has been uploaded to Minio and to db')
       } catch (err) {
         throw err