diff --git a/frontend/src/js/component/wb-collection-content.js b/frontend/src/js/component/wb-collection-content.js
index 31f5816..49c876a 100644
--- a/frontend/src/js/component/wb-collection-content.js
+++ b/frontend/src/js/component/wb-collection-content.js
@@ -7,11 +7,18 @@ import makeArvadosRequest from 'make-arvados-request';
 class WBCollectionContent extends Component {
   constructor(...args) {
     super(...args);
-    this.state.path = '.';
     this.state.rows = [];
     this.state.manifestReader = null;
   }
 
+  getUrl(params) {
+    let res = '/collection-browse/' +
+      (params.uuid || this.props.uuid) + '/' +
+      encodeURIComponent(params.collectionPath || this.props.collectionPath) + '/' +
+      (params.page || this.props.page);
+    return res;
+  }
+
   componentDidMount() {
     let { arvHost, arvToken } = this.props.app.state;
     let { uuid } = this.props;
@@ -26,20 +33,52 @@ class WBCollectionContent extends Component {
     });
   }
 
+  componentWillReceiveProps(nextProps) {
+    this.props = nextProps;
+    this.prepareRows();
+  }
+
   prepareRows() {
-    this.setState({});
+    let { manifestReader } = this.state;
+    let { collectionPath } = this.props;
+
+    //path = path.split('/');
+    //path = [ '.' ].concat(path);
+
+    let listing = manifestReader.listDirectory('.' + collectionPath);
+
+    this.setState({
+      'rows': listing.map(item => (
+        (item[0] === 'd') ? [
+          ({ item[1] }/),
+          'Directory',
+          null,
+          (
)
+        ] : [
+          ({ item[1] }),
+          'File',
+          filesize(item[2]),
+          ()
+        ]
+      ))
+    });
   }
 
-  render({}, { rows }) {
+  render({ collectionPath }, { rows }) {
     return (
       
-        
+        
 
-        
       
     );
   }
 }
 
+WBCollectionContent.defaultProps = {
+  'collectionPath': '',
+  'page': 0
+};
+
 export default WBCollectionContent;
