diff --git a/README.md b/README.md
index e3417878e63f365689df347de9f02fb0efcb9fbf..7099c5b1b78c887d30e06463b54698871abdc115 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,3 @@
-Note: xpub is still _very_ new. This repository contains an initial set of components but is not yet ready for use.
 
 ## xPub-faraday  
 
@@ -7,13 +6,11 @@ An MVP implementation of the first design sessions which allows a user to go thr
 ## Roadmap
 
 The major tasks we're planning to work on are the following: 
-* Implement a future-proof theming setup. (#88)
-* Let users go through multiple rounds of review. (#50)
-* Implement roles and permissions. (#58)
-* Change the data model to account for the changes that have occured in `pubsweet-server`, as well as to make it easily portable to Postgres in the future. (#67)
-* Merge xpub's authentication, routing and navigation with pubsweet's. (#55 #89 #57)
-
-![Project roadmap](https://gitlab.coko.foundation/xpub/xpub-faraday/raw/master/packages/xpub-faraday/static/faraday-roadmap.png "Faraday Project Roadmap")
+* Implement a future-proof theming setup.
+* Let users go through multiple rounds of review.
+* Implement roles and permissions.
+* Change the data model to account for the changes that have occured in `pubsweet-server`, as well as to make it easily portable to Postgres in the future.
+* Merge xpub's authentication, routing and navigation with pubsweet's.
 
 You can follow more fine-grained lists of things that we're working on  
 * [Faraday](https://gitlab.coko.foundation/xpub/xpub-faraday/boards) for tasks related to `xpub-faraday` and  
@@ -21,7 +18,7 @@ You can follow more fine-grained lists of things that we're working on
 
 ## Installing
 
-In the root directory, run `yarn` to install all the dependencies.
+In the root directory, run `yarn` to install all the dependencies. 
 
 ## Configuration
 Add the following values to `packages/xpub-collabra/config/local-development.json`
@@ -34,10 +31,16 @@ Add the following values to `packages/xpub-collabra/config/local-development.jso
 }
 ```
 
+xPub-faraday is using external services as AWS, MTS-FTP, Publons, ORCID. In order to run the app locally a `.env` file is mandatory with keys and settings for each service.
+
+Contact us at technology@hindawi.com for help getting setup.
+
 ## Running the app
 
-1. `cd packages/xpub-faraday`
-2. The first time you run the app, initialize the database with `yarn run setupdb` (press Enter when asked for a collection title, to skip that step).
+1. Open Docker engine
+2. `cd packages/xpub-faraday`
+3. start services with `yarn services`
+3. The first time you run the app, initialize the database with `yarn run setupdb` (press Enter when asked for a collection title, to skip that step).
 3. `yarn start`
 
 
diff --git a/packages/component-faraday-ui/src/PublonsTable.js b/packages/component-faraday-ui/src/PublonsTable.js
new file mode 100644
index 0000000000000000000000000000000000000000..d11c7d479ecb15cc49cbfe9d7ef2938335e444ce
--- /dev/null
+++ b/packages/component-faraday-ui/src/PublonsTable.js
@@ -0,0 +1,154 @@
+import React, { Fragment } from 'react'
+import styled from 'styled-components'
+import { th } from '@pubsweet/ui-toolkit'
+import { Button, Spinner } from '@pubsweet/ui'
+import { get } from 'lodash'
+import { compose, withHandlers, withProps } from 'recompose'
+
+import { Label, OpenModal, Text, withFetching } from '../'
+
+const TableView = ({
+  reviewers,
+  onInviteReviewer,
+  setFetching,
+  isFetching,
+  publonsError,
+}) => {
+  if (publonsError)
+    return (
+      <Text align="center" error>
+        {publonsError}
+      </Text>
+    )
+  return reviewers.length === 0 ? (
+    <Text align="center">No suggestions yet.</Text>
+  ) : (
+    <Table>
+      <thead>
+        <tr>
+          <th>
+            <Label>Full Name</Label>
+          </th>
+          <th>
+            <Label>Affiliation</Label>
+          </th>
+          <th>
+            <Label>No. of Reviews</Label>
+          </th>
+          <th>&nbsp;</th>
+        </tr>
+      </thead>
+      <tbody>
+        {reviewers.map(reviewer => (
+          <TableRow key={reviewer.email}>
+            <td>
+              <Text>{`${get(reviewer, 'name', '')}`}</Text>
+            </td>
+            <td>
+              <Text>{`${get(reviewer, 'affiliation', '')}`}</Text>
+            </td>
+            <td>
+              <Text>{`${get(reviewer, 'reviews', '')}`}</Text>
+            </td>
+            <HiddenCell>
+              <OpenModal
+                confirmText="Invite"
+                isFetching={isFetching}
+                onConfirm={modalProps => onInviteReviewer(reviewer, modalProps)}
+                setFetching={setFetching}
+                title="Send invitation to review?"
+              >
+                {showModal => (
+                  <Button onClick={showModal} primary size="small">
+                    SEND
+                  </Button>
+                )}
+              </OpenModal>
+            </HiddenCell>
+          </TableRow>
+        ))}
+      </tbody>
+    </Table>
+  )
+}
+
+const PublonsTable = ({ publonsFetching, ...rest }) => (
+  <Fragment>{publonsFetching ? <Spinner /> : <TableView {...rest} />}</Fragment>
+)
+
+export default compose(
+  withFetching,
+  withProps(({ reviewers = [] }) => ({
+    reviewers,
+  })),
+  withHandlers({
+    onInviteReviewer: ({ onInvite }) => (reviewer, modalProps) => {
+      const newReviewer = {
+        email: reviewer.email,
+        role: 'reviewer',
+        firstName: reviewer.name,
+        lastName: '',
+      }
+      onInvite(newReviewer, modalProps)
+    },
+  }),
+)(PublonsTable)
+
+// #region styles
+const Table = styled.table`
+  border-collapse: collapse;
+
+  & thead {
+    border: 1px solid ${th('colorBorder')};
+    background-color: ${th('colorBackgroundHue2')};
+    padding-top: calc(${th('gridUnit')} * 2);
+  }
+
+  & th,
+  & td {
+    border: none;
+    padding-left: calc(${th('gridUnit')} * 2);
+    text-align: start;
+    vertical-align: middle;
+
+    height: calc(${th('gridUnit')} * 5);
+    min-width: calc(${th('gridUnit')} * 12);
+  }
+`
+
+const HiddenCell = styled.td`
+  opacity: 0;
+  padding-top: ${th('gridUnit')};
+`
+
+const HidableCell = styled.td`
+  opacity: 1;
+  padding-top: ${th('gridUnit')};
+`
+
+const TableRow = styled.tr`
+  background-color: ${th('colorBackgroundHue2')};
+  border-bottom: 1px solid ${th('colorBorder')};
+
+  & td:first-child {
+    min-width: calc(${th('gridUnit')} * 20);
+  }
+
+  & td:last-child {
+    vertical-align: top;
+    text-align: right;
+    padding-right: calc(8px * 2);
+  }
+
+  &:hover {
+    background: ${th('colorBackgroundHue3')};
+
+    ${HiddenCell} {
+      opacity: 1;
+    }
+    ${HidableCell} {
+      opacity: 0;
+    }
+  }
+`
+// #endregion
diff --git a/packages/component-faraday-ui/src/PublonsTable.md b/packages/component-faraday-ui/src/PublonsTable.md
new file mode 100644
index 0000000000000000000000000000000000000000..f692c2e4740672589b4ff386c06e1f13c180315e
--- /dev/null
+++ b/packages/component-faraday-ui/src/PublonsTable.md
@@ -0,0 +1,39 @@
+A list of publon reviewers.
+
+```js
+const reviewers = [
+  {
+    id: 0,
+    email: 'email1@email.com',
+    publishingName: 'Name1',
+    recentOrganizations: {
+      name: 'Org1'
+    },
+    numVerifiedReviews: '100'
+  },
+  {
+    id: 1,
+    email: 'email2@email.com',
+    publishingName: 'Name2',
+    recentOrganizations: {
+      name: 'Org2'
+    },
+    numVerifiedReviews: '200'
+  },
+  {
+    id: 2,
+    email: 'email3@email.com',
+    publishingName: 'Name3',
+    recentOrganizations: {
+      name: 'Org3'
+    },
+    numVerifiedReviews: '300'
+  },
+];
+
+<PublonsTable reviewers={reviewers} onInviteReviwer={(reviewer, modalProps) => {
+  console.log('the reviewer', reviewer)
+  
+  modalProps.setModalError('avem eroare boss')
+}}/>
+```
diff --git a/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js b/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js
index d64a8a58c009bf3d77b62b2f5e2367b371d389c9..336bf7d1f631bcffd8b0077c9e4d7bcdfc075e03 100644
--- a/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js
+++ b/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js
@@ -12,6 +12,7 @@ import {
   marginHelper,
   ContextualBox,
   ReviewersTable,
+  PublonsTable,
   ReviewerReport,
   InviteReviewers,
   ReviewerBreakdown,
@@ -24,10 +25,14 @@ const ReviewerDetails = ({
   reports = [],
   fragment,
   invitations,
+  publonReviewers,
+  isFetching,
   previewFile,
   downloadFile,
+  fetchingError,
   canInviteReviewers,
   onInviteReviewer,
+  onInvitePublonReviewer,
   onResendReviewerInvite,
   onRevokeReviewerInvite,
   toggle,
@@ -59,12 +64,19 @@ const ReviewerDetails = ({
               >
                 <H4>Reviewer Details</H4>
               </TabButton>
-
               <TabButton
                 ml={1}
                 mr={1}
                 onClick={() => changeTab(1)}
                 selected={selectedTab === 1}
+              >
+                <H4>Reviewer Suggestions</H4>
+              </TabButton>
+              <TabButton
+                ml={1}
+                mr={1}
+                onClick={() => changeTab(2)}
+                selected={selectedTab === 2}
               >
                 <H4>Reviewer Reports</H4>
                 <Tag mr={1}>{reports.length}</Tag>
@@ -87,6 +99,14 @@ const ReviewerDetails = ({
                 </Fragment>
               )}
               {selectedTab === 1 && (
+                <PublonsTable
+                  onInvite={onInvitePublonReviewer}
+                  publonsError={fetchingError}
+                  publonsFetching={isFetching}
+                  reviewers={publonReviewers}
+                />
+              )}
+              {selectedTab === 2 && (
                 <Fragment>
                   {reports.length === 0 && (
                     <Text align="center">No reports submitted yet.</Text>
@@ -114,14 +134,22 @@ const ReviewerDetails = ({
 export default compose(
   withFilePreview,
   withFileDownload,
-  withProps(({ invitations = [], reviewerReports = [], currentUser }) => ({
-    token: get(currentUser, 'token', ''),
-    invitations: invitations.map(i => ({
-      ...i,
-      review: reviewerReports.find(r => r.userId === i.userId),
-    })),
-    reports: reviewerReports.filter(r => r.submittedOn),
-  })),
+  withProps(
+    ({
+      invitations = [],
+      publonReviewers = [],
+      reviewerReports = [],
+      currentUser,
+    }) => ({
+      token: get(currentUser, 'token', ''),
+      publonReviewers,
+      invitations: invitations.map(i => ({
+        ...i,
+        review: reviewerReports.find(r => r.userId === i.userId),
+      })),
+      reports: reviewerReports.filter(r => r.submittedOn),
+    }),
+  ),
   withProps(({ currentUser }) => ({
     canInviteReviewers: get(currentUser, 'permissions.canInviteReviewers'),
     canViewReviewersDetails: get(
diff --git a/packages/component-faraday-ui/src/index.js b/packages/component-faraday-ui/src/index.js
index 9c505e4d598f0482be74d0c8d9de774572327b8d..263820a923f836e555affe74bed8bd51d6ea7b6d 100644
--- a/packages/component-faraday-ui/src/index.js
+++ b/packages/component-faraday-ui/src/index.js
@@ -30,6 +30,7 @@ export { default as Pagination } from './Pagination'
 export { default as PersonInfo } from './PersonInfo'
 export { default as PersonInvitation } from './PersonInvitation'
 export { default as PreviewFile } from './PreviewFile'
+export { default as PublonsTable } from './PublonsTable'
 export { default as RadioWithComments } from './RadioWithComments'
 export { default as ReviewerReport } from './ReviewerReport'
 export { default as ReviewersTable } from './ReviewersTable'
diff --git a/packages/component-invite/src/FragmentsInvitations.js b/packages/component-invite/src/FragmentsInvitations.js
index 7a4d2507424cbeb5a5a0c0357779508fed009a8d..7e01cf30948ac41226e63f44571199461c0f106a 100644
--- a/packages/component-invite/src/FragmentsInvitations.js
+++ b/packages/component-invite/src/FragmentsInvitations.js
@@ -16,7 +16,12 @@ const FragmentsInvitations = app => {
    * @apiParamExample {json} Body
    *    {
    *      "email": "email@example.com",
-   *      "role": "reviewer", [acceptedValues: reviewer]
+   *      "role": "reviewer", [acceptedValues: reviewer],
+   *      "firstName": "Julien",
+   *      "lastName": "Hopfenkonig",
+   *      "affiliation": "UCLA",
+   *      "country": "RO"
+   *      "isPublons": false [Boolean]
    *    }
    * @apiSuccessExample {json} Success
    *    HTTP/1.1 200 OK
@@ -51,8 +56,8 @@ const FragmentsInvitations = app => {
    *    HTTP/1.1 200 OK
    *    [{
    *      "name": "John Smith",
-   *     "invitedOn": 1525428890167,
-   *     "respondedOn": 1525428890299,
+   *      "invitedOn": 1525428890167,
+   *      "respondedOn": 1525428890299,
    *      "email": "email@example.com",
    *      "status": "pending",
    *      "invitationId": "1990881"
diff --git a/packages/component-invite/src/routes/fragmentsInvitations/post.js b/packages/component-invite/src/routes/fragmentsInvitations/post.js
index b0935ef55d759310cdcc596e40e70353967370f9..ae1eeb0282021d4211f9048abe2fc969e5396308 100644
--- a/packages/component-invite/src/routes/fragmentsInvitations/post.js
+++ b/packages/component-invite/src/routes/fragmentsInvitations/post.js
@@ -122,9 +122,17 @@ module.exports = models => async (req, res) => {
   } catch (e) {
     const userHelper = new User({ UserModel })
 
+    const userData = req.body
+    const { firstName, lastName, isPublons } = userData
+
+    if (process.env.PUBLONS_MOCK_EMAIL && isPublons) {
+      const mockEmail = process.env.PUBLONS_MOCK_EMAIL
+      userData.email = mockEmail.replace('__NAME__', `${firstName}.${lastName}`)
+    }
+
     const newUser = await userHelper.createUser({
       role,
-      body: req.body,
+      body: userData,
     })
 
     if (collection.status === 'heAssigned')
diff --git a/packages/component-manuscript/src/components/ManuscriptLayout.js b/packages/component-manuscript/src/components/ManuscriptLayout.js
index fc006093cb6812da5384997a07d97dba965ed1f3..f3bfdbb744fc13812e5afdf256cfd53c34584276 100644
--- a/packages/component-manuscript/src/components/ManuscriptLayout.js
+++ b/packages/component-manuscript/src/components/ManuscriptLayout.js
@@ -45,6 +45,7 @@ const ManuscriptLayout = ({
   fragment = {},
   changeForm,
   isFetching,
+  fetchingError,
   formValues,
   heExpanded,
   onHEResponse,
@@ -57,18 +58,19 @@ const ManuscriptLayout = ({
   onRevokeReviewerInvite,
   toggleReviewerResponse,
   invitationsWithReviewers,
+  publonReviewers,
   reviewerResponseExpanded,
   pendingOwnRecommendation,
   toggleReviewerRecommendations,
   reviewerRecommendationExpanded,
   shouldReview,
   submittedOwnRecommendation,
-  heAccepted,
   reviewerReports,
   onEditorialRecommendation,
   reviewerRecommendations,
   toggleReviewerDetails,
   reviewerDetailsExpanded,
+  onInvitePublonReviewer,
 }) => (
   <Root pb={30}>
     {!isEmpty(collection) && !isEmpty(fragment) ? (
@@ -166,15 +168,19 @@ const ManuscriptLayout = ({
           <ReviewerDetails
             currentUser={currentUser}
             expanded={reviewerDetailsExpanded}
+            fetchingError={fetchingError}
             fragment={fragment}
             getSignedUrl={getSignedUrl}
             highlight={reviewerReports.length === 0}
             invitations={invitationsWithReviewers}
+            isFetching={isFetching.publonsFetching}
             journal={journal}
             mb={2}
+            onInvitePublonReviewer={onInvitePublonReviewer}
             onInviteReviewer={onInviteReviewer}
             onResendReviewerInvite={onResendReviewerInvite}
             onRevokeReviewerInvite={onRevokeReviewerInvite}
+            publonReviewers={publonReviewers}
             reviewerReports={reviewerReports}
             scrollIntoView
             toggle={toggleReviewerDetails}
diff --git a/packages/component-manuscript/src/components/ManuscriptPage.js b/packages/component-manuscript/src/components/ManuscriptPage.js
index ac4868da0b46a6367c6241e128a699d413fb9f63..af451b26a93a5d81891cb85f584e108fb404ac36 100644
--- a/packages/component-manuscript/src/components/ManuscriptPage.js
+++ b/packages/component-manuscript/src/components/ManuscriptPage.js
@@ -56,10 +56,19 @@ import {
   getFragmentReviewerRecommendations,
   getInvitationsWithReviewersForFragment,
 } from 'pubsweet-component-faraday-selectors'
-import { RemoteOpener, handleError } from 'pubsweet-component-faraday-ui'
+import {
+  RemoteOpener,
+  handleError,
+  withFetching,
+} from 'pubsweet-component-faraday-ui'
 
 import ManuscriptLayout from './ManuscriptLayout'
-import { parseEicDecision, parseSearchParams, redirectToError } from './utils'
+import {
+  parseEicDecision,
+  parseSearchParams,
+  redirectToError,
+  getPublonsReviewers,
+} from './utils'
 import {
   canAssignHE,
   selectFetching,
@@ -74,6 +83,8 @@ export default compose(
   setDisplayName('ManuscriptPage'),
   withJournal,
   withRouter,
+  withFetching,
+  withState('publonReviewers', 'setPub', []),
   withState('editorInChief', 'setEiC', 'N/A'),
   ConnectPage(({ match }) => [
     actions.getCollection({ id: match.params.project }),
@@ -136,6 +147,7 @@ export default compose(
         pendingHEInvitation,
         pendingOwnRecommendation,
         pendingReviewerInvitation,
+        isFetching,
       },
     ) => ({
       currentUser: {
@@ -165,6 +177,7 @@ export default compose(
       },
       isFetching: {
         editorsFetching: selectFetching(state),
+        publonsFetching: isFetching,
       },
       formValues: {
         eicDecision: getFormValues('eic-decision')(state),
@@ -209,6 +222,8 @@ export default compose(
         setEiC(`${firstName} ${lastName}`)
       }
     },
+    setPublons: ({ setPub }) => (publonReviewers = []) =>
+      setPub(publonReviewers),
     assignHE: ({
       assignHandlingEditor,
       fetchUpdatedCollection,
@@ -403,6 +418,41 @@ export default compose(
         })
     },
   }),
+  withHandlers({
+    onInvitePublonReviewer: ({
+      collection,
+      fragment,
+      fetchUpdatedCollection,
+      setPublons,
+      setFetching: setListFetching,
+      setError,
+      clearError,
+    }) => (values, { hideModal, setModalError, setFetching }) => {
+      setFetching(true)
+      inviteReviewer({
+        reviewerData: values,
+        fragmentId: fragment.id,
+        collectionId: collection.id,
+        isPublon: true,
+      })
+        .then(() => {
+          setFetching(false)
+          hideModal()
+          fetchUpdatedCollection()
+          getPublonsReviewers({
+            fragmentId: fragment.id,
+            setPublons,
+            setFetching: setListFetching,
+            setError,
+            clearError,
+          })
+        })
+        .catch(err => {
+          setFetching(false)
+          handleError(setModalError)(err)
+        })
+    },
+  }),
   fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({
     toggleAssignHE: toggle,
     heExpanded: expanded,
@@ -435,14 +485,24 @@ export default compose(
         match,
         history,
         location,
+        setPublons,
         shouldReview,
         reviewerReports,
         setEditorInChief,
         clearCustomError,
         hasManuscriptFailure,
         fetchUpdatedCollection,
-        currentUser: { isInvitedHE, isInvitedToReview, isHEToManuscript },
+        currentUser: {
+          isInvitedHE,
+          isInvitedToReview,
+          isHEToManuscript,
+          permissions: { canInviteReviewers },
+        },
+        setFetching,
+        setError,
+        clearError,
       } = this.props
+
       if (hasManuscriptFailure) {
         history.push('/not-found')
         clearCustomError()
@@ -462,6 +522,16 @@ export default compose(
         setEditorInChief(head(res.users)),
       )
 
+      if (canInviteReviewers) {
+        getPublonsReviewers({
+          fragmentId,
+          setPublons,
+          setFetching,
+          setError,
+          clearError,
+        })
+      }
+
       if (isInvitedHE) {
         this.props.toggleHEResponse()
       }
diff --git a/packages/component-manuscript/src/components/utils.js b/packages/component-manuscript/src/components/utils.js
index 031879a3af200d911cfa905707d35b3406b41395..3fd58fbc9af7b3c79394b81f3cfde6162c2d09a3 100644
--- a/packages/component-manuscript/src/components/utils.js
+++ b/packages/component-manuscript/src/components/utils.js
@@ -13,6 +13,7 @@ import { change as changeForm } from 'redux-form'
 
 import { actions } from 'pubsweet-client/src'
 import { handleError } from 'pubsweet-component-faraday-ui'
+import { get as apiGet } from 'pubsweet-client/src/helpers/api'
 
 import {
   autosaveRequest,
@@ -303,3 +304,24 @@ export const parseEicDecision = ({ decision, message }) => ({
     },
   ],
 })
+
+// handle publons
+export const getPublonsAPI = fragmentId =>
+  apiGet(`/fragments/${fragmentId}/publons`)
+
+export const getPublonsReviewers = ({
+  fragmentId,
+  setPublons,
+  setFetching,
+  setError,
+  clearError,
+}) => {
+  clearError()
+  setFetching(true)
+  getPublonsAPI(fragmentId)
+    .then(res => {
+      setPublons(res)
+      setFetching(false)
+    })
+    .catch(handleError(setError))
+}
diff --git a/packages/components-faraday/src/redux/reviewers.js b/packages/components-faraday/src/redux/reviewers.js
index 7542b980da4cdb1aaab21256f0b85bca2cabfb3d..9d2ee9b6333822535652d83f30b1802a21a879df 100644
--- a/packages/components-faraday/src/redux/reviewers.js
+++ b/packages/components-faraday/src/redux/reviewers.js
@@ -59,10 +59,16 @@ export const getCollectionReviewers = (collectionId, fragmentId) => dispatch =>
   )
 // #endregion
 
-export const inviteReviewer = ({ reviewerData, collectionId, fragmentId }) =>
+export const inviteReviewer = ({
+  reviewerData,
+  collectionId,
+  fragmentId,
+  isPublons = false,
+}) =>
   create(`/collections/${collectionId}/fragments/${fragmentId}/invitations`, {
     ...reviewerData,
     role: 'reviewer',
+    isPublons,
   })
 
 // #region Actions - invitations