diff --git a/.gitignore b/.gitignore
index 6fd060f87..7d9a0cd94 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
 dist/css/*
 dist/js/*
+!dist/js/flowplayer/
+!dist/js/flowplayer/
 node_modules
 .sass-cache
 .idea
diff --git a/dist/index.html b/dist/index.html
index 4bfac2bd2..d3fbbb0f6 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -21,6 +21,7 @@
       <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react.js"></script>
       <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react-dom.js"></script>
       <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.7.4/polyfill.js"></script>
+      <script src="./js/flowplayer/flowplayer-3.2.13.min.js"></script>
       <script src="./js/lbry.js"></script>
       <script src="./js/component/common.js"></script>
       <script src="./js/component/splash.js"></script>
@@ -29,6 +30,7 @@
       <script src="./js/page/help.js"></script>
       <script src="./js/page/watch.js"></script>
       <script src="./js/page/report.js"></script>
+      <script src="./js/page/my_files.js"></script>
       <script src="./js/page/start.js"></script>
       <script src="./js/app.js"></script>
       <script src="./js/main.js"></script>
diff --git a/dist/js/flowplayer/flowplayer-3.2.13.min.js b/dist/js/flowplayer/flowplayer-3.2.13.min.js
new file mode 100644
index 000000000..eba948758
--- /dev/null
+++ b/dist/js/flowplayer/flowplayer-3.2.13.min.js
@@ -0,0 +1,22 @@
+/*
+ * flowplayer.js The Flowplayer API
+ *
+ * Copyright 2009-2011 Flowplayer Oy
+ *
+ * This file is part of Flowplayer.
+ *
+ * Flowplayer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Flowplayer is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Flowplayer.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+!function(){function h(p){console.log("$f.fireEvent",[].slice.call(p))}function l(r){if(!r||typeof r!="object"){return r}var p=new r.constructor();for(var q in r){if(r.hasOwnProperty(q)){p[q]=l(r[q])}}return p}function n(u,r){if(!u){return}var p,q=0,s=u.length;if(s===undefined){for(p in u){if(r.call(u[p],p,u[p])===false){break}}}else{for(var t=u[0];q<s&&r.call(t,q,t)!==false;t=u[++q]){}}return u}function c(p){return document.getElementById(p)}function j(r,q,p){if(typeof q!="object"){return r}if(r&&q){n(q,function(s,t){if(!p||typeof t!="function"){r[s]=t}})}return r}function o(t){var r=t.indexOf(".");if(r!=-1){var q=t.slice(0,r)||"*";var p=t.slice(r+1,t.length);var s=[];n(document.getElementsByTagName(q),function(){if(this.className&&this.className.indexOf(p)!=-1){s.push(this)}});return s}}function g(p){p=p||window.event;if(p.preventDefault){p.stopPropagation();p.preventDefault()}else{p.returnValue=false;p.cancelBubble=true}return false}function k(r,p,q){r[p]=r[p]||[];r[p].push(q)}function e(p){return p.replace(/&amp;/g,"%26").replace(/&/g,"%26").replace(/=/g,"%3D")}function f(){return"_"+(""+Math.random()).slice(2,10)}var i=function(u,s,t){var r=this,q={},v={};r.index=s;if(typeof u=="string"){u={url:u}}j(this,u,true);n(("Begin*,Start,Pause*,Resume*,Seek*,Stop*,Finish*,LastSecond,Update,BufferFull,BufferEmpty,BufferStop").split(","),function(){var w="on"+this;if(w.indexOf("*")!=-1){w=w.slice(0,w.length-1);var x="onBefore"+w.slice(2);r[x]=function(y){k(v,x,y);return r}}r[w]=function(y){k(v,w,y);return r};if(s==-1){if(r[x]){t[x]=r[x]}if(r[w]){t[w]=r[w]}}});j(this,{onCuepoint:function(y,x){if(arguments.length==1){q.embedded=[null,y];return r}if(typeof y=="number"){y=[y]}var w=f();q[w]=[y,x];if(t.isLoaded()){t._api().fp_addCuepoints(y,s,w)}return r},update:function(x){j(r,x);if(t.isLoaded()){t._api().fp_updateClip(x,s)}var w=t.getConfig();var y=(s==-1)?w.clip:w.playlist[s];j(y,x,true)},_fireEvent:function(w,z,x,B){if(w=="onLoad"){n(q,function(C,D){if(D[0]){t._api().fp_addCuepoints(D[0],s,C)}});return false}B=B||r;if(w=="onCuepoint"){var A=q[z];if(A){return A[1].call(t,B,x)}}if(z&&"onBeforeBegin,onMetaData,onMetaDataChange,onStart,onUpdate,onResume".indexOf(w)!=-1){j(B,z);if(z.metaData){if(!B.duration){B.duration=z.metaData.duration}else{B.fullDuration=z.metaData.duration}}}var y=true;n(v[w],function(){y=this.call(t,B,z,x)});return y}});if(u.onCuepoint){var p=u.onCuepoint;r.onCuepoint.apply(r,typeof p=="function"?[p]:p);delete u.onCuepoint}n(u,function(w,x){if(typeof x=="function"){k(v,w,x);delete u[w]}});if(s==-1){t.onCuepoint=this.onCuepoint}};var m=function(q,s,r,u){var p=this,t={},v=false;if(u){j(t,u)}n(s,function(w,x){if(typeof x=="function"){t[w]=x;delete s[w]}});j(this,{animate:function(z,A,y){if(!z){return p}if(typeof A=="function"){y=A;A=500}if(typeof z=="string"){var x=z;z={};z[x]=A;A=500}if(y){var w=f();t[w]=y}if(A===undefined){A=500}s=r._api().fp_animate(q,z,A,w);return p},css:function(x,y){if(y!==undefined){var w={};w[x]=y;x=w}s=r._api().fp_css(q,x);j(p,s);return p},show:function(){this.display="block";r._api().fp_showPlugin(q);return p},hide:function(){this.display="none";r._api().fp_hidePlugin(q);return p},toggle:function(){this.display=r._api().fp_togglePlugin(q);return p},fadeTo:function(z,y,x){if(typeof y=="function"){x=y;y=500}if(x){var w=f();t[w]=x}this.display=r._api().fp_fadeTo(q,z,y,w);this.opacity=z;return p},fadeIn:function(x,w){return p.fadeTo(1,x,w)},fadeOut:function(x,w){return p.fadeTo(0,x,w)},getName:function(){return q},getPlayer:function(){return r},_fireEvent:function(x,w,y){if(x=="onUpdate"){var A=r._api().fp_getPlugin(q);if(!A){return}j(p,A);delete p.methods;if(!v){n(A.methods,function(){var C=""+this;p[C]=function(){var D=[].slice.call(arguments);var E=r._api().fp_invoke(q,C,D);return E==="undefined"||E===undefined?p:E}});v=true}}var B=t[x];if(B){var z=B.apply(p,w);if(x.slice(0,1)=="_"){delete t[x]}return z}return p}})};function b(r,H,u){var x=this,w=null,E=false,v,t,G=[],z={},y={},F,s,q,D,p,B;j(x,{id:function(){return F},isLoaded:function(){return(w!==null&&w.fp_play!==undefined&&!E)},getParent:function(){return r},hide:function(I){if(I){r.style.height="0px"}if(x.isLoaded()){w.style.height="0px"}return x},show:function(){r.style.height=B+"px";if(x.isLoaded()){w.style.height=p+"px"}return x},isHidden:function(){return x.isLoaded()&&parseInt(w.style.height,10)===0},load:function(K){if(!x.isLoaded()&&x._fireEvent("onBeforeLoad")!==false){var I=function(){if(v&&!flashembed.isSupported(H.version)){r.innerHTML=""}if(K){K.cached=true;k(y,"onLoad",K)}flashembed(r,H,{config:u})};var J=0;n(a,function(){this.unload(function(L){if(++J==a.length){I()}})})}return x},unload:function(K){if(v.replace(/\s/g,"")!==""){if(x._fireEvent("onBeforeUnload")===false){if(K){K(false)}return x}E=true;try{if(w){if(w.fp_isFullscreen()){w.fp_toggleFullscreen()}w.fp_close();x._fireEvent("onUnload")}}catch(I){}var J=function(){w=null;r.innerHTML=v;E=false;if(K){K(true)}};if(/WebKit/i.test(navigator.userAgent)&&!/Chrome/i.test(navigator.userAgent)){setTimeout(J,0)}else{J()}}else{if(K){K(false)}}return x},getClip:function(I){if(I===undefined){I=D}return G[I]},getCommonClip:function(){return t},getPlaylist:function(){return G},getPlugin:function(I){var K=z[I];if(!K&&x.isLoaded()){var J=x._api().fp_getPlugin(I);if(J){K=new m(I,J,x);z[I]=K}}return K},getScreen:function(){return x.getPlugin("screen")},getControls:function(){return x.getPlugin("controls")._fireEvent("onUpdate")},getLogo:function(){try{return x.getPlugin("logo")._fireEvent("onUpdate")}catch(I){}},getPlay:function(){return x.getPlugin("play")._fireEvent("onUpdate")},getConfig:function(I){return I?l(u):u},getFlashParams:function(){return H},loadPlugin:function(L,K,N,M){if(typeof N=="function"){M=N;N={}}var J=M?f():"_";x._api().fp_loadPlugin(L,K,N,J);var I={};I[J]=M;var O=new m(L,null,x,I);z[L]=O;return O},getState:function(){return x.isLoaded()?w.fp_getState():-1},play:function(J,I){var K=function(){if(J!==undefined){x._api().fp_play(J,I)}else{x._api().fp_play()}};if(x.isLoaded()){K()}else{if(E){setTimeout(function(){x.play(J,I)},50)}else{x.load(function(){K()})}}return x},getVersion:function(){var J="flowplayer.js @VERSION";if(x.isLoaded()){var I=w.fp_getVersion();I.push(J);return I}return J},_api:function(){if(!x.isLoaded()){throw"Flowplayer "+x.id()+" not loaded when calling an API method"}return w},setClip:function(I){n(I,function(J,K){if(typeof K=="function"){k(y,J,K);delete I[J]}else{if(J=="onCuepoint"){$f(r).getCommonClip().onCuepoint(I[J][0],I[J][1])}}});x.setPlaylist([I]);return x},getIndex:function(){return q},bufferAnimate:function(I){w.fp_bufferAnimate(I===undefined||I);return x},_swfHeight:function(){return w.clientHeight}});n(("Click*,Load*,Unload*,Keypress*,Volume*,Mute*,Unmute*,PlaylistReplace,ClipAdd,Fullscreen*,FullscreenExit,Error,MouseOver,MouseOut").split(","),function(){var I="on"+this;if(I.indexOf("*")!=-1){I=I.slice(0,I.length-1);var J="onBefore"+I.slice(2);x[J]=function(K){k(y,J,K);return x}}x[I]=function(K){k(y,I,K);return x}});n(("pause,resume,mute,unmute,stop,toggle,seek,getStatus,getVolume,setVolume,getTime,isPaused,isPlaying,startBuffering,stopBuffering,isFullscreen,toggleFullscreen,reset,close,setPlaylist,addClip,playFeed,setKeyboardShortcutsEnabled,isKeyboardShortcutsEnabled").split(","),function(){var I=this;x[I]=function(K,J){if(!x.isLoaded()){return x}var L=null;if(K!==undefined&&J!==undefined){L=w["fp_"+I](K,J)}else{L=(K===undefined)?w["fp_"+I]():w["fp_"+I](K)}return L==="undefined"||L===undefined?x:L}});x._fireEvent=function(R){if(typeof R=="string"){R=[R]}var S=R[0],P=R[1],N=R[2],M=R[3],L=0;if(u.debug){h(R)}if(!x.isLoaded()&&S=="onLoad"&&P=="player"){w=w||c(s);p=x._swfHeight();n(G,function(){this._fireEvent("onLoad")});n(z,function(T,U){U._fireEvent("onUpdate")});t._fireEvent("onLoad")}if(S=="onLoad"&&P!="player"){return}if(S=="onError"){if(typeof P=="string"||(typeof P=="number"&&typeof N=="number")){P=N;N=M}}if(S=="onContextMenu"){n(u.contextMenu[P],function(T,U){U.call(x)});return}if(S=="onPluginEvent"||S=="onBeforePluginEvent"){var I=P.name||P;var J=z[I];if(J){J._fireEvent("onUpdate",P);return J._fireEvent(N,R.slice(3))}return}if(S=="onPlaylistReplace"){G=[];var O=0;n(P,function(){G.push(new i(this,O++,x))})}if(S=="onClipAdd"){if(P.isInStream){return}P=new i(P,N,x);G.splice(N,0,P);for(L=N+1;L<G.length;L++){G[L].index++}}var Q=true;if(typeof P=="number"&&P<G.length){D=P;var K=G[P];if(K){Q=K._fireEvent(S,N,M)}if(!K||Q!==false){Q=t._fireEvent(S,N,M,K)}}n(y[S],function(){Q=this.call(x,P,N);if(this.cached){y[S].splice(L,1)}if(Q===false){return false}L++});return Q};function C(){if($f(r)){$f(r).getParent().innerHTML="";q=$f(r).getIndex();a[q]=x}else{a.push(x);q=a.length-1}B=parseInt(r.style.height,10)||r.clientHeight;F=r.id||"fp"+f();s=H.id||F+"_api";H.id=s;v=r.innerHTML;if(typeof u=="string"){u={clip:{url:u}}}u.playerId=F;u.clip=u.clip||{};if(r.getAttribute("href",2)&&!u.clip.url){u.clip.url=r.getAttribute("href",2)}if(u.clip.url){u.clip.url=e(u.clip.url)}t=new i(u.clip,-1,x);u.playlist=u.playlist||[u.clip];var J=0;n(u.playlist,function(){var M=this;if(typeof M=="object"&&M.length){M={url:""+M}}if(M.url){M.url=e(M.url)}n(u.clip,function(N,O){if(O!==undefined&&M[N]===undefined&&typeof O!="function"){M[N]=O}});u.playlist[J]=M;M=new i(M,J,x);G.push(M);J++});n(u,function(M,N){if(typeof N=="function"){if(t[M]){t[M](N)}else{k(y,M,N)}delete u[M]}});n(u.plugins,function(M,N){if(N){z[M]=new m(M,N,x)}});if(!u.plugins||u.plugins.controls===undefined){z.controls=new m("controls",null,x)}z.canvas=new m("canvas",null,x);v=r.innerHTML;function L(M){if(/iPad|iPhone|iPod/i.test(navigator.userAgent)&&!/.flv$/i.test(G[0].url)&&!K()){return true}if(!x.isLoaded()&&x._fireEvent("onBeforeClick")!==false){x.load()}return g(M)}function K(){return x.hasiPadSupport&&x.hasiPadSupport()}function I(){if(v.replace(/\s/g,"")!==""){if(r.addEventListener){r.addEventListener("click",L,false)}else{if(r.attachEvent){r.attachEvent("onclick",L)}}}else{if(r.addEventListener&&!K()){r.addEventListener("click",g,false)}x.load()}}setTimeout(I,0)}if(typeof r=="string"){var A=c(r);if(!A){throw"Flowplayer cannot access element: "+r}r=A;C()}else{C()}}var a=[];function d(p){this.length=p.length;this.each=function(r){n(p,r)};this.size=function(){return p.length};var q=this;for(name in b.prototype){q[name]=function(){var r=arguments;q.each(function(){this[name].apply(this,r)})}}}window.flowplayer=window.$f=function(){var q=null;var p=arguments[0];if(!arguments.length){n(a,function(){if(this.isLoaded()){q=this;return false}});return q||a[0]}if(arguments.length==1){if(typeof p=="number"){return a[p]}else{if(p=="*"){return new d(a)}n(a,function(){if(this.id()==p.id||this.id()==p||this.getParent()==p){q=this;return false}});return q}}if(arguments.length>1){var u=arguments[1],r=(arguments.length==3)?arguments[2]:{};if(typeof u=="string"){u={src:u}}u=j({bgcolor:"#000000",version:[10,1],expressInstall:"http://releases.flowplayer.org/swf/expressinstall.swf",cachebusting:false},u);if(typeof p=="string"){if(p.indexOf(".")!=-1){var t=[];n(o(p),function(){t.push(new b(this,l(u),l(r)))});return new d(t)}else{var s=c(p);return new b(s!==null?s:l(p),l(u),l(r))}}else{if(p){return new b(p,l(u),l(r))}}}return null};j(window.$f,{fireEvent:function(){var q=[].slice.call(arguments);var r=$f(q[0]);return r?r._fireEvent(q.slice(1)):null},addPlugin:function(p,q){b.prototype[p]=q;return $f},each:n,extend:j});if(typeof jQuery=="function"){jQuery.fn.flowplayer=function(r,q){if(!arguments.length||typeof arguments[0]=="number"){var p=[];this.each(function(){var s=$f(this);if(s){p.push(s)}});return arguments.length?p[arguments[0]]:new d(p)}return this.each(function(){$f(this,l(r),q?l(q):{})})}}}();!function(){var h=document.all,j="http://get.adobe.com/flashplayer",c=typeof jQuery=="function",e=/(\d+)[^\d]+(\d+)[^\d]*(\d*)/,b={width:"100%",height:"100%",id:"_"+(""+Math.random()).slice(9),allowfullscreen:true,allowscriptaccess:"always",quality:"high",version:[3,0],onFail:null,expressInstall:null,w3c:false,cachebusting:false};if(window.attachEvent){window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){}})}function i(m,l){if(l){for(var f in l){if(l.hasOwnProperty(f)){m[f]=l[f]}}}return m}function a(f,n){var m=[];for(var l in f){if(f.hasOwnProperty(l)){m[l]=n(f[l])}}return m}window.flashembed=function(f,m,l){if(typeof f=="string"){f=document.getElementById(f.replace("#",""))}if(!f){return}if(typeof m=="string"){m={src:m}}return new d(f,i(i({},b),m),l)};var g=i(window.flashembed,{conf:b,getVersion:function(){var m,f,o;try{o=navigator.plugins["Shockwave Flash"];if(o[0].enabledPlugin!=null){f=o.description.slice(16)}}catch(p){try{m=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");f=m&&m.GetVariable("$version")}catch(n){try{m=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");f=m&&m.GetVariable("$version")}catch(l){}}}f=e.exec(f);return f?[1*f[1],1*f[(f[1]*1>9?2:3)]*1]:[0,0]},asString:function(l){if(l===null||l===undefined){return null}var f=typeof l;if(f=="object"&&l.push){f="array"}switch(f){case"string":l=l.replace(new RegExp('(["\\\\])',"g"),"\\$1");l=l.replace(/^\s?(\d+\.?\d*)%/,"$1pct");return'"'+l+'"';case"array":return"["+a(l,function(o){return g.asString(o)}).join(",")+"]";case"function":return'"function()"';case"object":var m=[];for(var n in l){if(l.hasOwnProperty(n)){m.push('"'+n+'":'+g.asString(l[n]))}}return"{"+m.join(",")+"}"}return String(l).replace(/\s/g," ").replace(/\'/g,'"')},getHTML:function(o,l){o=i({},o);var n='<object width="'+o.width+'" height="'+o.height+'" id="'+o.id+'" name="'+o.id+'"';if(o.cachebusting){o.src+=((o.src.indexOf("?")!=-1?"&":"?")+Math.random())}if(o.w3c||!h){n+=' data="'+o.src+'" type="application/x-shockwave-flash"'}else{n+=' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'}n+=">";if(o.w3c||h){n+='<param name="movie" value="'+o.src+'" />'}o.width=o.height=o.id=o.w3c=o.src=null;o.onFail=o.version=o.expressInstall=null;for(var m in o){if(o[m]){n+='<param name="'+m+'" value="'+o[m]+'" />'}}var p="";if(l){for(var f in l){if(l[f]){var q=l[f];p+=f+"="+(/function|object/.test(typeof q)?g.asString(q):q)+"&"}}p=p.slice(0,-1);n+='<param name="flashvars" value=\''+p+"' />"}n+="</object>";return n},isSupported:function(f){return k[0]>f[0]||k[0]==f[0]&&k[1]>=f[1]}});var k=g.getVersion();function d(f,n,m){if(g.isSupported(n.version)){f.innerHTML=g.getHTML(n,m)}else{if(n.expressInstall&&g.isSupported([6,65])){f.innerHTML=g.getHTML(i(n,{src:n.expressInstall}),{MMredirectURL:encodeURIComponent(location.href),MMplayerType:"PlugIn",MMdoctitle:document.title})}else{if(!f.innerHTML.replace(/\s/g,"")){f.innerHTML="<h2>Flash version "+n.version+" or greater is required</h2><h3>"+(k[0]>0?"Your version is "+k:"You have no flash plugin installed")+"</h3>"+(f.tagName=="A"?"<p>Click here to download latest version</p>":"<p>Download latest version from <a href='"+j+"'>here</a></p>");if(f.tagName=="A"||f.tagName=="DIV"){f.onclick=function(){location.href=j}}}if(n.onFail){var l=n.onFail.call(this);if(typeof l=="string"){f.innerHTML=l}}}}if(h){window[n.id]=document.getElementById(n.id)}i(this,{getRoot:function(){return f},getOptions:function(){return n},getConf:function(){return m},getApi:function(){return f.firstChild}})}if(c){jQuery.tools=jQuery.tools||{version:"@VERSION"};jQuery.tools.flashembed={conf:b};jQuery.fn.flashembed=function(l,f){return this.each(function(){$(this).data("flashembed",flashembed(this,l,f))})}}}();
\ No newline at end of file
diff --git a/dist/js/flowplayer/flowplayer-3.2.18.swf b/dist/js/flowplayer/flowplayer-3.2.18.swf
new file mode 100644
index 000000000..aed1fcb12
Binary files /dev/null and b/dist/js/flowplayer/flowplayer-3.2.18.swf differ
diff --git a/dist/js/flowplayer/flowplayer.controls-3.2.16.swf b/dist/js/flowplayer/flowplayer.controls-3.2.16.swf
new file mode 100644
index 000000000..eacc8c029
Binary files /dev/null and b/dist/js/flowplayer/flowplayer.controls-3.2.16.swf differ
diff --git a/js/app.js b/js/app.js
index ac6d67509..99d89f991 100644
--- a/js/app.js
+++ b/js/app.js
@@ -1,15 +1,10 @@
-var appStyles = {
-  width: '800px',
-  marginLeft: 'auto',
-  marginRight: 'auto',
-};
 var App = React.createClass({
   getInitialState: function() {
     // For now, routes are in format ?page or ?page=args
     var match, param, val;
     [match, param, val] = window.location.search.match(/\??([^=]*)(?:=(.*))?/);
 
-    if (['settings', 'help', 'start', 'watch', 'report'].indexOf(param) != -1) {
+    if (['settings', 'help', 'start', 'watch', 'report', 'files'].indexOf(param) != -1) {
       var viewingPage = param;
     } else {
       var viewingPage = 'home';
@@ -44,31 +39,21 @@ var App = React.createClass({
       }
     });
   },
-  componentDidMount: function() {
-    lbry.getStartNotice(function(notice) {
-      if (notice) {
-        alert(notice);
-      }
-    });
-  },
   render: function() {
     if (this.state.viewingPage == 'home') {
-      var content = <HomePage />;
+      return <HomePage />;
     } else if (this.state.viewingPage == 'settings') {
-      var content = <SettingsPage />;
+      return <SettingsPage />;
     } else if (this.state.viewingPage == 'help') {
-      var content = <HelpPage />;
+      return <HelpPage />;
     } else if (this.state.viewingPage == 'watch') {
-      var content = <WatchPage name={this.state.pageArgs}/>;
+      return <WatchPage name={this.state.pageArgs}/>;
     } else if (this.state.viewingPage == 'report') {
-      var content = <ReportPage />;
+      return <ReportPage />;
+    } else if (this.state.viewingPage == 'files') {
+      return <MyFilesPage />;
     } else if (this.state.viewingPage == 'start') {
-      var content = <StartPage />;
+      return <StartPage />;
     }
-    return (
-      <div style={appStyles}>
-        {content}
-      </div>
-    );
   }
 });
\ No newline at end of file
diff --git a/js/component/common.js b/js/component/common.js
index c1dd5610e..c4f9b7631 100644
--- a/js/component/common.js
+++ b/js/component/common.js
@@ -3,9 +3,10 @@
 var Icon = React.createClass({
   propTypes: {
     style: React.PropTypes.object,
+    fixed: React.PropTypes.boolean,
   },
   render: function() {
-    var className = 'icon ' + this.props.icon;
+    var className = 'icon ' + ('fixed' in this.props ? 'icon-fixed-width ' : '') + this.props.icon;
     return <span className={className} style={this.props.style}></span>
   }
 });
@@ -18,7 +19,8 @@ var Link = React.createClass({
       className = (this.props.button ? 'button-block button-' + this.props.button : 'button-text') +
                   (this.props.hidden ? ' hidden' : '') + (this.props.disabled ? ' disabled' : '');
     return (
-      <a className={className} href={href} style={this.props.style ? this.props.style : {}} onClick={this.props.onClick}>
+      <a className={className} href={href} style={this.props.style ? this.props.style : {}}
+        title={this.props.title} onClick={this.props.onClick}>
         {this.props.icon ? icon : '' }
         {this.props.label}
       </a>
@@ -26,6 +28,79 @@ var Link = React.createClass({
   }
 });
 
+// Generic menu styles
+var menuStyle = {
+  border: '1px solid #aaa',
+  padding: '4px',
+  whiteSpace: 'nowrap',
+};
+
+var Menu = React.createClass({
+  handleWindowClick: function(e) {
+    if (this.props.toggleButton && ReactDOM.findDOMNode(this.props.toggleButton).contains(e.target)) {
+      // Toggle button was clicked
+      this.setState({
+        open: !this.state.open
+      });
+    } else if (this.state.open && !this.refs.div.contains(e.target)) {
+      // Menu is open and user clicked outside of it
+      this.setState({
+        open: false
+      });
+    }
+  },
+  propTypes: {
+    openButton: React.PropTypes.element,
+  },
+  getInitialState: function() {
+    return {
+      open: false,
+    };
+  },
+  componentDidMount: function() {
+    window.addEventListener('click', this.handleWindowClick, false);
+  },
+  componentWillUnmount: function() {
+    window.removeEventListener('click', this.handleWindowClick, false);
+  },
+  render: function() {
+    return (
+      <div ref='div' style={menuStyle} className={this.state.open ? '' : 'hidden'}>
+        {this.props.children}
+      </div>
+    );
+  }
+});
+
+var menuItemStyle = {
+  display: 'block',
+};
+var MenuItem = React.createClass({
+  propTypes: {
+    href: React.PropTypes.string,
+    label: React.PropTypes.string,
+    icon: React.PropTypes.string,
+    onClick: React.PropTypes.function,
+  },
+  getDefaultProps: function() {
+    return {
+      iconPosition: 'left',
+    }
+  },
+  render: function() {
+    var icon = (this.props.icon ? <Icon icon={this.props.icon} fixed /> : null);
+
+    return (
+      <a style={menuItemStyle} href={this.props.href} label={this.props.label} title={this.props.label}
+         className="button-text no-underline">
+        {this.props.iconPosition == 'left' ? icon : null}
+        {this.props.label}
+        {this.props.iconPosition == 'left' ? null : icon}
+      </a>
+    );
+  }
+});
+
 var creditAmountStyle = {
   color: '#216C2A',
   fontWeight: 'bold',
@@ -48,4 +123,16 @@ var CreditAmount = React.createClass({
       </span>
     );
   }
+});
+
+var subPageLogoStyle = {
+  maxWidth: '150px',
+  display: 'block',
+  marginTop: '36px',
+};
+
+var SubPageLogo = React.createClass({
+  render: function() {
+    return <img src="img/lbry-dark-1600x528.png" style={subPageLogoStyle} />;
+  }
 });
\ No newline at end of file
diff --git a/js/lbry.js b/js/lbry.js
index 3c8d7a0a8..16b8f5ef8 100644
--- a/js/lbry.js
+++ b/js/lbry.js
@@ -103,6 +103,22 @@ lbry.getFileStatus = function(name, callback) {
   lbry.call('get_lbry_file', { 'name': name }, callback);
 }
 
+lbry.getFilesInfo = function(callback) {
+  lbry.call('get_lbry_files', {}, callback);
+}
+
+lbry.startFile = function(name, callback) {
+  lbry.call('start_lbry_file', { name: name }, callback);
+}
+
+lbry.stopFile = function(name, callback) {
+  lbry.call('stop_lbry_file', { name: name }, callback);
+}
+
+lbry.deleteFile = function(name, callback) {
+  lbry.call('delete_lbry_file', { name: name }, callback)
+}
+
 lbry.getVersionInfo = function(callback) {
   lbry.call('version', {}, callback);
 };
@@ -154,6 +170,26 @@ lbry.imagePath = function(file)
   return lbry.rootPath + '/img/' + file; 
 }
 
+lbry.getMediaType = function(filename) {
+  var dotIndex = filename.lastIndexOf('.');
+  if (dotIndex == -1) {
+    return 'unknown';
+  }
+
+  var ext = filename.substr(dotIndex + 1);
+  if (/^mp4|mov|m4v|flv|f4v$/i.test(ext)) {
+    return 'video';
+  } else if (/^mp3|m4a|aac|wav|flac|ogg$/i.test(ext)) {
+    return 'audio';
+  } else if (/^html|htm|pdf|odf|doc|docx|md|markdown|txt$/i.test(ext)) {
+    return 'document';
+  } else {
+    return 'unknown';
+  }
+}
+
 lbry.stop = function(callback) {
   lbry.call('stop', {}, callback);
 };
+
+
diff --git a/js/page/help.js b/js/page/help.js
index c4599692f..64f0845cb 100644
--- a/js/page/help.js
+++ b/js/page/help.js
@@ -3,7 +3,8 @@
 var HelpPage = React.createClass({
   render: function() {
     return (
-      <main>
+      <main className="page">
+        <SubPageLogo />
         <h1>Troubleshooting</h1>
         <p>Here are the most commonly encountered problems and what to try doing about them.</p>
 
diff --git a/js/page/home.js b/js/page/home.js
index 914c24248..a05acd075 100644
--- a/js/page/home.js
+++ b/js/page/home.js
@@ -228,23 +228,41 @@ var Header = React.createClass({
 });
 
 var topBarStyle = {
-  'float': 'right'
+  'float': 'right',
+  'position': 'relative',
+  'height': '26px',
 },
 balanceStyle = {
   'marginRight': '5px'
-},
-closeIconStyle = {
-  'color': '#ff5155'
 };
 
+var mainMenuStyle = {
+  position: 'absolute',
+  top: '26px',
+  right: '0px',
+};
+
+var MainMenu = React.createClass({
+  render: function() {
+    var isLinux = /linux/i.test(navigator.userAgent); // @TODO: find a way to use getVersionInfo() here without messy state management
+    return (
+      <div style={mainMenuStyle}>
+        <Menu {...this.props}>
+          <MenuItem href='/?files' label="My Files" icon='icon-cloud-download' />
+          <MenuItem href='/?settings' label="Settings" icon='icon-gear' />
+          <MenuItem href='/?help' label="Help" icon='icon-question-circle' />
+          {isLinux ? <MenuItem href="/?start" label="Exit LBRY" icon="icon-close" />
+                   : null}
+        </Menu>
+      </div>
+    );
+  }
+});
+
 var TopBar = React.createClass({
-  onClose: function() {
-    window.location.href = "?start";
-  },
   getInitialState: function() {
     return {
       balance: 0,
-      showClose: /linux/i.test(navigator.userAgent) // @TODO: find a way to use getVersionInfo() here without messy state management
     };
   },
   componentDidMount: function() {
@@ -254,27 +272,34 @@ var TopBar = React.createClass({
       });
     }.bind(this));
   },
-
+  onClose: function() {
+    window.location.href = "?start";
+  },
   render: function() {
     return (
       <span className='top-bar' style={topBarStyle}>
         <span style={balanceStyle}>
           <CreditAmount amount={this.state.balance}/>
         </span>
-        <Link href='/?settings' icon='icon-gear' />
-        { ' ' }
-        <Link href='/?help' icon='icon-question-circle' />
-        { ' ' }
-        <Link href="/?start" onClick={this.onClose} icon="icon-close" style={closeIconStyle} hidden={!this.state.showClose} />
+
+        <Link ref="menuButton" title="LBRY Menu" icon="icon-bars" />
+        <MainMenu toggleButton={this.refs.menuButton} />
       </span>
     );
   }
 });
 
 var HomePage = React.createClass({
+  componentDidMount: function() {
+    lbry.getStartNotice(function(notice) {
+      if (notice) {
+        alert(notice);
+      }
+    });
+  },
   render: function() {
     return (
-      <div>
+      <div className="page">
         <Header />
         <Discover />
       </div>
diff --git a/js/page/my_files.js b/js/page/my_files.js
new file mode 100644
index 000000000..8802c0cc2
--- /dev/null
+++ b/js/page/my_files.js
@@ -0,0 +1,138 @@
+var removeIconColumnStyle = {
+  fontSize: '1.3em',
+  height: '120px',
+  display: 'flex',
+  alignItems: 'center',
+  justifyContent: 'center',
+},
+progressBarStyle = {
+  height: '15px',
+  width: '230px',
+  backgroundColor: '#444',
+  border: '2px solid #eee',
+  display: 'inline-block',
+},
+myFilesRowImgStyle = {
+    maxHeight: '100px',
+    display: 'block',
+    marginLeft: 'auto',
+    marginRight: 'auto',
+    float: 'left'
+};
+
+var MyFilesRow = React.createClass({
+  onRemoveClicked: function() {
+     var alertText = 'Are you sure you\'d like to remove "' + this.props.title + '?" This will ' +
+                     (this.completed ? ' stop the download and ' : '') +
+                     'permanently remove the file from your system.';
+
+    if (confirm(alertText)) {
+      lbry.deleteFile(this.props.lbryUri);
+    }
+  },
+  onPauseResumeClicked: function() {
+    if (this.props.stopped) {
+      lbry.startFile(this.props.lbryUri);
+    } else {
+      lbry.stopFile(this.props.lbryUri);
+    }
+  },
+  render: function() {
+    if (this.props.completed) {
+      var pauseLink = null;
+      var curProgressBarStyle = {display: 'none'};
+    } else {
+      var pauseLink = <Link icon={this.props.stopped ? 'icon-play' : 'icon-pause'}
+                            label={this.props.stopped ? 'Resume download' : 'Pause download'}
+                            onClick={() => { this.onPauseResumeClicked() }} />;
+
+      var curProgressBarStyle = Object.assign({}, progressBarStyle);
+      curProgressBarStyle.width = this.props.ratioLoaded * 230;
+      curProgressBarStyle.borderRightWidth = 230 - (this.props.ratioLoaded * 230) + 2;    
+    }
+
+    if (this.props.showWatchButton) {
+      // No support for lbry:// URLs in Windows or on Chrome yet
+      if (/windows|win32/i.test(navigator.userAgent) || (window.chrome && window.navigator.vendor == "Google Inc.")) {
+        var watchUri = "/?watch=" + this.props.lbryUri;
+      } else {
+        var watchUri = 'lbry://' + this.props.lbryUri;
+      }
+
+      var watchLink = <Link href={watchUri} label="Watch" icon="icon-play" button="primary" />;
+    } else {
+      var watchLink = null;
+    }
+
+    return (
+      <div className="row-fluid">
+        <div className="span3">
+          <img src={this.props.imgUrl} alt={'Photo for ' + this.props.title} style={myFilesRowImgStyle} />
+        </div>
+        <div className="span6">
+          <h2>{this.props.title}</h2>
+          <div className={this.props.completed ? 'hidden' : ''} style={curProgressBarStyle}></div>
+          { ' ' }
+          {this.props.completed ? 'Download complete' : (parseInt(this.props.ratioLoaded * 100) + '%')}
+          <div>{ pauseLink }</div>
+          <div>{ watchLink }</div>
+        </div>
+        <div className="span1" style={removeIconColumnStyle}>
+          <Link icon="icon-close" title="Remove file" onClick={() => { this.onRemoveClicked() } } /><br />
+        </div>
+      </div>
+    );
+  }
+});
+
+var MyFilesPage = React.createClass({
+  getInitialState: function() {
+    return {
+      filesInfo: null,
+    };
+  },
+  componentWillMount: function() {
+    this.updateFilesInfo();
+  },
+  updateFilesInfo: function() {
+    lbry.getFilesInfo((filesInfo) => {
+      this.setState({
+        filesInfo: (filesInfo ? filesInfo : []),
+      });
+      setTimeout(() => { this.updateFilesInfo() }, 1000);
+    });
+  },
+  render: function() {
+    if (this.state.filesInfo === null) {
+      return null;
+    }
+
+    if (!this.state.filesInfo.length) {
+      var content = <span>You haven't downloaded anything from LBRY yet. Go <Link href="/" label="search for your first download" />!</span>;
+    } else {
+      var content = [];
+      for (let fileInfo of this.state.filesInfo) {
+        let {completed, written_bytes, total_bytes, lbry_uri, file_name, stopped, metadata} = fileInfo;
+        let {name, stream_name, thumbnail} = metadata;
+
+        var title = (name || stream_name || ('lbry://' + lbry_uri));
+        var ratioLoaded = written_bytes / total_bytes;
+        var showWatchButton = (lbry.getMediaType(file_name) == 'video');
+
+        content.push(<MyFilesRow lbryUri={lbry_uri} title={title} completed={completed} stopped={stopped}
+                                 ratioLoaded={ratioLoaded} imgUrl={thumbnail}
+                                 showWatchButton={showWatchButton}/>);
+      }
+    }
+    return (
+      <main className="page">
+      <SubPageLogo />
+      <h1>My files</h1>
+      {content}
+      <section>
+        <Link href="/" label="<< Return" />
+      </section>
+      </main>
+    );
+  }
+});
\ No newline at end of file
diff --git a/js/page/report.js b/js/page/report.js
index ddfb999c4..bd46f2919 100644
--- a/js/page/report.js
+++ b/js/page/report.js
@@ -20,7 +20,8 @@ var ReportPage = React.createClass({
   },
   render: function() {
     return (
-      <main>
+      <main className="page">
+        <SubPageLogo />
         <h1>Report a bug</h1>
         <section>
         <p>Please describe the problem you experienced and any information you think might be useful to us. Links to screenshots are great!</p>
diff --git a/js/page/settings.js b/js/page/settings.js
index 958bcd312..31b7c1d27 100644
--- a/js/page/settings.js
+++ b/js/page/settings.js
@@ -73,7 +73,8 @@ var SettingsPage = React.createClass({
     }
 
     return (
-      <main>
+      <main className="page">
+        <SubPageLogo />
         <h1>Settings</h1>
         <section>
           <h4>Run on startup</h4>
diff --git a/js/page/start.js b/js/page/start.js
index 1c5b1d0b6..2f91a91d1 100644
--- a/js/page/start.js
+++ b/js/page/start.js
@@ -4,7 +4,8 @@ var StartPage = React.createClass({
   },
   render: function() {
     return (
-      <main>
+      <main className="page">
+        <SubPageLogo />
         <h1>LBRY has closed</h1>
         <Link href="lbry://lbry" label="Click here to start LBRY" />
       </main>
diff --git a/js/page/watch.js b/js/page/watch.js
index a34e5eddb..c0af88688 100644
--- a/js/page/watch.js
+++ b/js/page/watch.js
@@ -1,6 +1,6 @@
 var videoStyle = {
   width: '100%',
-  height: '100%',
+//  height: '100%',
   backgroundColor: '#000'
 };
 
@@ -19,19 +19,6 @@ var WatchPage = React.createClass({
     lbry.getStream(this.props.name);
     this.updateLoadStatus();
   },
-  reloadIfNeeded: function() {
-    // Fallback option for loading problems: every 15 seconds, if the video hasn't reported being
-    // playable yet, ask it to reload.
-    if (!this.state.readyToPlay) {
-      this._video.load()
-      setTimeout(() => { this.reloadIfNeeded() }, 15000);
-    }
-  },
-  onCanPlay: function() {
-    this.setState({
-      readyToPlay: true
-    });
-  },
   updateLoadStatus: function() {
     lbry.getFileStatus(this.props.name, (status) => {
       if (!status || status.code != 'running' || status.written_bytes == 0) {
@@ -44,31 +31,20 @@ var WatchPage = React.createClass({
         setTimeout(() => { this.updateLoadStatus() }, 250);
       } else {
         this.setState({
-          loadStatusMessage: "Buffering",
-          downloadStarted: true,
-        });
-        setTimeout(() => { this.reloadIfNeeded() }, 15000);
+          readyToPlay: true
+        })
+        flowplayer('player', 'js/flowplayer/flowplayer-3.2.18.swf');
       }
     });
   },
   render: function() {
-    if (!this.state.downloadStarted) {
-      var video = null;
-    } else {
-      // If the download has started, render the <video> behind the scenes so it can start loading.
-      // When the video is actually ready to play, the loading text is hidden and the video shown.
-      var video = <video src={"/view?name=" + this.props.name} style={videoStyle}
-                         className={this.state.readyToPlay ? '' : 'hidden'} controls
-                         onCanPlay={this.onCanPlay} ref={(video) => {this._video = video}}/>;
-    }
-
     return (
-      <main>
+      <main className="page full-width">
       <div className={this.state.readyToPlay ? 'hidden' : ''}>
         <h3>Loading lbry://{this.props.name}</h3>
         {this.state.loadStatusMessage}...
       </div>
-      {video}
+      <a id="player" href={"/view?name=" + this.props.name} style={videoStyle} />
       </main>
     );
   }
diff --git a/scss/_gui.scss b/scss/_gui.scss
index a85f09ab8..1c866e86f 100644
--- a/scss/_gui.scss
+++ b/scss/_gui.scss
@@ -13,6 +13,22 @@ body
     position: relative;
 }
 
+.page {
+  margin-left: auto;
+  margin-right: auto;
+  width: 800px;
+
+  &.full-width {
+    width: 100%;
+  }
+}
+
+.icon-fixed-width {
+  /* This borrowed is from a component of Font Awesome we're not using, maybe add it? */
+  width: (18em / 14);
+  text-align: center;
+}
+
 section
 {
   margin-bottom: $spacing-vertical;
@@ -22,7 +38,7 @@ section
   }
 }
 
-h1 { font-size: 2.0em; margin-bottom: $spacing-vertical / 2; margin-top: $spacing-vertical * 1.5; }
+h1 { font-size: 2.0em; margin-bottom: $spacing-vertical / 2; margin-top: $spacing-vertical; }
 h2 { font-size: 1.75em; }
 h3 { font-size: 1.4em; }
 h4 { font-size: 1.2em; }
@@ -127,15 +143,34 @@ input[type="search"]
 .button-text
 {
   color: $color-primary;
-  text-decoration: underline;
+  .icon
+  {
+    &:first-child {
+      padding-right: 5px;
+    }
+    &:last-child:not(:only-child) {
+      padding-left: 5px;
+    }
+  }
+
+  &:not(.no-underline) {
+    text-decoration: underline;
+    .icon {
+      text-decoration: none;
+    }
+  }
   &:hover
   {
     opacity: 0.70;
     transition: opacity .225s ease;
+    text-decoration: underline;
+    .icon {
+      text-decoration: none;
+    }
   }
 }
 
-.icon {
+.icon:only-child {
   position: relative;
   top: 0.16em;
 }