diff --git a/Bookshelf.cabal b/Bookshelf.cabal
--- a/Bookshelf.cabal
+++ b/Bookshelf.cabal
@@ -1,5 +1,5 @@
 name:           Bookshelf
-version:        0.1.3
+version:        0.1.5
 synopsis:       A simple document organizer with some wiki functionality
 description:    A simple document organizer with some wiki functionality
 category:       Text
@@ -8,18 +8,19 @@
 author:         Emil Axelsson <emax@chalmers.se>
 maintainer:     Emil Axelsson <emax@chalmers.se>
 homepage:       http://www.cs.chalmers.se/~emax/bookshelf/Manual.shelf.html
-build-depends:  base, filepath, directory, utf8-string, parseargs, pandoc
+build-depends:  base < 5, filepath, directory, utf8-string, parseargs, pandoc == 1.3
 build-type:     Simple
 
 data-files:
   bookshelf.css
   Documentation/Manual.shelf
+  Documentation/Credits.shelf
   Documentation/Test/Document1.txt
   Documentation/Test/Document2.txt
-  Documentation/Test/Document3.txt
-  Documentation/Test/Document3.shelf
+  Documentation/Test/Document2.shelf
   Documentation/Test/Notes.shelf
+  Documentation/Test/Symbols.shelf
 
-extra-source-files: Generate.hs
+extra-source-files: Types.hs, Generate.hs, Directory.hs
 executable:         bookshelf
 main-is:            Bookshelf.hs
diff --git a/Bookshelf.hs b/Bookshelf.hs
--- a/Bookshelf.hs
+++ b/Bookshelf.hs
@@ -26,34 +26,45 @@
 
 import Control.Monad
 import Data.List
-import System.Directory
 import System.Environment
 import System.FilePath
 import qualified System.IO.UTF8 as UTF8
 
 import System.Console.ParseArgs
 
+import Types
 import Generate
+import Directory
 
 
 
+-- | Move down to the given directory (affects `relPath_` and `cssLink_` in
+-- `Context`).
+moveDown :: Context -> FilePath -> Context
+moveDown context dir = context
+    { relPath_ = relPath context </> dir
+    , cssLink_ = liftM (".." </>) $ cssLink context
+    }
+
+
+
 -- | @getDirectoryContentsSeparated path = (dirs, files)@
 --
 -- Returns the files and directories under @path@:
 --
 -- @dirs@ is a list of all directories (@.@ and @..@ excluded);
 -- @files@ is a list of all files.
-getDirectoryContentsSeparated :: FilePath -> IO ([String], [String])
+getDirectoryContentsSeparated :: FilePath -> IO ([FilePath], [FilePath])
 getDirectoryContentsSeparated path = do
     conts  <- getDirectoryContents path
     isDirs <- sequence [ doesDirectoryExist (path </> cont) | cont <- conts]
 
-    let files = [cont | (cont,isDir) <- zip conts isDirs, not isDir]
+    let files = [cont | (cont,isDir) <- zip conts isDirs, not isDir, relevant cont]
         dirs  = [cont | (cont,isDir) <- zip conts isDirs, isDir, relevant cont]
 
     return (dirs,files)
   where
-    relevant = (`notElem` [".",".."])
+    relevant x = not $ "." `isPrefixOf` x
 
 
 
@@ -72,7 +83,7 @@
 --
 -- Files/directories with an associated @.ignore@ file are excluded from the
 -- results.
-getShelfContents :: FilePath -> IO ([String], [String], [String], [String])
+getShelfContents :: FilePath -> IO ([FilePath], [FilePath], [FilePath], [FilePath])
 getShelfContents path = do
     (ds,fs) <- getDirectoryContentsSeparated path
 
@@ -225,17 +236,4 @@
   --     it doesn't regenerate the index (which might then become inconsistent
   --     if meta information is changed). Don't forget to update the `argSpec`
   --     text if this feature is reintroduced.
