diff --git a/website/site/content/docs/dev/building.md b/website/site/content/docs/dev/building.md
index 45768223..395ae3af 100644
--- a/website/site/content/docs/dev/building.md
+++ b/website/site/content/docs/dev/building.md
@@ -4,7 +4,9 @@ weight = 0
 +++
 
 
-You must install [sbt](https://scala-sbt.org) and [Elm](https://elm-lang.org).
+You must install [sbt](https://scala-sbt.org),
+[nodejs](https://www.npmjs.com/get-npm) (for the `npm` command) and
+[Elm](https://elm-lang.org).
 
 Clone the sources and run:
 
diff --git a/website/site/content/docs/dev/translation.md b/website/site/content/docs/dev/translation.md
new file mode 100644
index 00000000..0b252a6f
--- /dev/null
+++ b/website/site/content/docs/dev/translation.md
@@ -0,0 +1,402 @@
++++
+title = "Translating Web-UI"
+weight = 10
++++
+
+
+Help with translating the web-ui is greatly appreciated. I can only
+provide translations for English and German, and these may be wrong -
+so pointing out mistakes is also appreciated :).
+
+Here is a detailed walkthrough for adding a new language. It requires
+to code in [Elm](https://elm-lang.org). But even if you're not a
+programmer, you will be comfortable as it's not difficult for this
+task. Elm is also a nice and friendly language, provding helpful error
+messages.
+
+This guide assumes no knowledge about Elm at all.
+
+# TL;DR
+
+If you are already familiar with Elm, here is the TL;DR:
+
+1. Goto `Messages.UiLanguage` in `modules/webapp/src/main/elm` and add
+   another language to the union type and also to the `all` list.
+2. Fix all compile errors by providing a different `Texts` value for
+   the new language.
+
+
+# Prepare
+
+You need to install [git](https://git-scm.org),
+[sbt](https://scala-sbt.org), [Elm](https://elm-lang.org) and
+[nodejs](https://www.npmjs.com/get-npm) (for the `npm` command) to
+compile and run the project.
+
+It is also recommended to install `elm-format` as it will help you to
+format the elm source code. Look
+[here](https://github.com/avh4/elm-format) for how to install it with
+your editor of choice.
+
+## Checkout the source code
+
+Note: These steps are only required to do once. If you come back to
+translating, just start the application.
+
+
+Use git to clone the docspell repository to your machine. In a
+terminal type:
+
+``` bash
+❯ git clone https://github.com/eikek/docspell.git
+Cloning into 'docspell'...
+remote: Enumerating objects: 1861, done.
+remote: Counting objects: 100% (1861/1861), done.
+remote: Compressing objects: 100% (861/861), done.
+remote: Total 30276 (delta 821), reused 1604 (delta 668), pack-reused 28415
+Receiving objects: 100% (30276/30276), 60.89 MiB | 23.62 MiB/s, done.
+Resolving deltas: 100% (14658/14658), done.
+
+/tmp took 4s
+❯
+```
+
+This creates a new directory `docspell`. Change into it, create a
+`DOCSPELL_ENV` environment variable and run sbt:
+
+``` bash
+❯ cd docspell
+docspell on  master via 🌳 v0.19.1 via ☕ v11.0.9 via ⬢ v12.21.0
+❯ export DOCSPELL_ENV=dev
+❯ sbt
+[info] welcome to sbt 1.5.0 (Oracle Corporation Java 1.8.0_212)
+[info] loading settings for project global-plugins from plugins.sbt ...
+[info] loading settings for project docspell-build from plugins.sbt ...
+[info] loading project definition from /tmp/docspell/project
+[info] compiling 6 Scala sources to /tmp/docspell/project/target/scala-2.12/sbt-1.0/classes ...
+[info] loading settings for project root from build.sbt,version.sbt ...
+[info] resolving key references (24191 settings) ...
+[info] set current project to docspell-root (in build file:/tmp/docspell/)
+[info] sbt server started at local:///home/eike/.sbt/1.0/server/3cf61b9ad9af43ee6032/sock
+[info] started sbt server
+sbt:docspell-root>
+```
+
+This downloads some stuff and puts you in the sbt shell. Now compile
+everything (only needed the first time after checkout):
+
+``` sbt
+sbt:docspell-root> make
+```
+
+This will take a while, you need to wait until this is finished.
+
+
+## Start the application
+
+If sbt is not started, start sbt from within the source root. Also
+export the `DOCSPELL_ENV` variable *before* starting sbt:
+
+``` bash
+> export DOCSPELL_ENV=dev
+> sbt
+```
+
+Then start the application:
+
+``` sbt
+sbt:docspell-root> reStart
+```
+
+This starts docspell (joex and the restserver). Once the output gets a
+bit quiter, open a browser and navigate to `http://localhost:7880`.
+You can create a new account (if not already done so) and login.
+
+Note that the database is created in your `/tmp` directory, so it
+might be cleared once you restart your machine. For translating this
+should not be a problem.
+
+## Make webui updates faster
+
+The sbt build tool could be used to watch the elm sources and
+re-compile everything on change. This however also restarts the server
+and takes quite long. When only coding on the webui the server can be
+just left as is. Only the new compiled webapp must be made available
+to the running server. For this, a script is provided in the
+`project/` folder.
+
+Now open another terminal and `cd` into the docspell folder as before
+and run the following:
+
+``` bash
+❯ ./project/dev-ui-build.sh watch
+Compile elm to js …
+Success!
+
+    Main ───> /tmp/docspell/modules/webapp/target/scala-2.13/classes/META-INF/resources/webjars/docspell-webapp/0.22.0-SNAPSHOT/docspell-app.js
+
+Building css …
+/tmp/docspell
+Watching css and elm sources. C-c to quit.
+Setting up watches.  Beware: since -r was given, this may take a while!
+Watches established.
+```
+
+Once you see this, you're all set. The docspell application is running
+and changes to elm files are detected, the webapp is compiled and the
+resulting javascript file is copied to the correct location. To see
+your changes, a refresh in the browser is necessary.
+
+If this script is not working, install inotify-tools. The
+`inotifywait` command is required.
+
+You'll notice that compiling elm files is very fast!
+
+
+## Find the webapp sources
+
+The web-ui is implemented in the `webapp` module. The sources can be
+found in the folder `modules/webapp/src/main/elm`.
+
+All translated strings are in the files below `Messages` directory.
+You should start with the file `UiLanguage.elm` to add a new language
+to the list. Then start with `App.elm` to provide transalations. See
+below for details.
+
+
+# Example: Add German
+
+## Add the new language
+
+Start by editing `UiLanguage.elm` and add another language to the
+list:
+
+``` elm
+type UiLanguage
+    = English
+    | German
+```
+
+More languaes are simply appended using the `|` symbol. Use the
+English name here, because this is source code.
+
+
+Also add it to the list of all languages below. Simply add the new
+language separated by a comma `,`.
+
+``` elm
+all : List UiLanguage
+all =
+    [ English
+    , German
+    ]
+```
+
+If you make a mistake, the elm compiler will tell you with usually
+quite helpful messages. Now, after adding this, there will be errors
+when compiling the elm files. You should see something like this:
+
+```
+Detected problems in 1 module.
+-- MISSING PATTERNS ------------------- modules/webapp/src/main/elm/Messages.elm
+
+This `case` does not have branches for all possibilities:
+
+45|>    case lang of
+46|>        English ->
+47|>            gb
+
+Missing possibilities include:
+
+    German
+
+I would have to crash if I saw one of those. Add branches for them!
+
+Hint: If you want to write the code for each branch later, use `Debug.todo` as a
+placeholder. Read <https://elm-lang.org/0.19.1/missing-patterns> for more
+guidance on this workflow.
+```
+
+So around line 45 in `Messages.elm` there is something wrong. This is
+the place where a record of all strings is returned given some
+lanugage. Currently, there is only one set of strings for English.
+Open this file, you see at the and a value of name `gb` for English.
+Copy it to another name, `de` for this example (it's good practice to
+stick to the two letter country code).
+
+``` elm
+de : Messages
+de =
+    { lang = German
+    , iso2 = "de"
+    , label = "Deutsch"
+    , flagIcon = "flag-icon flag-icon-de"
+    , app = Messages.App.gb
+    , collectiveSettings = Messages.Page.CollectiveSettings.gb
+    , login = Messages.Page.Login.gb
+    , register = Messages.Page.Register.gb
+    , newInvite = Messages.Page.NewInvite.gb
+    , upload = Messages.Page.Upload.gb
+    , itemDetail = Messages.Page.ItemDetail.gb
+    , queue = Messages.Page.Queue.gb
+    , userSettings = Messages.Page.UserSettings.gb
+    , manageData = Messages.Page.ManageData.gb
+    , home = Messages.Page.Home.gb
+    }
+```
+
+Change `lang`, `iso2`, `label` and `flagIcon` appropriately. For the
+`label` use the native language name (not English), as this is the
+label shown to users when selecting a language. The flag icon can be
+copied and only the last two letters need to be changed to the country
+code. You may look [here](https://github.com/lipis/flag-icon-css) for
+additional information.
+
+Now the error can be fixed. Go to line 45 and add another branch to
+the `case` expression:
+
+``` elm
+get : UiLanguage -> Messages
+get lang =
+    case lang of
+        English ->
+            gb
+
+        German ->
+            de
+```
+
+This makes the compiler happy again. If you refresh the browser, you
+should see the new language in the dropdown menu. You can already
+choose the new language, but nothing happens in the application. Of
+course, we just copied the English strings for now. So now begins the
+translation process.
+
+
+## Translating
+
+Now translation can begin. If you look at the newly created value
+`de`, you'll see some entries in the record. Each corresponds to a
+page: `login` is for the login page, `home` for the "home page" etc;
+and `app` is for the top menu.
+
+Take one of them and start translating. For the example, I use the
+first one which is `Messages.App`. The file to this is
+`Messages/App.em`. You can always replace the dots with slashes to
+find a file to an elm module. Open this file and you'll see again a
+`gb` value at the end. Copy it to `de` and start translating:
+
+``` elm
+de : Texts
+de =
+    { collectiveProfile = "Kollektiv-Profil"
+    , userProfile = "Benutzer-Profil"
+    , lightDark = "Hell/Dunkel"
+    , logout = "Abmelden"
+    , items = "Dokumente"
+    , manageData = "Daten verwalten"
+    , uploadFiles = "Dateien hochladen"
+    , processingQueue = "Verarbeitung"
+    , newInvites = "Neue Einladung"
+    , help = "Hilfe (English)"
+    }
+```
+
+Then go to the beginning of the file and add the new `de` value to the
+list of "exposed" values. This is necessary so it can be used from
+within the `Messages.elm` module.
+
+``` elm
+module Messages.App exposing
+    ( Texts
+    , de {- the new value -}
+    , gb
+    )
+```
+
+Now you can go back to `Messages.elm` and exchange `Messages.App.gb`
+with `Messages.App.de`.
+
+``` elm
+de : Messages
+de =
+    { lang = German
+    , iso2 = "de"
+    , label = "Deutsch"
+    , flagIcon = "flag-icon flag-icon-de"
+    , app = Messages.App.de
+    , collectiveSettings = Messages.Page.CollectiveSettings.gb
+    , login = Messages.Page.Login.gb
+    , register = Messages.Page.Register.gb
+    , newInvite = Messages.Page.NewInvite.gb
+    , upload = Messages.Page.Upload.gb
+    , itemDetail = Messages.Page.ItemDetail.gb
+    , queue = Messages.Page.Queue.gb
+    , userSettings = Messages.Page.UserSettings.gb
+    , manageData = Messages.Page.ManageData.gb
+    , home = Messages.Page.Home.gb
+    }
+```
+
+If you refresh the browser, you should now see the new values. Then
+take the next entry and start over. It happens that some files contain
+other string-sets of certain components. Then just follow this guide
+recursively.
+
+
+# Publishing
+
+You can publish your work to this repo in various ways:
+
+## Github PR
+
+This is the preferred way, because it means less work for me :). If
+you have a github account, you can create a pull request. Here is a
+quick walk-through. There is a thorough help [at
+github](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/proposing-changes-to-your-work-with-pull-requests).
+
+1. Fork this repository in the github webapp
+2. Go to the docspell source root you checked out in the terminal. Run:
+   ```
+   git remote rename origin upstream
+   git remote add origin git@github.com:<your-github-name>/docspell.git
+   git fetch --all
+   ```
+3. Create a new git branch:
+   ```
+   git checkout -b translate origin/master
+   ```
+4. Make a commit of your changes:
+   ```
+   git config user.name "Your Name"
+   git config user.email "Your Email" #(note that this email will be publicly viewable! a dummy address is fine, too)
+   git commit -am 'Add translation for German'
+   ```
+   Modify the message to your needs.
+5. Push the change to your fork:
+   ```
+   git push origin translate
+   ```
+6. Go to the github webapp and create a pull request from your branch.
+
+## E-Mail
+
+You can send me the patch via e-mail. You can use `git send-email` or
+your favorite e-mail client. For this do step 4 from above and then:
+
+```
+git bundle create translation.bundle origin/master..HEAD
+```
+
+Then send the created `translate.bundle` file. If this command doesn't
+work, try:
+
+```
+git format-patch origin/master..HEAD
+```
+
+This results in one or more `0001-…` files that you can send.
+
+## Any other
+
+Contact me by mail or create an issue.