diff --git a/packages/component-faraday-ui/src/ReviewersTable.js b/packages/component-faraday-ui/src/ReviewersTable.js
index e031cddbe5662310219b6f21d8ee3e8b6781271b..74ddafc17049e76ed80fcc5b799f1f9091c1bec9 100644
--- a/packages/component-faraday-ui/src/ReviewersTable.js
+++ b/packages/component-faraday-ui/src/ReviewersTable.js
@@ -1,14 +1,16 @@
 import React, { Fragment } from 'react'
-import { get } from 'lodash'
 import styled from 'styled-components'
-import { shouldUpdate } from 'recompose'
 import { th } from '@pubsweet/ui-toolkit'
 import { DateParser } from '@pubsweet/ui'
+import { get, isEqual, orderBy } from 'lodash'
+import { compose, shouldUpdate, withHandlers, withProps } from 'recompose'
 
 import { Label, PersonInvitation, Text } from '../'
 
 const ReviewersTable = ({
   invitations,
+  getInvitationStatus,
+  renderAcceptedLabel,
   onResendReviewerInvite,
   onRevokeReviewerInvite,
 }) =>
@@ -40,7 +42,9 @@ const ReviewersTable = ({
                 'person.lastName',
               )}`}</Text>
               {invitation.isAccepted && (
-                <Text customId ml={1}>{`Reviewer ${index + 1}`}</Text>
+                <Text customId ml={1}>
+                  {renderAcceptedLabel(index)}
+                </Text>
               )}
             </td>
             <td>
@@ -49,23 +53,19 @@ const ReviewersTable = ({
               </DateParser>
             </td>
             <td>
-              {invitation.respondedOn && (
-                <Fragment>
+              <Fragment>
+                {invitation.respondedOn && (
                   <DateParser timestamp={invitation.respondedOn}>
                     {timestamp => <Text>{timestamp}</Text>}
                   </DateParser>
-                  <Text ml={1} secondary>
-                    ACCEPTED
-                  </Text>
-                </Fragment>
-              )}
+                )}
+                <Text ml={invitation.respondedOn ? 1 : 0} secondary>
+                  {getInvitationStatus(invitation)}
+                </Text>
+              </Fragment>
             </td>
             <td>
-              {invitation.respondedOn && (
-                <DateParser timestamp={invitation.respondedOn}>
-                  {timestamp => <Text>{timestamp}</Text>}
-                </DateParser>
-              )}
+              <div />
             </td>
             <HiddenCell>
               {!invitation.hasAnswer && (
@@ -82,7 +82,33 @@ const ReviewersTable = ({
     </Table>
   )
 
-export default shouldUpdate(() => false)(ReviewersTable)
+const orderInvitations = i => {
+  if (!i.hasAnswer) return -1
+  if (i.isAccepted) return 0
+  return 1
+}
+
+export default compose(
+  shouldUpdate(
+    ({ invitations }, { invitations: nextInvitations }) =>
+      !isEqual(invitations, nextInvitations),
+  ),
+  withProps(({ invitations = [] }) => ({
+    invitations: orderBy(invitations, orderInvitations),
+  })),
+  withProps(({ invitations = [] }) => ({
+    firstAccepted: invitations.findIndex(i => i.hasAnswer && i.isAccepted),
+  })),
+  withHandlers({
+    renderAcceptedLabel: ({ firstAccepted, invitations }) => index =>
+      `Reviewer ${index - firstAccepted + 1}`,
+    getInvitationStatus: () => ({ hasAnswer, isAccepted }) => {
+      if (!hasAnswer) return 'PENDING'
+      if (isAccepted) return 'ACCEPTED'
+      return 'DECLINED'
+    },
+  }),
+)(ReviewersTable)
 
 // #region styles
 const Table = styled.table`
