diff --git a/package.json b/package.json
index b10cec32d..0fe9622c2 100644
--- a/package.json
+++ b/package.json
@@ -32,6 +32,7 @@
     "postinstall": "electron-builder install-app-deps && node build/downloadDaemon.js"
   },
   "dependencies": {
+    "@types/three": "^0.93.1",
     "bluebird": "^3.5.1",
     "breakdance": "^3.0.1",
     "classnames": "^2.2.5",
diff --git a/src/renderer/component/common/markdown-preview.jsx b/src/renderer/component/common/markdown-preview.jsx
index b00ae7025..78af2273d 100644
--- a/src/renderer/component/common/markdown-preview.jsx
+++ b/src/renderer/component/common/markdown-preview.jsx
@@ -6,25 +6,34 @@ import remarkEmoji from 'remark-emoji';
 import ExternalLink from 'component/externalLink';
 import defaultSchema from 'hast-util-sanitize/lib/github.json';
 
+type MarkdownProps = {
+  content: ?string,
+  promptLinks?: boolean,
+};
+
+type SimpleLinkProps = {
+  href?: string,
+  title?: string,
+  children?: React.Node,
+};
+
+const SimpleLink = (props: SimpleLinkProps) => {
+  const { href, title, children } = props;
+  return (
+    <a href={href} title={title}>
+      {children}
+    </a>
+  );
+};
+
 // Use github sanitation schema
 const schema = { ...defaultSchema };
 
 // Extend sanitation schema to support lbry protocol
 schema.protocols.href[3] = 'lbry';
 
-type MarkdownProps = {
-  content: string,
-  promptLinks?: boolean,
-};
-
-const SimpleLink = ({ href, title, children }) => (
-  <a href={href} title={title}>
-    {children}
-  </a>
-);
-
 const MarkdownPreview = (props: MarkdownProps) => {
-  const { content, externalLinks, promptLinks } = props;
+  const { content, promptLinks } = props;
   const remarkOptions = {
     sanitize: schema,
     remarkReactComponents: {
diff --git a/src/renderer/component/fileRender/view.jsx b/src/renderer/component/fileRender/view.jsx
index b9901564e..80a3236a5 100644
--- a/src/renderer/component/fileRender/view.jsx
+++ b/src/renderer/component/fileRender/view.jsx
@@ -10,11 +10,11 @@ import HtmlViewer from 'component/viewers/htmlViewer';
 type Props = {
   mediaType: string,
   source: {
+    stream: string => void,
     fileName: string,
     fileType: string,
+    contentType: string,
     downloadPath: string,
-    stream: opts => void,
-    blob: callback => void,
   },
   currentTheme: string,
 };
diff --git a/src/renderer/component/viewers/codeViewer.jsx b/src/renderer/component/viewers/codeViewer.jsx
index 1d5164468..d10f3135c 100644
--- a/src/renderer/component/viewers/codeViewer.jsx
+++ b/src/renderer/component/viewers/codeViewer.jsx
@@ -1,6 +1,6 @@
 // @flow
 
-import React from 'react';
+import * as React from 'react';
 import CodeMirror from 'codemirror/lib/codemirror';
 import { openSnippetMenu, stopContextMenu } from 'util/contextMenu';
 
@@ -22,21 +22,20 @@ import 'codemirror/mode/javascript/javascript';
 
 type Props = {
   theme: string,
-  value: string,
+  value: ?string,
   contentType: string,
 };
 
 class CodeViewer extends React.PureComponent<Props> {
-  constructor(props) {
+  constructor(props: Props) {
     super(props);
     this.codeMirror = null;
-    this.textarea = React.createRef();
   }
 
   componentDidMount() {
     const { theme, contentType } = this.props;
     // Init CodeMirror
-    this.codeMirror = CodeMirror.fromTextArea(this.textarea.current, {
+    this.codeMirror = CodeMirror.fromTextArea(this.textarea, {
       // Auto detect syntax with file contentType
       mode: contentType,
       // Adaptive theme
@@ -54,11 +53,14 @@ class CodeViewer extends React.PureComponent<Props> {
     this.codeMirror.on('contextmenu', openSnippetMenu);
   }
 
+  textarea: ?HTMLTextAreaElement;
+  codeMirror: any;
+
   render() {
     const { value } = this.props;
     return (
       <div className="code-viewer" onContextMenu={stopContextMenu}>
-        <textarea ref={this.textarea} disabled value={value} />
+        <textarea ref={textarea => (this.textarea = textarea)} disabled value={value} />
       </div>
     );
   }
diff --git a/src/renderer/component/viewers/documentViewer.jsx b/src/renderer/component/viewers/documentViewer.jsx
index 608d34873..ed309236d 100644
--- a/src/renderer/component/viewers/documentViewer.jsx
+++ b/src/renderer/component/viewers/documentViewer.jsx
@@ -8,19 +8,25 @@ import MarkdownPreview from 'component/common/markdown-preview';
 type Props = {
   theme: string,
   source: {
-    stream: opts => void,
+    stream: string => any,
     fileType: string,
     contentType: string,
   },
 };
 
-class DocumentViewer extends React.PureComponent<Props> {
-  constructor(props) {
+type State = {
+  error: boolean,
+  loading: boolean,
+  content: ?string,
+};
+
+class DocumentViewer extends React.PureComponent<Props, State> {
+  constructor(props: Props) {
     super(props);
     this.state = {
-      error: null,
-      content: null,
+      error: false,
       loading: true,
+      content: null,
     };
   }
 
@@ -38,13 +44,14 @@ class DocumentViewer extends React.PureComponent<Props> {
       this.setState({ content: data, loading: false });
     });
 
-    stream.on('error', error => {
+    stream.on('error', () => {
       this.setState({ error: true, loading: false });
     });
   }
 
-  renderDocument(content = null) {
+  renderDocument() {
     let viewer = null;
+    const { content } = this.state;
     const { source, theme } = this.props;
     const { fileType, contentType } = source;
     const markdownType = ['md', 'markdown'];
@@ -70,7 +77,7 @@ class DocumentViewer extends React.PureComponent<Props> {
       <div className="file-render__viewer document-viewer">
         {loading && !error && <LoadingScreen status={loadingMessage} spinner />}
         {error && <LoadingScreen status={errorMessage} spinner={!error} />}
-        {isReady && this.renderDocument(content)}
+        {isReady && this.renderDocument()}
       </div>
     );
   }
diff --git a/src/renderer/component/viewers/docxViewer.jsx b/src/renderer/component/viewers/docxViewer.jsx
index 9959678c5..790269fe6 100644
--- a/src/renderer/component/viewers/docxViewer.jsx
+++ b/src/renderer/component/viewers/docxViewer.jsx
@@ -10,11 +10,17 @@ type Props = {
   source: string,
 };
 
-class DocxViewer extends React.PureComponent<Props> {
-  constructor(props) {
+type State = {
+  error: boolean,
+  loading: boolean,
+  content: ?string,
+};
+
+class DocxViewer extends React.PureComponent<Props, State> {
+  constructor(props: Props) {
     super(props);
     this.state = {
-      error: null,
+      error: false,
       content: null,
       loading: true,
     };
@@ -46,7 +52,7 @@ class DocxViewer extends React.PureComponent<Props> {
         const markdown = breakdance.render(result.value);
         this.setState({ content: markdown, loading: false });
       })
-      .catch(error => {
+      .catch(() => {
         this.setState({ error: true, loading: false });
       })
       .done();
diff --git a/src/renderer/component/viewers/pdfViewer.jsx b/src/renderer/component/viewers/pdfViewer.jsx
index ce0a2095a..e297adfd1 100644
--- a/src/renderer/component/viewers/pdfViewer.jsx
+++ b/src/renderer/component/viewers/pdfViewer.jsx
@@ -1,5 +1,5 @@
 // @flow
-import React from 'react';
+import * as React from 'react';
 import { stopContextMenu } from 'util/contextMenu';
 
 type Props = {
@@ -7,16 +7,11 @@ type Props = {
 };
 
 class PdfViewer extends React.PureComponent<Props> {
-  constructor(props) {
-    super(props);
-    this.viewer = React.createRef();
-  }
-
   render() {
     const { source } = this.props;
     return (
       <div className="file-render__viewer" onContextMenu={stopContextMenu}>
-        <webview ref={this.viewer} src={`chrome://pdf-viewer/index.html?src=file://${source}`} />
+        <webview src={`chrome://pdf-viewer/index.html?src=file://${source}`} />
       </div>
     );
   }
diff --git a/src/renderer/component/viewers/threeViewer/index.jsx b/src/renderer/component/viewers/threeViewer/index.jsx
index 0f4afb433..229347830 100644
--- a/src/renderer/component/viewers/threeViewer/index.jsx
+++ b/src/renderer/component/viewers/threeViewer/index.jsx
@@ -12,6 +12,13 @@ import ThreeScene from './internal/scene';
 import ThreeLoader from './internal/loader';
 import ThreeRenderer from './internal/renderer';
 
+type viewerTheme = {
+  gridColor: string,
+  groundColor: string,
+  backgroundColor: string,
+  centerLineColor: string,
+};
+
 type Props = {
   theme: string,
   source: {
@@ -27,12 +34,13 @@ type State = {
 };
 
 class ThreeViewer extends React.PureComponent<Props, State> {
-  static testWebgl = new Promise((resolve, reject) => {
-    if (detectWebGL()) resolve();
-    else reject();
-  });
+  static testWebgl = (): Promise<void> =>
+    new Promise((resolve, reject) => {
+      if (detectWebGL()) resolve();
+      else reject();
+    });
 
-  static createOrbitControls(camera, canvas) {
+  static createOrbitControls(camera: any, canvas: any) {
     const controls = new THREE.OrbitControls(camera, canvas);
     // Controls configuration
     controls.enableDamping = true;
@@ -46,7 +54,7 @@ class ThreeViewer extends React.PureComponent<Props, State> {
     return controls;
   }
 
-  static fitMeshToCamera(group) {
+  static fitMeshToCamera(group: any) {
     const max = { x: 0, y: 0, z: 0 };
     const min = { x: 0, y: 0, z: 0 };
 
@@ -82,23 +90,9 @@ class ThreeViewer extends React.PureComponent<Props, State> {
     See: https://github.com/mrdoob/three.js/blob/dev/docs/scenes/js/material.js#L195
   */
 
-  static updateMaterial(material, geometry) {
-    material.vertexColors = +material.vertexColors; // Ensure number
-    material.side = +material.side; // Ensure number
-    material.needsUpdate = true;
-    // If Geometry needs update
-    if (geometry) {
-      geometry.verticesNeedUpdate = true;
-      geometry.normalsNeedUpdate = true;
-      geometry.colorsNeedUpdate = true;
-    }
-  }
-
   constructor(props: Props) {
     super(props);
     const { theme } = this.props;
-    this.viewer = React.createRef();
-    this.guiContainer = React.createRef();
     // Object defualt color
     this.materialColor = '#44b098';
     // Viewer themes
@@ -124,10 +118,21 @@ class ThreeViewer extends React.PureComponent<Props, State> {
       isReady: false,
       isLoading: false,
     };
+    // Internal objects
+    this.gui = null;
+    this.grid = null;
+    this.mesh = null;
+    this.camera = null;
+    this.frameID = null;
+    this.renderer = null;
+    this.material = null;
+    this.geometry = null;
+    this.targetCenter = null;
+    this.bufferGeometry = null;
   }
 
   componentDidMount() {
-    ThreeViewer.testWebgl
+    ThreeViewer.testWebgl()
       .then(() => {
         this.renderScene();
         // Update render on resize window
@@ -187,7 +192,39 @@ class ThreeViewer extends React.PureComponent<Props, State> {
     }
   }
 
-  transformGroup(group) {
+  // Define component types
+  theme: viewerTheme;
+  themes: { dark: viewerTheme, light: viewerTheme };
+  materialColor: string;
+  // Refs
+  viewer: ?HTMLElement;
+  guiContainer: ?HTMLElement;
+  // Too complex to add a custom type
+  gui: any;
+  grid: any;
+  mesh: any;
+  scene: any;
+  camera: any;
+  frameID: any;
+  controls: any;
+  material: any;
+  geometry: any;
+  targetCenter: any;
+  bufferGeometry: any;
+
+  updateMaterial(material: any, geometry: any) {
+    this.material.vertexColors = +material.vertexColors; // Ensure number
+    this.material.side = +material.side; // Ensure number
+    this.material.needsUpdate = true;
+    // If Geometry needs update
+    if (geometry) {
+      this.geometry.verticesNeedUpdate = true;
+      this.geometry.normalsNeedUpdate = true;
+      this.geometry.colorsNeedUpdate = true;
+    }
+  }
+
+  transformGroup(group: any) {
     ThreeViewer.fitMeshToCamera(group);
 
     if (!this.targetCenter) {
@@ -203,20 +240,19 @@ class ThreeViewer extends React.PureComponent<Props, State> {
 
       const config = {
         color: this.materialColor,
-      };
-
-      config.reset = () => {
-        // Reset material color
-        config.color = this.materialColor;
-        // Reset material
-        this.material.color.set(config.color);
-        this.material.flatShading = true;
-        this.material.shininess = 30;
-        this.material.wireframe = false;
-        // Reset autoRotate
-        this.controls.autoRotate = false;
-        // Reset camera
-        this.restoreCamera();
+        reset: () => {
+          // Reset material color
+          config.color = this.materialColor;
+          // Reset material
+          this.material.color.set(config.color);
+          this.material.flatShading = true;
+          this.material.shininess = 30;
+          this.material.wireframe = false;
+          // Reset autoRotate
+          this.controls.autoRotate = false;
+          // Reset camera
+          this.restoreCamera();
+        },
       };
 
       const materialFolder = this.gui.addFolder('Material');
@@ -240,7 +276,7 @@ class ThreeViewer extends React.PureComponent<Props, State> {
         .add(this.material, 'flatShading')
         .name('FlatShading')
         .onChange(() => {
-          ThreeViewer.updateMaterial(this.material);
+          this.updateMaterial(this.material);
         })
         .listen();
 
@@ -258,11 +294,13 @@ class ThreeViewer extends React.PureComponent<Props, State> {
 
       sceneFolder.add(config, 'reset').name('Reset');
 
-      this.guiContainer.current.appendChild(this.gui.domElement);
+      if (this.guiContainer) {
+        this.guiContainer.appendChild(this.gui.domElement);
+      }
     }
   }
 
-  createGeometry(data) {
+  createGeometry(data: any) {
     this.bufferGeometry = data;
     this.bufferGeometry.computeBoundingBox();
     this.bufferGeometry.center();
@@ -301,14 +339,14 @@ class ThreeViewer extends React.PureComponent<Props, State> {
   };
 
   handleResize = () => {
-    const { offsetWidth: width, offsetHeight: height } = this.viewer.current;
+    const { offsetWidth: width, offsetHeight: height } = this.viewer || {};
     this.camera.aspect = width / height;
     this.camera.updateProjectionMatrix();
     this.controls.update();
     this.renderer.setSize(width, height);
   };
 
-  updateControlsTarget(point) {
+  updateControlsTarget(point: { x: number, y: number, z: number }) {
     this.controls.target.fromArray([point.x, point.y, point.z]);
     this.controls.update();
   }
@@ -319,7 +357,10 @@ class ThreeViewer extends React.PureComponent<Props, State> {
     this.updateControlsTarget(this.targetCenter);
   }
 
-  renderStl(data) {
+  // Flow requested to add it here
+  renderer: any;
+
+  renderStl(data: any) {
     this.createGeometry(data);
     this.mesh = new THREE.Mesh(this.geometry, this.material);
     this.mesh.name = 'model';
@@ -327,7 +368,7 @@ class ThreeViewer extends React.PureComponent<Props, State> {
     this.transformGroup(this.mesh);
   }
 
-  renderObj(event) {
+  renderObj(event: any) {
     const mesh = event.detail.loaderRootNode;
     this.mesh = new THREE.Group();
     this.mesh.name = 'model';
@@ -352,7 +393,7 @@ class ThreeViewer extends React.PureComponent<Props, State> {
     this.transformGroup(this.mesh);
   }
 
-  renderModel(fileType, parsedData) {
+  renderModel(fileType: string, parsedData: any) {
     const renderTypes = {
       stl: data => this.renderStl(data),
       obj: data => this.renderObj(data),
@@ -377,9 +418,8 @@ class ThreeViewer extends React.PureComponent<Props, State> {
       ...this.theme,
     });
 
-    const viewer = this.viewer.current;
     const canvas = this.renderer.domElement;
-    const { offsetWidth: width, offsetHeight: height } = viewer;
+    const { offsetWidth: width, offsetHeight: height } = this.viewer || {};
 
     // Grid
     this.grid = ThreeGrid({ size: 100, gridColor, centerLineColor });
@@ -408,7 +448,9 @@ class ThreeViewer extends React.PureComponent<Props, State> {
     this.startLoader();
 
     // Append canvas
-    viewer.appendChild(canvas);
+    if (this.viewer) {
+      this.viewer.appendChild(canvas);
+    }
 
     const updateScene = () => {
       this.frameID = requestAnimationFrame(updateScene);
@@ -433,11 +475,11 @@ class ThreeViewer extends React.PureComponent<Props, State> {
       <React.Fragment>
         {error && <LoadingScreen status={error} spinner={false} />}
         {showLoading && <LoadingScreen status={loadingMessage} spinner />}
-        <div ref={this.guiContainer} className={containerClass} />
+        <div ref={element => (this.guiContainer = element)} className={containerClass} />
         <div
           style={{ opacity: showViewer ? 1 : 0 }}
           className="three-viewer file-render__viewer"
-          ref={this.viewer}
+          ref={viewer => (this.viewer = viewer)}
         />
       </React.Fragment>
     );
diff --git a/yarn.lock b/yarn.lock
index ff1003b87..5f1f4193e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -130,6 +130,10 @@
   version "8.10.21"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.21.tgz#12b3f2359b27aa05a45d886c8ba1eb8d1a77e285"
 
+"@types/three@^0.93.1":
+  version "0.93.1"
+  resolved "https://registry.yarnpkg.com/@types/three/-/three-0.93.1.tgz#0b9ba53182afe16659e220d670471b4475687d64"
+
 "@types/webpack-env@^1.13.5":
   version "1.13.6"
   resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.6.tgz#128d1685a7c34d31ed17010fc87d6a12c1de6976"