diff --git a/packages/component-manuscript/src/components/Authors.js b/packages/component-manuscript/src/components/Authors.js
index dc07b1adc938e8f8d71ca3f49a6bf55f70ee4c83..bd8462bca91a3e0ddb2c56e7c5b72ec5c84bbeb7 100644
--- a/packages/component-manuscript/src/components/Authors.js
+++ b/packages/component-manuscript/src/components/Authors.js
@@ -17,7 +17,7 @@ const TR = ({
       {isSubmitting && <AuthorStatus>SA</AuthorStatus>}
       {isCorresponding && !isSubmitting && <AuthorStatus>CA</AuthorStatus>}
     </td>
-    <td>{email || 'N/A'}</td>
+    <td>{email || ''}</td>
     <td>{affiliation}</td>
   </Row>
 )
@@ -27,7 +27,7 @@ const Authors = ({ authors }) => (
     <thead>
       <tr>
         <td colSpan="2">Full Name</td>
-        <td>Email</td>
+        <td>{authors[0].email ? 'Email' : ''}</td>
         <td>Affiliation</td>
       </tr>
     </thead>
diff --git a/packages/component-manuscript/src/components/ReviewerReportForm.js b/packages/component-manuscript/src/components/ReviewerReportForm.js
new file mode 100644
index 0000000000000000000000000000000000000000..2a62ea58832a86e892f27406b822f32aeb43d7eb
--- /dev/null
+++ b/packages/component-manuscript/src/components/ReviewerReportForm.js
@@ -0,0 +1,280 @@
+import React, { Fragment } from 'react'
+import { connect } from 'react-redux'
+import { required } from 'xpub-validators'
+import styled, { css } from 'styled-components'
+import { compose, withHandlers, withProps } from 'recompose'
+import { th, Menu, ValidatedField, Icon, Button, Spinner } from '@pubsweet/ui'
+import {
+  reduxForm,
+  isSubmitting,
+  change as changeForm,
+  getFormValues,
+} from 'redux-form'
+import AutosaveIndicator from 'pubsweet-component-wizard/src/components/AutosaveIndicator'
+import {
+  autosaveRequest,
+  autosaveSuccess,
+} from 'pubsweet-component-wizard/src/redux/autosave'
+
+import { parseReviewResponseToForm, parseReviewRequest } from './utils'
+
+const guidelinesLink =
+  'https://about.hindawi.com/authors/peer-review-at-hindawi/'
+const options = [
+  {
+    value: 'publish',
+    label: 'Publish unaltered',
+  },
+  {
+    value: 'major',
+    label: 'Consider after major revision',
+  },
+  {
+    value: 'minor',
+    label: 'Consider after major revision',
+  },
+  {
+    value: 'reject',
+    label: 'Reject',
+  },
+]
+
+const review = {
+  id: 'revuewiuuuid',
+  userId: 'uuuuuuid',
+  recommendation: 'publish',
+  recommendationType: 'review',
+  comments: [
+    {
+      content: 'Here is public text',
+      public: true,
+      files: [],
+    },
+    {
+      content: 'Here is PRIVATE text',
+      public: false,
+      files: [],
+    },
+  ],
+}
+
+const ReviewerReportForm = ({
+  isSubmitting,
+  changeField,
+  handleSubmit,
+  formValues = {},
+  initialValues,
+}) => (
+  <Root>
+    <Row>
+      <Label>Recommendation*</Label>
+      <ActionLink href={guidelinesLink} target="_blank">
+        Hindawi Reviewer Guidelines
+      </ActionLink>
+    </Row>
+    <Row>
+      <ValidatedField
+        component={input => (
+          <Menu
+            {...input}
+            inline
+            onChange={v => changeField('recommendation', v)}
+            options={options}
+            placeholder="Select"
+          />
+        )}
+        name="recommendation"
+        validate={[required]}
+      />
+    </Row>
+    <Spacing />
+    <Row>
+      <Label>
+        Report <ActionText left={12}>Upload file</ActionText>
+      </Label>
+    </Row>
+    <Row>
+      <FullWidth>
+        <ValidatedField
+          component={input => (
+            <Textarea
+              {...input}
+              hasError={input.validationStatus === 'error'}
+              onChange={e => changeField('public', e.target.value)}
+              rows={6}
+            />
+          )}
+          name="public"
+          validate={[required]}
+        />
+      </FullWidth>
+    </Row>
+    {formValues.hasConfidential ? (
+      <Fragment>
+        <Row>
+          <Label>
+            Note for the editorial team <i>Not shared with the author</i>
+          </Label>
+          <ActionTextIcon onClick={() => changeField('hasConfidential', false)}>
+            <Icon primary size={3}>
+              x
+            </Icon>
+            Remove
+          </ActionTextIcon>
+        </Row>
+        <Row>
+          <FullWidth>
+            <ValidatedField
+              component={input => (
+                <Textarea
+                  {...input}
+                  hasError={input.validationStatus === 'error'}
+                  onChange={e => changeField('confidential', e.target.value)}
+                  rows={6}
+                />
+              )}
+              name="confidential"
+              validate={[required]}
+            />
+          </FullWidth>
+        </Row>
+      </Fragment>
+    ) : (
+      <Row>
+        <ActionText onClick={() => changeField('hasConfidential', true)}>
+          Add confidential note for the Editorial Team
+        </ActionText>
+      </Row>
+    )}
+
+    <Spacing />
+    <Row>
+      {isSubmitting ? (
+        <Spinner size={4} />
+      ) : (
+        <ActionButton onClick={handleSubmit}> Submit report </ActionButton>
+      )}
+      <AutosaveIndicator formName="reviewerReport" />
+    </Row>
+  </Root>
+)
+
+// To be removed
+const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
+
+export default compose(
+  connect(
+    state => ({
+      formValues: getFormValues('reviewerReport')(state),
+      isSubmitting: isSubmitting('reviewerReport')(state),
+    }),
+    { changeForm, getFormValues },
+  ),
+  withProps(() => ({
+    initialValues: parseReviewResponseToForm({}),
+  })),
+  withHandlers({
+    changeField: ({ changeForm }) => (field, value) => {
+      changeForm('reviewerReport', field, value)
+    },
+  }),
+  reduxForm({
+    form: 'reviewerReport',
+    enableReinitialize: true,
+    forceUnregisterOnUnmount: true,
+    onChange: (values, dispatch) => {
+      dispatch(autosaveRequest())
+      sleep(1000).then(() => dispatch(autosaveSuccess(new Date())))
+    },
+    onSubmit: (values, dispatch, { isSubmitting }) =>
+      sleep(1000).then(() => {
+        // TODO: link to backend
+        const review = parseReviewRequest(values)
+        window.alert(`You submitted:\n\n${JSON.stringify(review, null, 2)}`)
+      }),
+  }),
+)(ReviewerReportForm)
+
+// #region styled-components
+
+const defaultText = css`
+  color: ${th('colorPrimary')};
+  font-family: ${th('fontReading')};
+  font-size: ${th('fontSizeBaseSmall')};
+`
+const Root = styled.div`
+  display: flex;
+  flex-direction: column;
+  margin: auto;
+  [role='listbox'] {
+    min-width: 280px;
+  }
+`
+
+const Label = styled.div`
+  ${defaultText};
+  text-transform: uppercase;
+  i {
+    text-transform: none;
+    margin-left: ${th('gridUnit')};
+  }
+`
+
+const ActionText = styled.span`
+  ${defaultText};
+  text-decoration: underline;
+  cursor: pointer;
+  margin-left: ${({ left }) => left || 0}px;
+`
+
+const ActionTextIcon = styled(ActionText)`
+  display: flex;
+  align-items: center;
+`
+const ActionLink = styled.a`
+  ${defaultText};
+`
+
+const Textarea = styled.textarea`
+  width: 100%;
+  padding: calc(${th('subGridUnit')}*2);
+  font-size: ${th('fontSizeBaseSmall')};
+  font-family: ${th('fontWriting')};
+  border-color: ${({ hasError }) =>
+    hasError ? th('colorError') : th('colorPrimary')};
+`
+
+const Spacing = styled.div`
+  margin-top: ${th('gridUnit')};
+  flex: 1;
+`
+
+const FullWidth = styled.div`
+  flex: 1;
+  > div {
+    flex: 1;
+  }
+`
+
+const Row = styled.div`
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  flex: 1;
+  box-sizing: border-box;
+  flex-wrap: wrap;
+  justify-content: space-between;
+`
+
+const ActionButton = styled(Button)`
+  ${defaultText};
+  align-items: center;
+  background-color: ${th('colorPrimary')};
+  color: ${th('colorTextReverse')};
+  display: flex;
+  padding: 4px 8px;
+  text-align: center;
+  height: calc(${th('subGridUnit')}*5);
+  text-transform: uppercase;
+`
+// #endregion
diff --git a/packages/component-manuscript/src/components/ReviewsAndReports.js b/packages/component-manuscript/src/components/ReviewsAndReports.js
index 6a8ead1f0fea8fa9f44965e425a3c6fe340e497b..15fa55f80fddbe236e0cb42015ff8e73145f2d3c 100644
--- a/packages/component-manuscript/src/components/ReviewsAndReports.js
+++ b/packages/component-manuscript/src/components/ReviewsAndReports.js
@@ -5,6 +5,7 @@ import styled from 'styled-components'
 import { compose, withHandlers, lifecycle } from 'recompose'
 import { ReviewerBreakdown } from 'pubsweet-components-faraday/src/components/Invitations'
 import ReviewersDetailsList from 'pubsweet-components-faraday/src/components/Reviewers/ReviewersDetailsList'
+import ReviewerReportForm from 'pubsweet-component-manuscript/src/components/ReviewerReportForm'
 import {
   selectReviewers,
   selectFetchingReviewers,
@@ -54,9 +55,9 @@ const ReviewsAndReports = ({
       </Root>
     )}
     {isReviewer && (
-      <Root>
+      <Root id="review-report">
         <Expandable label="Your Report" startExpanded>
-          <div>Form here, to be implemented</div>
+          <ReviewerReportForm />
         </Expandable>
       </Root>
     )}
diff --git a/packages/component-manuscript/src/components/utils.js b/packages/component-manuscript/src/components/utils.js
index 0fb7764d1db83459daa972501fdd4b3bc1afe763..17ad97ee832b37c0a6daa0b3a85c45b7be7e4d2b 100644
--- a/packages/component-manuscript/src/components/utils.js
+++ b/packages/component-manuscript/src/components/utils.js
@@ -1,5 +1,5 @@
 import moment from 'moment'
-import { get, find, capitalize } from 'lodash'
+import { get, find, capitalize, omit } from 'lodash'
 
 export const parseTitle = version => {
   const title = get(version, 'metadata.title')
@@ -80,3 +80,38 @@ export const redirectToError = redirectFn => err => {
     redirectFn('/error-page', 'Oops! Something went wrong.')
   }
 }
+
+export const parseReviewResponseToForm = (review = {}) => {
+  const comments = review.comments || []
+  const publicComment = comments.find(c => c.public)
+  const privateComment = comments.find(c => !c.public)
+  return {
+    ...review,
+    public: get(publicComment, 'content'),
+    files: get(publicComment, 'files'),
+    confidential: get(privateComment, 'content'),
+    hasConfidential: !!get(privateComment, 'content'),
+  }
+}
+
+export const parseReviewRequest = (review = {}) => {
+  const comments = [
+    {
+      public: true,
+      content: review.public,
+      files: review.files || [],
+    },
+  ]
+
+  if (review.hasConfidential) {
+    comments.push({
+      public: false,
+      content: review.confidential,
+      files: [],
+    })
+  }
+  return {
+    ...omit(review, ['public', 'confidential', 'hasConfidential', 'files']),
+    comments,
+  }
+}
diff --git a/packages/component-wizard/src/redux/autosave.js b/packages/component-wizard/src/redux/autosave.js
index a9a8bb816c086884dd7031aeb99dcd6a041e8392..e6db38ebc19e5a9c3799524faf72824bde2e4088 100644
--- a/packages/component-wizard/src/redux/autosave.js
+++ b/packages/component-wizard/src/redux/autosave.js
@@ -43,7 +43,7 @@ export default (state = initialState, action) => {
     case 'UPDATE_FRAGMENT_SUCCESS':
       return {
         ...initialState,
-        lastUpdate: action.receivedAt,
+        lastUpdate: action.receivedAt || action.lastUpdate,
       }
     default:
       return state
diff --git a/packages/component-wizard/src/redux/conversion.js b/packages/component-wizard/src/redux/conversion.js
index becacf4146503472797087aa17aafebd4efdf257..a4043ca5dd365aadc19f2f7a9e7908e89a592c6a 100644
--- a/packages/component-wizard/src/redux/conversion.js
+++ b/packages/component-wizard/src/redux/conversion.js
@@ -58,6 +58,9 @@ export const createDraftSubmission = history => (dispatch, getState) => {
         version: 1,
       }),
     ).then(({ fragment }) => {
+      if (!fragment.id) {
+        throw new Error('Failed to create a project')
+      }
       const route = `/projects/${collection.id}/versions/${fragment.id}/submit`
       if (!currentUser.admin) {
         addSubmittingAuthor(currentUser, collection.id)
diff --git a/packages/components-faraday/src/redux/index.js b/packages/components-faraday/src/redux/index.js
index ddaa6385d75eba8dbcc2f2abfe25f757f6021591..12a9544f097bb4a8b08317dad23152255879d3fe 100644
--- a/packages/components-faraday/src/redux/index.js
+++ b/packages/components-faraday/src/redux/index.js
@@ -2,3 +2,4 @@ export { default as authors } from './authors'
 export { default as editors } from './editors'
 export { default as files } from './files'
 export { default as reviewers } from './reviewers'
+export { default as recommendations } from './recommendations'
diff --git a/packages/components-faraday/src/redux/recommendations.js b/packages/components-faraday/src/redux/recommendations.js
new file mode 100644
index 0000000000000000000000000000000000000000..3a8cf0213622cf40184dc55569490d94aa865abd
--- /dev/null
+++ b/packages/components-faraday/src/redux/recommendations.js
@@ -0,0 +1,88 @@
+import {
+  get as apiGet,
+  create,
+  remove,
+  update,
+} from 'pubsweet-client/src/helpers/api'
+
+const REQUEST = 'recommendations/REQUEST'
+const ERROR = 'recommendations/ERROR'
+
+const GET_RECOMMENDATIONS_SUCCESS = 'recommendations/GET_SUCCESS'
+const GET_RECOMMENDATION_SUCCESS = 'recommendations/GET_ITEM_SUCCESS'
+const UPDATE_RECOMMENDATION_SUCCESS = 'recommendations/UPDATE_SUCCESS'
+
+export const recommendationsRequest = () => ({
+  type: REQUEST,
+})
+
+export const recommendationsError = error => ({
+  type: ERROR,
+  error,
+})
+
+export const getRecommendationsSuccess = recommendations => ({
+  type: GET_RECOMMENDATIONS_SUCCESS,
+  payload: { recommendations },
+})
+
+export const getRecommendationSuccess = recommendation => ({
+  type: GET_RECOMMENDATION_SUCCESS,
+  payload: { recommendation },
+})
+
+export const updateRecommendationSuccess = recommendation => ({
+  type: UPDATE_RECOMMENDATION_SUCCESS,
+  payload: { recommendation },
+})
+
+// Actions
+
+// State
+const initialState = {
+  fetching: false,
+  error: null,
+  recommendations: [],
+  recommendation: {},
+}
+
+export default (state = initialState, action = {}) => {
+  switch (action.type) {
+    case REQUEST:
+      return {
+        ...state,
+        fetching: true,
+        recommendations: [],
+        recommendation: {},
+      }
+    case ERROR:
+      return {
+        ...state,
+        fetching: false,
+        error: action.error,
+      }
+    case GET_RECOMMENDATIONS_SUCCESS:
+      return {
+        ...state,
+        fetching: false,
+        error: null,
+        recommendations: action.payload.recommendations,
+      }
+    case GET_RECOMMENDATION_SUCCESS:
+      return {
+        ...state,
+        fetching: false,
+        error: null,
+        recommendation: action.payload.recommendation,
+      }
+    case UPDATE_RECOMMENDATION_SUCCESS:
+      return {
+        ...state,
+        fetching: false,
+        error: null,
+        recommendation: action.payload.recommendation,
+      }
+    default:
+      return state
+  }
+}