diff --git a/klaus.py b/klaus.py
index 88236360baf5ea1d1c852d43c997ec540c8646ac..f4624c14fd894de02f2f2dea5ebd6dee0a229249 100644
--- a/klaus.py
+++ b/klaus.py
@@ -1,4 +1,5 @@
 import os
+import stat
 import time
 from functools import wraps
 
@@ -78,8 +79,6 @@ def get_repo(name):
         raise HttpError(404, 'No repository named "%s"' % name)
 
 def get_commit(repo, id):
-    if isinstance(repo, basestring):
-        repo = get_repo(repo)
     try:
         commit = repo[id]
         if not isinstance(commit, Commit):
@@ -88,23 +87,45 @@ def get_commit(repo, id):
     except KeyError:
         raise HttpError(404, '"%s" has no commit "%s"' % (repo.name, id))
 
+def get_branch_or_commit(repo, id):
+    try:
+        return repo.get_branch(id)
+    except KeyError:
+        return get_commit(repo, id)
+
+def get_tree_or_blob_url(repo, commit_id, tree_entry):
+    if tree_entry.mode & stat.S_IFDIR:
+        view = 'view_tree'
+    else:
+        view = 'view_blob'
+    return app.build_url(view,
+        repo=repo.name, commit_id=commit_id, path=tree_entry.path)
+
 @app.route('/')
 def repo_list(env):
     return {'repos' : app.repos.items()}
 
 @app.route('/:repo:/')
 def view_repo(env, repo):
-    redirect_to = app.build_url('view_tree', repo=repo, commit_id='master')
+    redirect_to = app.build_url('view_tree', repo=repo, commit_id='master', path='')
     return '302 Move On', {'Location' : redirect_to}, ''
 
-@app.route('/:repo:/tree/:commit_id:/')
-def view_tree(env, repo, commit_id):
+@app.route('/:repo:/tree/:commit_id:/(?P<path>.*)')
+def view_tree(env, repo, commit_id, path):
     repo = get_repo(repo)
-    try:
-        commit = repo.get_branch(commit_id)
-    except KeyError:
-        commit = get_commit(repo, commit_id)
-    return {'repo' : repo, 'commit' : commit}
+    commit = get_branch_or_commit(repo, commit_id)
+    files = ((name, get_tree_or_blob_url(repo, commit_id, entry))
+             for name, entry in repo.listdir(commit, path))
+    return {'repo' : repo, 'commit_id' : commit_id,
+            'files' : files, 'path' : path}
+
+@app.route('/:repo:/blob/:commit_id:/(?P<path>.*)')
+def view_blob(env, repo, commit_id, path):
+    repo = get_repo(repo)
+    commit = get_branch_or_commit(repo, commit_id)
+    directory, filename = os.path.split(path)
+    blob = repo[repo.get_tree(commit, directory)[filename][1]]
+    return {'repo' : repo, 'blob' : blob, 'path' : path, 'commit_id' : commit_id}
 
 @app.route('/:repo:/commit/:id:/')
 def view_commit(env, repo, id):
diff --git a/repo.py b/repo.py
index af34db80c8e167120292c4c845f5c8be4b85d2ca..4d3b10e5779282e86280daa243581d597455f363 100644
--- a/repo.py
+++ b/repo.py
@@ -20,12 +20,16 @@ class RepoWrapper(dulwich.repo.Repo):
             head = self[head.parents[0]]
             max_commits -= 1
 
-    def listdir(self, commit=None, root=None):
+    def get_tree(self, commit, path):
         tree = self[commit.tree]
-        if root is not None:
-            for directory in root.split('/'):
-                tree = self[tree[directory].sha]
-        return tree.iteritems()
+        if path:
+            for directory in path.split('/'):
+                tree = self[tree[directory][1]]
+        return tree
+
+    def listdir(self, commit, root=None):
+        tree = self.get_tree(commit, root)
+        return ((entry.path, entry.in_path(root)) for entry in tree.iteritems())
 
     def commit_diff(self, commit):
         parent = self[commit.parents[0]]
diff --git a/templates/view_blob.html b/templates/view_blob.html
new file mode 100644
index 0000000000000000000000000000000000000000..b339de0329591d5637dd68c4a791d653b01d8bd7
--- /dev/null
+++ b/templates/view_blob.html
@@ -0,0 +1,12 @@
+{% if path %}
+  {% set title = '%s in %s/%s' % (path, repo.name, commit_id) %}
+{% else %}
+  {% set title = '%s/%s' % (repo.name, commit_id) %}
+{% endif %}
+
+{% extends 'base.html' %}
+{% block content %}
+
+{{ blob.data|pygmentize }}
+
+{% endblock %}
diff --git a/templates/view_tree.html b/templates/view_tree.html
index 13a3249453f653551c9e2ab1477cba84a9997e28..bde19caff82b3d330bb40a4ed4fd5fcdc598524d 100644
--- a/templates/view_tree.html
+++ b/templates/view_tree.html
@@ -1,4 +1,9 @@
-{% set title = repo.name %}
+{% if path %}
+  {% set title = '%s in %s/%s' % (path, repo.name, commit_id) %}
+{% else %}
+  {% set title = '%s/%s' % (repo.name, commit_id) %}
+{% endif %}
+
 {% extends 'base.html' %}
 {% block content %}
 
@@ -17,8 +22,8 @@
 </ul>
 
 <ul class=tree>
-{% for file, _, _ in repo.listdir(commit=commit) %}
-  <li>{{ file }}</li>
+{% for name, url in files %}
+  <li><a href="{{ url }}">{{ name }}</a></li>
 {% endfor %}
 </ul>