diff --git a/packages/components-faraday/src/components/SignUp/ReviewerDecline.js b/packages/components-faraday/src/components/SignUp/ReviewerDecline.js
index 0b8522d14a13737583a2d80f650ec4fa35179dcd..65a3a8ed8f901048e7deb715b318115c42395ba1 100644
--- a/packages/components-faraday/src/components/SignUp/ReviewerDecline.js
+++ b/packages/components-faraday/src/components/SignUp/ReviewerDecline.js
@@ -1,68 +1,52 @@
 import React from 'react'
-import { connect } from 'react-redux'
-import styled from 'styled-components'
-import { th } from '@pubsweet/ui-toolkit'
+import { get } from 'lodash'
 import { withJournal } from 'xpub-journal'
-import { replace } from 'react-router-redux'
 import { compose, lifecycle } from 'recompose'
+import { H2 } from '@pubsweet/ui'
+import {
+  Row,
+  Text,
+  ActionLink,
+  ShadowedBox,
+} from 'pubsweet-component-faraday-ui'
 
 import { redirectToError } from '../utils'
-import { FormItems } from '../UIComponents'
 import { reviewerDecline } from '../../redux/reviewers'
 
-const { RootContainer, Title } = FormItems
+const ReviewerDecline = ({ journal }) => (
+  <ShadowedBox center mt={2} width={60}>
+    <H2>Thank you for letting us know</H2>
 
-const ReviewerDecline = ({ journal: { metadata: { email } } }) => (
-  <RootContainer bordered>
-    <Title>Thank you for letting us know.</Title>
-    <div>
-      <Description>
+    <Row mt={2}>
+      <Text align="center">
         We hope you will review for Hindawi in the future. If you want any more
         information, or would like to submit a review for this article, then
         please contact us at{' '}
-        <MailLink href={`mailto:${email}`} target="_blank">
-          {email}
-        </MailLink>.
-      </Description>
-    </div>
-  </RootContainer>
+        <ActionLink to={`mailto:${get(journal, 'metadata.email')}`}>
+          {get(journal, 'metadata.email')}
+        </ActionLink>.
+      </Text>
+    </Row>
+  </ShadowedBox>
 )
 
 export default compose(
   withJournal,
-  connect(null, { reviewerDecline, replace }),
   lifecycle({
     componentDidMount() {
       const {
+        history,
+        fragmentId,
         collectionId,
         invitationId,
         invitationToken,
-        reviewerDecline,
-        replace,
-        fragmentId,
       } = this.props
-      reviewerDecline(
+      reviewerDecline({
+        fragmentId,
         invitationId,
         collectionId,
-        fragmentId,
         invitationToken,
-      ).catch(redirectToError(replace))
+      }).catch(redirectToError(history.replace))
     },
   }),
 )(ReviewerDecline)
-
-// #region styled-components
-const MailLink = styled.a`
-  color: ${th('colorPrimary')};
-
-  &:visited {
-    color: ${th('colorTextPlaceholder')};
-  }
-`
-
-const Description = styled.span`
-  color: ${th('colorPrimary')};
-  font-family: ${th('fontReading')};
-  font-size: ${th('fontSizeBaseSmall')};
-`
-// #endregion
diff --git a/packages/components-faraday/src/components/SignUp/ReviewerInviteDecision.js b/packages/components-faraday/src/components/SignUp/ReviewerInviteDecision.js
index c0d72b3e10d5ecaa808b74f1dfe17456a1ebff68..7a6fa96c4718a6dcb087ab8217bbcb9125d81d8e 100644
--- a/packages/components-faraday/src/components/SignUp/ReviewerInviteDecision.js
+++ b/packages/components-faraday/src/components/SignUp/ReviewerInviteDecision.js
@@ -1,140 +1,157 @@
 import React from 'react'
-import { get } from 'lodash'
 import { connect } from 'react-redux'
-import { push, replace } from 'react-router-redux'
+import { reduxForm } from 'redux-form'
 import { required, minChars } from 'xpub-validators'
-import { reduxForm, SubmissionError } from 'redux-form'
 import { compose, withState, lifecycle } from 'recompose'
 import { loginUser } from 'pubsweet-component-login/actions'
-import { Button, ValidatedField, TextField } from '@pubsweet/ui'
-
-import { redirectToError } from '../utils'
-import { FormItems } from '../UIComponents'
-import { reviewerDecision, setReviewerPassword } from '../../redux/reviewers'
-
-const {
+import { Button, ValidatedField, H2, TextField, Spinner } from '@pubsweet/ui'
+import {
   Row,
-  Err,
-  Title,
+  Item,
+  Text,
   Label,
-  Email,
-  RowItem,
-  Subtitle,
-  RootContainer,
-  FormContainer,
-} = FormItems
+  ShadowedBox,
+  withFetching,
+} from 'pubsweet-component-faraday-ui'
+
+import { redirectToError, passwordValidator } from '../utils'
+import { reviewerDecision, setReviewerPassword } from '../../redux/reviewers'
 
 const agreeText = `You have been invited to review a manuscript on the Hindawi platform. Please set a password and proceed to the manuscript.`
 const declineText = `You have decline to work on a manuscript.`
 
 const PasswordField = input => <TextField {...input} type="password" />
 const min8Chars = minChars(8)
+
 const ReviewerInviteDecision = ({
   agree,
   error,
+  isFetching,
   handleSubmit,
   errorMessage,
   reviewerEmail,
+  fetchingError,
 }) => (
-  <RootContainer bordered>
-    <Title>Reviewer Invitation</Title>
-    <Subtitle>{agree === 'true' ? agreeText : declineText}</Subtitle>
-    <Email>{reviewerEmail}</Email>
-    {agree === 'true' && (
-      <FormContainer onSubmit={handleSubmit}>
-        <Row>
-          <RowItem vertical>
-            <Label> Password </Label>
-            <ValidatedField
-              component={PasswordField}
-              name="password"
-              validate={[required, min8Chars]}
-            />
-          </RowItem>
-        </Row>
-        {error && (
-          <Row>
-            <RowItem>
-              <Err>Token expired or Something went wrong.</Err>
-            </RowItem>
-          </Row>
-        )}
-        <Row>
-          <Button primary type="submit">
-            CONFIRM
-          </Button>
-        </Row>
-      </FormContainer>
+  <ShadowedBox center mt={2} width={60}>
+    <H2>Reviewer Invitation</H2>
+    <Text align="center" secondary>
+      {reviewerEmail}
+    </Text>
+
+    <Row mt={2}>
+      <Text align="center">{agree === 'true' ? agreeText : declineText}</Text>
+    </Row>
+
+    <Row mt={2}>
+      <Item vertical>
+        <Label required>Password</Label>
+        <ValidatedField
+          component={PasswordField}
+          name="password"
+          validate={[required, min8Chars]}
+        />
+      </Item>
+    </Row>
+
+    <Row mt={2}>
+      <Item vertical>
+        <Label required>Confirm password</Label>
+        <ValidatedField
+          component={PasswordField}
+          name="confirmPassword"
+          validate={[required]}
+        />
+      </Item>
+    </Row>
+
+    {fetchingError && (
+      <Row mt={2}>
+        <Text align="center" error>
+          {fetchingError}
+        </Text>
+      </Row>
     )}
-  </RootContainer>
+
+    <Row mt={2}>
+      {isFetching ? (
+        <Spinner />
+      ) : (
+        <Button onClick={handleSubmit} primary size="medium">
+          CONFIRM
+        </Button>
+      )}
+    </Row>
+  </ShadowedBox>
 )
 
 export default compose(
+  withFetching,
   withState('reviewerEmail', 'setEmail', ''),
   connect(null, {
-    push,
-    replace,
     loginUser,
-    reviewerDecision,
-    setReviewerPassword,
   }),
   lifecycle({
     componentDidMount() {
       const {
         agree,
         email,
-        replace,
+        history,
         setEmail,
         fragmentId,
         collectionId,
         invitationId,
-        reviewerDecision,
       } = this.props
       setEmail(email)
 
       if (agree === 'false') {
-        reviewerDecision(invitationId, collectionId, fragmentId, false).catch(
-          redirectToError(replace),
-        )
+        reviewerDecision({
+          fragmentId,
+          agree: false,
+          collectionId,
+          invitationId,
+        }).catch(redirectToError(history.replace))
       }
     },
   }),
   reduxForm({
     form: 'invite-reviewer',
+    validate: passwordValidator,
     onSubmit: (
       { password },
       dispatch,
       {
-        push,
         email,
         token,
-        location,
+        setError,
         loginUser,
         fragmentId,
+        setFetching,
         collectionId,
         invitationId,
-        setReviewerPassword,
       },
-    ) =>
+    ) => {
+      setFetching(true)
+      setError('')
       setReviewerPassword({
         email,
         token,
         password,
       })
         .then(() => {
+          setError('')
+          setFetching(false)
           loginUser(
-            { username: email, password },
+            {
+              username: email,
+              password,
+            },
             `/projects/${collectionId}/versions/${fragmentId}/details?agree=${true}&invitationId=${invitationId}`,
           )
         })
-        .catch(error => {
-          const err = get(error, 'response')
-          if (err) {
-            const errorMessage = get(JSON.parse(err), 'error')
-            throw new SubmissionError({
-              _error: errorMessage || 'Something went wrong',
-            })
-          }
-        }),
+        .catch(() => {
+          setFetching(false)
+          setError('Something went wrong...')
+        })
+    },
   }),
 )(ReviewerInviteDecision)
diff --git a/packages/components-faraday/src/components/UIComponents/ErrorPage.js b/packages/components-faraday/src/components/UIComponents/ErrorPage.js
index fe9ffab27d2aca61eac794b502ec4b1ed68bfb74..ca1052e09a82b2a4f923a7b688f77bfcac8dd841 100644
--- a/packages/components-faraday/src/components/UIComponents/ErrorPage.js
+++ b/packages/components-faraday/src/components/UIComponents/ErrorPage.js
@@ -1,35 +1,21 @@
 import React from 'react'
-import { Button } from '@pubsweet/ui'
-import styled from 'styled-components'
-import { th } from '@pubsweet/ui-toolkit'
+import { Button, H2 } from '@pubsweet/ui'
+import { Row, ShadowedBox, Text } from 'pubsweet-component-faraday-ui'
 
 const ErrorPage = ({ location: { state }, history }) => (
-  <Root>
-    <Title>{state}</Title>
-    <Button onClick={() => history.push('/')} primary>
-      Go to Dashboard
-    </Button>
-  </Root>
-)
-
-export default ErrorPage
+  <ShadowedBox center mt={2} width={60}>
+    <H2>Error</H2>
 
-// #region styles
-const Root = styled.div`
-  color: ${th('colorText')};
-  margin: 0 auto;
-  text-align: center;
-  width: 70vw;
+    <Row mt={2}>
+      <Text align="center">{state}</Text>
+    </Row>
 
-  a {
-    color: ${th('colorText')};
-  }
-`
+    <Row mt={2}>
+      <Button onClick={() => history.push('/')} primary>
+        Go to Dashboard
+      </Button>
+    </Row>
+  </ShadowedBox>
+)
 
-const Title = styled.div`
-  color: ${th('colorPrimary')};
-  font-size: ${th('fontSizeHeading5')};
-  font-family: ${th('fontHeading')};
-  margin: calc(${th('subGridUnit')} * 2) auto;
-`
-// #endregion
+export default ErrorPage
diff --git a/packages/components-faraday/src/index.js b/packages/components-faraday/src/index.js
index db4b6cd565c1db6e4afba19f44272d8200786c50..f2e244a4264d4b2de2337305c35fc60ce134aaa7 100644
--- a/packages/components-faraday/src/index.js
+++ b/packages/components-faraday/src/index.js
@@ -5,7 +5,6 @@ module.exports = {
       authors: () => require('./redux/authors').default,
       customError: () => require('./redux/errors').default,
       files: () => require('./redux/files').default,
-      reviewers: () => require('./redux/reviewers').default,
       technicalCheck: () => require('./redux/technicalCheck').default,
     },
   },
