diff --git a/__tests__/src/components/ManifestListItem.test.js b/__tests__/src/components/ManifestListItem.test.js
index 5ffff7ede0cb695015268fc93ee6e65976cdb8fd..dae4a8354d9aa45d1eece87ebdfa68ec5c39056d 100644
--- a/__tests__/src/components/ManifestListItem.test.js
+++ b/__tests__/src/components/ManifestListItem.test.js
@@ -29,7 +29,7 @@ describe('ManifestListItem', () => {
     const wrapper = createWrapper({ ready: false });
 
     expect(wrapper.find('.mirador-manifest-list-item').length).toBe(1);
-    expect(wrapper.find('ReactPlaceholder').length).toBe(1);
+    expect(wrapper.find('ReactPlaceholder').length > 0).toBe(true);
   });
   it('renders an error message if fetching the manifest failed', () => {
     const wrapper = createWrapper({ error: 'This is an error message' });
diff --git a/__tests__/src/selectors/index.test.js b/__tests__/src/selectors/index.test.js
index b301ab2b63b53520685f59f7e92d319bb1355825..6855e3e05a602b45e9b1e5ee4ed97dc878d0f945 100644
--- a/__tests__/src/selectors/index.test.js
+++ b/__tests__/src/selectors/index.test.js
@@ -83,6 +83,30 @@ describe('getManifestThumbnail()', () => {
     expect(received).toEqual(manifestFixture001.thumbnail['@id']);
   });
 
+  it('returns the first canvas thumbnail id', () => {
+    const manifest = {
+      manifestation: {
+        getThumbnail: () => (null),
+        getSequences: () => [
+          {
+            getCanvases: () => [
+              { getThumbnail: () => ({ id: 'xyz' }) },
+            ],
+          },
+        ],
+      },
+    };
+
+    const received = getManifestThumbnail(manifest);
+    expect(received).toEqual('xyz');
+  });
+
+  it('returns a thumbnail sized image url from the first canvas', () => {
+    const manifest = { manifestation: manifesto.create(manifestFixture019) };
+    const received = getManifestThumbnail(manifest);
+    expect(received).toEqual('https://stacks.stanford.edu/image/iiif/hg676jb4964%2F0380_796-44/full/,80/0/default.jpg');
+  });
+
   it('should return null if manifest has no thumbnail', () => {
     const manifest = { manifestation: manifesto.create({}) };
     const received = getManifestThumbnail(manifest);
diff --git a/src/components/ManifestListItem.js b/src/components/ManifestListItem.js
index d5e0a6fabb37d1fbf119c17720d17fd59d066efe..022f2943924121f6d788435db6d99b59e5dec294 100644
--- a/src/components/ManifestListItem.js
+++ b/src/components/ManifestListItem.js
@@ -95,14 +95,14 @@ export class ManifestListItem extends React.Component {
                 <Grid container spacing={24} className={classes.label}>
                   <Grid item xs={4} sm={3}>
                     {
-                      thumbnail && (
+                      <ReactPlaceholder ready={!!thumbnail} type="rect" style={{ width: 120, height: 80 }}>
                         <img
                           className={ns('manifest-list-item-thumb')}
                           src={thumbnail}
                           alt=""
                           height="80"
                         />
-                      )
+                      </ReactPlaceholder>
                     }
                   </Grid>
                   <Grid item xs={8} sm={9}>
diff --git a/src/state/selectors/index.js b/src/state/selectors/index.js
index f2940ef1181b82bf26602e6f08275a257bd05432..6d952061c3ee20979abf8a2df392b6c90b85c7cf 100644
--- a/src/state/selectors/index.js
+++ b/src/state/selectors/index.js
@@ -2,6 +2,7 @@ import filter from 'lodash/filter';
 import flatten from 'lodash/flatten';
 import { LanguageMap } from 'manifesto.js';
 import Annotation from '../../lib/Annotation';
+import ManifestoCanvas from '../../lib/ManifestoCanvas';
 
 /**
 * Return the manifest that belongs to a certain window.
@@ -43,14 +44,39 @@ export function getManifestProvider(manifest) {
 }
 
 /**
-* Return the logo of a manifest or null
+* Return the supplied thumbnail for a manifest or null
 * @param {object} manifest
 * @return {String|null}
 */
 export function getManifestThumbnail(manifest) {
-  return manifest.manifestation
-    && manifest.manifestation.getThumbnail()
-    && manifest.manifestation.getThumbnail().id;
+  /** */
+  function getTopLevelManifestThumbnail() {
+    return manifest.manifestation
+      && manifest.manifestation.getThumbnail()
+      && manifest.manifestation.getThumbnail().id;
+  }
+
+  /** */
+  function getFirstCanvasThumbnail() {
+    const canvases = getManifestCanvases(manifest);
+
+    return canvases.length > 0 && canvases[0].getThumbnail() && canvases[0].getThumbnail().id;
+  }
+
+  /** */
+  function generateThumbnailFromFirstCanvas() {
+    const canvases = getManifestCanvases(manifest);
+
+    if (canvases.length === 0) return null;
+
+    const manifestoCanvas = new ManifestoCanvas(canvases[0]);
+
+    return manifestoCanvas.thumbnail(null, 80);
+  }
+
+  return getTopLevelManifestThumbnail()
+    || getFirstCanvasThumbnail()
+    || generateThumbnailFromFirstCanvas();
 }
 
 /**