-
--- XXX
--- Possible extensions
--- ===================
-
---   * Partial regeneration when only part of the directory has changed.
---   * Allow links relative to the source directory. Possible syntax: `"bookshelf://..."`
---   * Optionally check that `http://` links are valid.
---   * Let contents of `index.shelf` (if existing) be inserted into index.html.
-
--- The edit/regenerate script should come after the document, through
--- the `writerIncludeAfter` parameter. Otherwise it gets placed before
--- footnotes.
 
diff --git a/Directory.hs b/Directory.hs
new file mode 100644
--- /dev/null
+++ b/Directory.hs
@@ -0,0 +1,50 @@
+-- Copyright (C) 2009 Emil Axelsson <emax@chalmers.se>
+--
+-- This program 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 2 of the License, or
+-- (at your option) any later version.
+--
+-- This program 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 this program; if not, write to the Free Software
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+-- |
+-- Copyright  : Copyright (C) 2009 Emil Axelsson <emax@chalmers.se>
+-- License    : GNU GPL, version 2 or above
+--
+-- Maintainer : Emil Axelsson <emax@chalmers.se>
+--
+-- A UTF8-friendly wrapper around (the needed part of) the @System.Directory@
+-- API. @System.Directory@ works with byte-oriented strings, so in order to make
+-- something user-presentable from them, they must be decoded.
+
+module Directory where
+
+
+
+import Control.Monad
+import qualified System.Directory as Dir
+
+import Codec.Binary.UTF8.String
+
+
+
+getCurrentDirectory = liftM decodeString Dir.getCurrentDirectory
+
+setCurrentDirectory = Dir.setCurrentDirectory . encodeString
+
+doesFileExist = Dir.doesFileExist . encodeString
+
+doesDirectoryExist = Dir.doesDirectoryExist . encodeString
+
+getDirectoryContents =
+    liftM (map decodeString) . Dir.getDirectoryContents . encodeString
+
+removeFile = Dir.removeFile . encodeString
+
diff --git a/Documentation/Credits.shelf b/Documentation/Credits.shelf
new file mode 100644
--- /dev/null
+++ b/Documentation/Credits.shelf
@@ -0,0 +1,7 @@
+% Credits
+
+The following people have contributed to Bookshelf:
+
+  * Thomas Girod
+  * Eugene Kirpichov
+
diff --git a/Documentation/Manual.shelf b/Documentation/Manual.shelf
--- a/Documentation/Manual.shelf
+++ b/Documentation/Manual.shelf
@@ -59,18 +59,22 @@
 
 Pandoc's markdown syntax allows the specification of ["title blocks"](http://johnmacfarlane.net/pandoc/README.html#title-blocks) containing information about document title, authors and date. If such information is provided for shelf documents, it will be included in the document listing for each directory.
 
-Whenever a shelf document and an ordinary document have the same name, apart from extensions, the shelf document is assumed to contain information about the ordinary document. In this situation, we call the ordinary document the *main document* and the corresponding shelf document the *info document*. An info document will only appear as an "info" link next to its main document in directory listings. Further more, the info document may optionally specify meta information about the main document by including a section of the following form at the top of the markdown source:
+Whenever a shelf document and an ordinary document have the same name, apart from extensions, the shelf document is assumed to contain information about the ordinary document. In this situation, we call the ordinary document the *main document* and the corresponding shelf document the *info document*. An info document will only appear as an "info" link next to its main document in directory listings. Furthermore, the info document may optionally specify meta information about the main document by including a section of the following form at the top of the markdown source:
 
     Meta
     ====
 
       * Title: Title of document
       * Authors:
-        * Author number 1
-        * Author number 2
-        * etc.
+          * Author number 1
+          * Author number 2
+          * etc.
       * Date:    Some string indicating date
       * Comment: Some comment
+      * Keywords:
+          * Keyword 1
+          * Keyword 2
+          * etc.
 
 This information will then be used when listing the ordinary document.
 