diff --git a/packages/components-faraday/src/redux/reviewers.js b/packages/components-faraday/src/redux/reviewers.js
index fdafed5c33010c2e569e9efc7bb830f8e9139300..7542b980da4cdb1aaab21256f0b85bca2cabfb3d 100644
--- a/packages/components-faraday/src/redux/reviewers.js
+++ b/packages/components-faraday/src/redux/reviewers.js
@@ -1,48 +1,13 @@
-import { get, orderBy } from 'lodash'
+import { get } from 'lodash'
 import { selectCurrentUser } from 'xpub-selectors'
 import {
-  get as apiGet,
   create,
   remove,
   update,
+  get as apiGet,
 } from 'pubsweet-client/src/helpers/api'
-import { orderReviewers } from './utils'
-
-const GET_REVIEWERS_REQUEST = 'GET_REVIEWERS_REQUEST'
-const GET_REVIEWERS_ERROR = 'GET_REVIEWERS_ERROR'
-const GET_REVIEWERS_SUCCESS = 'GET_REVIEWERS_SUCCESS'
-
-export const getReviewersRequest = () => ({
-  type: GET_REVIEWERS_REQUEST,
-})
-
-export const getReviewersError = error => ({
-  type: GET_REVIEWERS_ERROR,
-  error,
-})
-
-export const getReviewersSuccess = reviewers => ({
-  type: GET_REVIEWERS_SUCCESS,
-  payload: { reviewers },
-})
-
-// reviewer invite constants and action creators
-const INVITE_REVIEWER_REQUEST = 'INVITE_REVIEWER_REQUEST'
-const INVITE_REVIEWER_SUCCESS = 'INVITE_REVIEWER_SUCCESS'
-const INVITE_REVIEWER_ERROR = 'INVITE_REVIEWER_ERROR'
 
 // reviewer decision constants and action creators