diff --git a/frontend/src/js/misc/wb-collection-manifest.js b/frontend/src/js/misc/wb-collection-manifest.js
index 704cc9d..904984f 100644
--- a/frontend/src/js/misc/wb-collection-manifest.js
+++ b/frontend/src/js/misc/wb-collection-manifest.js
@@ -1,17 +1,52 @@
-class CMDirectory {
-  constructor() {
-    this.directories = {};
-    this.files = {};
+//
+// Directory: Hash[string, [Directory, File]]
+// File = [blockRefs, size]
+// blockRefs: Array[blockRef]
+// blockRef: [locator, position, size]
+// locator: String
+// position: Number
+// size: Number
+//
+
+class WBManifestReader {
+  constructor(manifest_text) {
+    this.rootDir = {};
+
+    if (!manifest_text)
+      return;
+
+    this.parse(manifest_text);
+  }
+
+  makeDir(parent, name) {
+    if (!(name in parent))
+      parent[name] = {};
+    if (parent[name] instanceof Array)
+      throw Error('Conflict trying to create a directory - a file with the same name already exists: ' + name);
+    return parent[name];
+  }
+
+  makePath(path) {
+    if (typeof(path) === 'string')
+      path = path.split('/');
+    let dir = this.rootDir;
+    for (let i = 1; i < path.length; i++)
+      dir = this.makeDir(dir, path[i]);
+    return dir;
   }
-}
 
-class CMFile {
-  constructor() {
-    this.blockRefs = [];
-    this.size = 0;
+  appendFile(streamName, locators, position, size, fileName) {
+    let path = streamName + '/' + fileName;
+    path = path.split('/');
+    let dir = this.makePath(path.slice(0, path.length - 1));
+    if (!(fileName in dir))
+      dir[fileName] = [[], 0];
+    if (!(dir[fileName] instanceof Array))
+      throw Error('Conflict trying to create a file - a directory with the same name already exists: ' + fileName);
+    this.appendReferences(dir[fileName], locators, position, size);
   }
 
-  append(locators, position, size) {
+  appendReferences(file, locators, position, size) {
     if (size === 0)
       return;
 
@@ -30,7 +65,7 @@ class CMFile {
     let startBlock = used.indexOf(true);
     let endBlock = used.lastIndexOf(true) + 1;
 
-    console.log('startBlock: ' + startBlock + ', endBlock: ' + endBlock);
+    // console.log('startBlock: ' + startBlock + ', endBlock: ' + endBlock);
 
     if (startBlock === -1)
       return;
@@ -47,53 +82,20 @@ class CMFile {
       runSize -= blockSize;
     }
 
-    this.blockRefs = this.blockRefs.concat(blockRefs);
-    this.size += size;
-  }
-}
-
-class WBManifestReader {
-  constructor(manifest_text) {
-    this.rootDir = new CMDirectory();
-
-    if (!manifest_text)
-      return;
-
-    this.parse(manifest_text);
-  }
-
-  makeDir(parent, name) {
-    if (!(name in parent.directories))
-      parent.directories[name] = new CMDirectory();
-    return parent.directories[name];
-  }
-
-  makePath(path) {
-    if (typeof(path) === 'string')
-      path = path.split('/');
-    let dir = this.rootDir;
-    for (let i = 1; i < path.length; i++)
-      dir = this.makeDir(dir, path[i]);
-    return dir;
-  }
-
-  appendFile(streamName, locators, position, size, fileName) {
-    let path = streamName + '/' + fileName;
-    path = path.split('/');
-    let dir = this.makePath(path.slice(0, path.length - 1));
-    if (!(fileName in dir.files))
-      dir.files[fileName] = new CMFile();
-    dir.files[fileName].append(locators, position, size);
+    file[0] = file[0].concat(blockRefs);
+    file[1] += size;
   }
 
   parse(manifest_text) {
     let rx = /^[a-f0-9]{32}\+[0-9]+/;
 
     let streams = manifest_text.split('\n');
+    if (!streams[streams.length - 1])
+      streams = streams.slice(0, streams.length - 1);
 
     streams.map(s => {
       let tokens = s.split(' ');
-      let streamName = tokens[0];
+      let streamName = this.unescapeName(tokens[0]);
 
       let n = tokens.map(t => rx.exec(t));
       n = n.indexOf(null, 1);
@@ -104,11 +106,61 @@ class WBManifestReader {
       let fileTokens = tokens.slice(n);
       fileTokens.map(t => {
         let [ position, size, fileName ] = t.split(':');
+        fileName = this.unescapeName(fileName);
         this.appendFile(streamName, locators,
           Number(position), Number(size), fileName);
       });
     });
   }
+
+  findDir(path) {
+    if (typeof(path) === 'string')
+      path = path.split('/');
+    if (path[0] !== '.')
+      throw Error('Path must begin with a dot component');
+    let dir = this.rootDir;
+    for (let i = 1; i < path.length; i++) {
+      if (!(path[i] in dir))
+        throw Error('Directory not found');
+      if (dir[path[i]] instanceof Array)
+        throw Error('Path is a file not directory');
+      dir = dir[path[i]];
+    }
+    return dir;
+  }
+
+  listDirectory(path) {
+    let dir = this.findDir(path);
+    let keys = Object.keys(dir);
+    keys.sort();
+    let subdirs = keys.filter(k => !(dir[k] instanceof Array));
+    let files = keys.filter(k => (dir[k] instanceof Array));
+    let res = subdirs.map(k => [ 'd', k, null ]);
+    res = res.concat(files.map(k => [ 'f', k, dir[k][1] ]));
+    return res;
+  }
+
+  unescapeName(name) {
+    return name.replace(/(\\\\|\\040)/g, (_, $1) => ($1 === '\\\\' ? '\\' : ' '));
+  }
+
+  escapeName(name) {
+    return name.replace(/ /g, '\\040');
+  }
+  /*  let ids = { '\\': 1, '0': 2, '4': 3 };
+    let transitions = [
+      [ [0, 0], [1, ''], [0, 0], [0, 0] ],
+      [ [0, 0], [0, '\\'], [2, ''], [0, 0] ],
+    ];
+    let mode = 0;
+    for (let i = 0; i < name.length; i++) {
+      let b = name[i];
+      let tokenId = Number(ids[b]);
+      [ mode, out ] = transitions[mode][tokenId];
+      if (out === 0)
+        out = b;
+    }
+  }*/
 }
 
 export { WBManifestReader };
diff --git a/frontend/src/js/page/wb-app.js b/frontend/src/js/page/wb-app.js
index ea554fb..4718dca 100644
--- a/frontend/src/js/page/wb-app.js
+++ b/frontend/src/js/page/wb-app.js
@@ -67,7 +67,7 @@ class WBApp extends Component {
 
         
 
-        
+        
       
     );
   }
diff --git a/frontend/src/js/page/wb-collection-browse.js b/frontend/src/js/page/wb-collection-browse.js
index e238702..d92cd86 100644
--- a/frontend/src/js/page/wb-collection-browse.js
+++ b/frontend/src/js/page/wb-collection-browse.js
@@ -4,7 +4,7 @@ import WBArvadosCrumbs from 'wb-arvados-crumbs';
 import WBCollectionContent from 'wb-collection-content';
 
 class WBCollectionBrowse extends Component {
-  render({ app, uuid }, {}) {
+  render({ app, uuid, collectionPath }, {}) {
     return (
       
         
@@ -15,7 +15,8 @@ class WBCollectionBrowse extends Component {
           This is the collection browser for { uuid }
         
 
-        
+        
       
     );
   }