@@ -93,4 +97,9 @@
     cabal install
 
 in the `Bookshelf` directory.
+
+Credits
+=======
+
+See [this list](Credits.shelf).
 
diff --git a/Documentation/Test/Document2.shelf b/Documentation/Test/Document2.shelf
new file mode 100644
--- /dev/null
+++ b/Documentation/Test/Document2.shelf
@@ -0,0 +1,13 @@
+Meta
+====
+
+  * Title: An interesting document
+  * Authors:
+      * Adam Helf
+  * Date:
+  * Comment: This is a cool document.
+
+Notes
+=====
+
+There could be some more notes here.
diff --git a/Documentation/Test/Document2.txt b/Documentation/Test/Document2.txt
--- a/Documentation/Test/Document2.txt
+++ b/Documentation/Test/Document2.txt
@@ -1,2 +1,1 @@
-This is another text file.
-
+This file has an associated info document that specifies title, authors, etc.
diff --git a/Documentation/Test/Document3.shelf b/Documentation/Test/Document3.shelf
deleted file mode 100644
--- a/Documentation/Test/Document3.shelf
+++ /dev/null
@@ -1,13 +0,0 @@
-Meta
-====
-
-  * Title: An interesting document
-  * Authors:
-      * Adam Helf
-  * Date:
-  * Comment: This is a cool document.
-
-Notes
-=====
-
-There could be some more notes here.
diff --git a/Documentation/Test/Document3.txt b/Documentation/Test/Document3.txt
deleted file mode 100644
--- a/Documentation/Test/Document3.txt
+++ /dev/null
@@ -1,1 +0,0 @@
-This file has an associated info document that specifies title, authors, etc.
diff --git a/Documentation/Test/Symbols.shelf b/Documentation/Test/Symbols.shelf
new file mode 100644
--- /dev/null
+++ b/Documentation/Test/Symbols.shelf
@@ -0,0 +1,65 @@
+% Symbols
+
+Arrows
+======
+
+← ↑ → ↓
+
+↔ ↕
+
+⇐ ⇑ ⇒ ⇓
+
+⇔ ⇕
+
+Mathematical operators
+======================
+
+∀ ∃ ⋀ ⋁ ¬ ≡
+
+⋂ ⋃ ⊂ ⊃ ⊆ ⊇ ∈ ∉
+
+∼ ≈ ≤ ≥
+
+· ∘ ∙ ⊕ ⊖ ⊗ ×
+
+¹ ² ³
+
+√ ∞
+
+Greek letters
+=============
+
+Sound       Symbol
+----------  ---------------------
+alpha       Α α
+beta        Β β
+gamma       Γ γ
+delta       Δ δ
+epsilon     Ε ε
+zeta        Ζ ζ
+eta         Η η
+theta       Θ θ
+iota        Ι ι
+kappa       Κ κ
+lambda      Λ λ
+mu          Μ μ
+nu          Ν ν
+xi          Ξ ξ
+omicron     Ο ο
+pi          Π π
+rho         Ρ ρ
+sigma       Σ σ
+tau         Τ τ
+upsilon     Υ υ
+phi         Φ φ
+chi         Χ χ
+psi         Ψ ψ
+omega       Ω ω
+
+Misc.
+=====
+
+® ©
+
+æ Æ ø Ø
+
diff --git a/Generate.hs b/Generate.hs
--- a/Generate.hs
+++ b/Generate.hs
@@ -34,74 +34,10 @@
 
 import Text.Pandoc
 