-const REVIEWER_DECISION_REQUEST = 'REVIEWER_DECISION_REQUEST'
-const REVIEWER_DECISION_ERROR = 'REVIEWER_DECISION_ERROR'
-const REVIEWER_DECISION_SUCCESS = 'REVIEWER_DECISION_SUCCESS'
-
-const reviewerDecisionRequest = () => ({ type: REVIEWER_DECISION_REQUEST })
-const reviewerDecisionError = error => ({
-  type: REVIEWER_DECISION_ERROR,
-  error,
-})
-const reviewerDecisionSuccess = () => ({ type: REVIEWER_DECISION_SUCCESS })
-
 const initialState = {
   fetching: {
     decision: false,
@@ -88,21 +53,10 @@ export const currentUserIsReviewer = (state, fragmentId) => {
   )
 }
 
-export const getCollectionReviewers = (
-  collectionId,
-  fragmentId,
-) => dispatch => {
-  dispatch(getReviewersRequest())
-  return apiGet(
+export const getCollectionReviewers = (collectionId, fragmentId) => dispatch =>
+  apiGet(
     `/collections/${collectionId}/fragments/${fragmentId}/invitations?role=reviewer`,
-  ).then(
-    r => dispatch(getReviewersSuccess(orderBy(r, orderReviewers))),
-    err => {
-      dispatch(getReviewersError(err))
-      throw err
-    },
   )
-}
 // #endregion
 
 export const inviteReviewer = ({ reviewerData, collectionId, fragmentId }) =>
@@ -112,13 +66,8 @@ export const inviteReviewer = ({ reviewerData, collectionId, fragmentId }) =>
   })
 
 // #region Actions - invitations