-
-
-data MetaInfo = MetaInfo
-       { title   :: [Inline]
-       , authors :: [[Inline]]
-       , date    :: [Inline]
-       , comment :: [Inline]
-       }
-     deriving (Eq, Show)
-
-data Context = Context
-       { -- | Optional link to CSS file
-         cssLink_    :: Maybe FilePath
-         -- | Optional editor command
-       , editor_     :: Maybe String
-         -- | Show the edit/regenerate script?
-       , showScript_ :: Bool
-         -- | Path to root of bookshelf
-       , rootPath_   :: FilePath
-         -- | Path to current node, relative to the root
-       , relPath_    :: FilePath
-       }
-     deriving (Eq, Show)
-
-data ShelfInfo = ShelfInfo
-       { -- | The document's context
-         shelfContext  :: Context
-         -- | The full name of the associated main document. `Nothing` means
-         -- that there is no main document.
-       , mainDocument  :: Maybe String
-         -- | The full name of the shelf document.
-       , shelfDocument :: String
-       }
-
-class HasContext a
-  where
-    cssLink    :: a -> Maybe FilePath
-    editor     :: a -> Maybe String
-    showScript :: a -> Bool
-    rootPath   :: a -> FilePath
-    relPath    :: a -> FilePath
-
-instance HasContext Context
-  where
-    cssLink    = cssLink_
-    editor     = editor_
-    showScript = showScript_
-    rootPath   = rootPath_
-    relPath    = relPath_
-
-instance HasContext ShelfInfo
-  where
-    cssLink    = cssLink_    . shelfContext
-    editor     = editor_     . shelfContext
-    showScript = showScript_ . shelfContext
-    rootPath   = rootPath_   . shelfContext
-    relPath    = relPath_    . shelfContext
+import Types
 
 
 
--- | Move down to the given directory (affects `relPath_` and `cssLink_` in
--- `Context`).
-moveDown :: Context -> String -> Context
-moveDown context dir = context
-    { relPath_ = relPath context </> dir
-    , cssLink_ = liftM (".." </>) $ cssLink context
-    }
-
 -- | Checks wether a path starts with @http:\/\/@.
 isHttp :: FilePath -> Bool
 isHttp path = ("http://" `isPrefixOf` path) || ("https://" `isPrefixOf` path)
@@ -254,7 +190,7 @@
 
 -- | Extracts title block information.
 extractMeta :: Pandoc -> MetaInfo
-extractMeta (Pandoc meta _) = MetaInfo title authors' date' []
+extractMeta (Pandoc meta _) = MetaInfo title authors' date' [] []
   where
     Meta title authors date = meta
 
@@ -271,11 +207,15 @@
 -- >
 -- >   * Title: Title of document
 -- >   * Authors:
--- >     * Author number 1
--- >     * Author number 2
--- >     * etc.
+-- >       * Author number 1
+-- >       * Author number 2
+-- >       * etc.
 -- >   * Date:    Some string indicating date
 -- >   * Comment: Some comment
+-- >   * Keywords:
+-- >       * Keyword 1
+-- >       * Keyword 2
+-- >       * etc.
 -- >
 -- > Here comes the rest of the document.
 -- > ...
@@ -286,13 +226,13 @@
 -- partial specifications. In particular, the fields are matched from the top,
 -- so it's fine to leave out fields at the bottom.
 parseMainMeta :: Pandoc -> MetaInfo
-parseMainMeta (Pandoc _ blocks) = MetaInfo title authors date comment
+parseMainMeta (Pandoc _ blocks) = MetaInfo title authors date comment keywords
   where
     metaBullets = case blocks of
       Header 1 [Str "Meta"] : BulletList bulls : _ -> bulls
       _                                            -> []
 
-    bsTit : bsAuth : bsDate : bsComm : _ = metaBullets ++ repeat []
+    bsTit : bsAuth : bsDate : bsComm : bsKeyw : _ = metaBullets ++ repeat []
 
     plain bs = do
       [Plain is] <- Just bs
@@ -303,14 +243,16 @@
       guard (f==f')
       return rest
 
-    parseAuthors bs = Fold.concat $ do
-      [Plain [Str "Authors:"], BulletList bulls] <- return bs
+    parseList f bs = Fold.concat $ do
+      [Plain [Str f'], BulletList bulls] <- return bs
+      guard (f==f')
       mapM plain bulls
 
-    title   = field "Title:"   bsTit
-    date    = field "Date:"    bsDate
-    comment = field "Comment:" bsComm
-    authors = parseAuthors bsAuth
+    title    = field "Title:"   bsTit
+    date     = field "Date:"    bsDate
+    comment  = field "Comment:" bsComm
+    authors  = parseList "Authors:"  bsAuth
+    keywords = parseList "Keywords:" bsKeyw
 
 
 
@@ -393,6 +335,7 @@
         [ bullet $ concat $ intersperse [Str ",", Space] $ authors meta
         , bullet $ date meta
         , bullet $ comment meta
+        , bullet $ concat $ intersperse [Str ",", Space] $ keywords meta
         ]
     ]
   where
@@ -415,10 +358,10 @@
 -- have no associated info document. @dirs@ is a list of all sub-directories.
 makeIndex
     :: Context
-    -> [(String, MetaInfo)]
-    -> [(String, MetaInfo)]
-    -> [String]
-    -> [String]
+    -> [(FilePath, MetaInfo)]
+    -> [(FilePath, MetaInfo)]
+    -> [FilePath]
+    -> [FilePath]
     -> String
 
 makeIndex context shelfs infos ords dirs = writeHtmlString wOpts pandoc
diff --git a/Types.hs b/Types.hs
new file mode 100644
--- /dev/null
+++ b/Types.hs
@@ -0,0 +1,87 @@
+-- Copyright (C) 2009 Emil Axelsson <emax@chalmers.se>
+--
+-- This program 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 2 of the License, or
+-- (at your option) any later version.
+--
+-- This program 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 this program; if not, write to the Free Software
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+-- |
+-- Copyright  : Copyright (C) 2009 Emil Axelsson <emax@chalmers.se>
+-- License    : GNU GPL, version 2 or above
+--
+-- Maintainer : Emil Axelsson <emax@chalmers.se>
+
+module Types where
+
+
+
+import Text.Pandoc
+
+
+
+data MetaInfo = MetaInfo
+       { title    :: [Inline]
+       , authors  :: [[Inline]]
+       , date     :: [Inline]
+       , comment  :: [Inline]
+       , keywords :: [[Inline]]
+       }
+     deriving (Eq, Show)
+
+data Context = Context
+       { -- | Optional link to CSS file
+         cssLink_    :: Maybe FilePath
+         -- | Optional editor command
+       , editor_     :: Maybe String
+         -- | Show the edit/regenerate script?
+       , showScript_ :: Bool
+         -- | Path to root of bookshelf
+       , rootPath_   :: FilePath
+         -- | Path to current node, relative to the root
+       , relPath_    :: FilePath
+       }
+     deriving (Eq, Show)
+
+data ShelfInfo = ShelfInfo
+       { -- | The document's context
+         shelfContext  :: Context
+         -- | The full name of the associated main document. `Nothing` means
+         -- that there is no main document.
+       , mainDocument  :: Maybe String
+         -- | The full name of the shelf document.
+       , shelfDocument :: String
+       }
+
+class HasContext a
+  where
+    cssLink    :: a -> Maybe FilePath
+    editor     :: a -> Maybe String
+    showScript :: a -> Bool
+    rootPath   :: a -> FilePath
+    relPath    :: a -> FilePath
+
+instance HasContext Context
+  where
+    cssLink    = cssLink_
+    editor     = editor_
+    showScript = showScript_
+    rootPath   = rootPath_
+    relPath    = relPath_
+
+instance HasContext ShelfInfo
+  where
+    cssLink    = cssLink_    . shelfContext
+    editor     = editor_     . shelfContext
+    showScript = showScript_ . shelfContext
+    rootPath   = rootPath_   . shelfContext
+    relPath    = relPath_    . shelfContext
+