-export const setReviewerPassword = reviewerBody => dispatch => {
-  dispatch(reviewerDecisionRequest())
-  return create(`/users/reset-password`, reviewerBody).then(r => {
-    dispatch(reviewerDecisionSuccess())
-    return r
-  })
-}
+export const setReviewerPassword = reviewerBody =>
+  create(`/users/reset-password`, reviewerBody)
 
 export const revokeReviewer = ({ fragmentId, collectionId, invitationId }) =>
   remove(
@@ -140,113 +89,23 @@ export const reviewerDecision = ({
     },
   )
 
-export const reviewerDecline = (
-  invitationId,
-  collectionId,
+export const reviewerDecline = ({
   fragmentId,
+  collectionId,
+  invitationId,
   invitationToken,
-) => dispatch => {
-  dispatch(reviewerDecisionRequest())
-  return update(
+}) =>
+  update(
     `/collections/${collectionId}/fragments/${fragmentId}/invitations/${invitationId}/decline`,
     {
       invitationToken,
     },
-  ).then(
-    res => {
-      dispatch(reviewerDecisionSuccess())
-      return res
-    },
-    err => {
-      dispatch(reviewerDecisionError(err.message))
-      throw err
-    },
   )
-}
 // #endregion
 
 // #region Reducer
 export default (state = initialState, action = {}) => {
   switch (action.type) {
-    case GET_REVIEWERS_REQUEST:
-      return {
-        ...state,
-        fetching: {
-          ...state.fetching,
-          reviewers: true,
-        },
-        reviewers: [],
-      }
-    case GET_REVIEWERS_ERROR:
-      return {
-        ...state,
-        fetching: {
-          ...state.fetching,
-          reviewers: false,
-        },
-        error: action.error,
-      }
-    case GET_REVIEWERS_SUCCESS:
-      return {
-        ...state,
-        fetching: {
-          ...state.fetching,
-          reviewers: false,
-        },
-        reviewers: action.payload.reviewers,
-      }
-    case INVITE_REVIEWER_REQUEST:
-      return {
-        ...state,
-        fetching: {
-          ...state.fetching,
-          invite: true,
-        },
-      }
-    case INVITE_REVIEWER_SUCCESS:
-      return {
-        ...state,
-        fetching: {
-          ...state.fetching,
-          invite: false,
-        },
-        error: null,
-      }
-    case INVITE_REVIEWER_ERROR:
-      return {
-        ...state,
-        fetching: {
-          ...state.fetching,
-          invite: false,
-        },
-        error: action.error,
-      }
-    case REVIEWER_DECISION_REQUEST:
-      return {
-        ...state,
-        fetching: {
-          ...state.fetching,
-          decision: true,
-        },
-      }
-    case REVIEWER_DECISION_ERROR:
-      return {
-        ...state,
-        fetching: {
-          ...state.fetching,
-          decision: false,
-        },
-        error: action.error,
-      }
-    case REVIEWER_DECISION_SUCCESS:
-      return {
-        ...state,
-        fetching: {
-          ...state.fetching,
-          decision: false,
-        },
-        error: null,
-      }
     case CLEAR_ERROR: {
       return {
         ...state,
diff --git a/packages/styleguide/styleguide.config.js b/packages/styleguide/styleguide.config.js
index 299ae2ec11754173694cb59a223d4b75483a6b6c..1a6fe7ba50ad201d0bc3ee0a474e8ac2c01d53d9 100644
--- a/packages/styleguide/styleguide.config.js
+++ b/packages/styleguide/styleguide.config.js
@@ -33,6 +33,7 @@ module.exports = {
       components: ['../component-faraday-ui/src/gridItems/[A-Z]*.js'],
     },
   ],
+  serverPort: process.env.NODE_ENV !== 'production' ? 6060 : 3000,
   skipComponentsWithoutExample: true,
   pagePerSection: true,
   styleguideComponents: {