diff --git a/README.md b/README.md
index 031b7ecf..2422fd94 100644
--- a/README.md
+++ b/README.md
@@ -1,31 +1,208 @@
-Libero Article Store
-====================
+[![Libero][Libero logo]][Libero]
+
+Article Store
+=============
-[](https://github.com/libero/article-store/actions?query=branch%3Amaster+workflow%3ACI)
+[![Build status][Build badge]][Build]
+[![Open issues][Open issues badge]][Open issues]
+[![Docker pulls][Docker pulls badge]][Docker image]
+[![License][License badge]][License]
+[![Slack][Slack badge]][Libero Community Slack]
-Implementation of a [Libero API](https://libero.pub/api).
+This app provides an HTTP API for creating, maintaining and reading articles.
-Requirements
+An article is an [RDF graph], where the root node is a [`http://schema.org/Article`][schema:Article]. We can encode an
+article in [JSON-LD]:
+
+```json
+{
+ "@context": "http://schema.org/",
+ "@id": "http://example.com/my-article-store/articles/1234567890",
+ "@type": "Article",
+ "name": "My article"
+}
+```
+
+The API uses the [Hydra vocabulary] as its [hypermedia format][HATEOAS]. It also follows the [Libero API specification].
+
+It's written in [TypeScript], uses the [Koa framework][Koa], and various [RDF/JS libraries][RDF/JS].
+
+The app persists articles in a [PostgreSQL] database.
+
+
+
+Further reading
+
+- [Libero API Specification]
+- [RDF 1.1 Primer]
+- [Hydra Core Vocabulary][Hydra vocabulary]
+- [RDF JavaScript Libraries][RDF/JS]
+ - [Data Model Specification][RDF/JS data model]
+ - [Dataset Specification][RDF/JS dataset]
+
+
+
+Table of contents
+-----------------
+
+1. [Installation](#installation)
+ 1. [Running an Article Store](#running-an-article-store)
+ 1. [Using the Docker CLI](#using-the-docker-cli)
+ 2. [Using Docker Compose](#using-docker-compose)
+ 2. [Configuration](#configuration)
+2. [Development](#development)
+ 1. [Running the app](#running-the-app)
+ 2. [Running the tests](#running-the-tests)
+ 3. [Linting](#linting)
+3. [Contributing](#contributing)
+4. [Getting help](#getting-help)
+5. [License](#license)
+
+Installation
------------
-- [Docker](https://www.docker.com/)
-- [GNU Bash](https://www.gnu.org/software/bash/)
-- [GNU Make](https://www.gnu.org/software/make/)
-- [Node.js](https://nodejs.org/) (for development)
+You can find the app on Docker Hub: [`liberoadmin/article-store`][Docker image].
-Running
--------
+As it is still under heavy development, there are not yet tagged releases. An image is available for every commit.
+
+### Running an Article Store
+
+#### Using the [Docker CLI]
+
+1. Start a PostgreSQL container by executing:
+
+ ```shell
+ docker run -d --name article-store-database \
+ -e "POSTGRES_DB=article-store" \
+ -e "POSTGRES_USER=user" \
+ postgres:11.5-alpine
+ ```
+
+2. Run the database creation with an ephemeral Article Store container:
+
+ ```shell
+ docker run --rm \
+ --link article-store-database \
+ -e "DATABASE_HOST=article-store-database" \
+ -e "DATABASE_NAME=article-store" \
+ -e "DATABASE_USER=user" \
+ liberoadmin/article-store:latest npm run initdb
+ ```
+
+3. Run an Article Store container and link it to the database container:
+
+ ```shell
+ docker run \
+ --link article-store-database \
+ -e "DATABASE_HOST=article-store-database" \
+ -e "DATABASE_NAME=article-store" \
+ -e "DATABASE_USER=user" \
+ -p 8080:8080 \
+ liberoadmin/article-store:latest
+ ```
+
+4. Access the Article Store entry point:
+
+ ```shell
+ curl --include http://localhost:8080/
+ ```
+
+#### Using [Docker Compose]
+
+1. Create a file called `docker-compose.yml`:
+
+ ```yaml
+ version: '3.4'
+
+ services:
+
+ db:
+ image: postgres:11.5-alpine
+ environment:
+ POSTGRES_DB: article-store
+ POSTGRES_USER: user
+
+ initdb:
+ image: liberoadmin/article-store:latest
+ command: >
+ /bin/sh -c '
+ while ! nc -z db 5432 ; do sleep 1 ; done
+ npm run initdb
+ '
+ environment:
+ DATABASE_HOST: db
+ DATABASE_NAME: article-store
+ DATABASE_USER: user
+
+ app:
+ image: liberoadmin/article-store:latest
+ environment:
+ DATABASE_HOST: db
+ DATABASE_NAME: article-store
+ DATABASE_USER: user
+ ports:
+ - '8080:8080'
+ ```
+
+2. Bring up the containers
+
+ ```shell
+ docker-compose up
+ ```
+
+3. Access the Article Store entry point:
+
+ ```shell
+ curl --include http://localhost:8080/
+ ```
+
+### Configuration
+
+The following environment variables can be set:
+
+#### `DATABASE_HOST`
+
+This variable is mandatory is the PostgreSQL hostname.
+
+#### `DATABASE_NAME`
+
+This variable is mandatory and is the name of the PostgreSQL database.
+
+#### `DATABASE_USER`
+
+This variable is mandatory and is the name of the PostgreSQL user.
+
+#### `DATABASE_PASSWORD`
+
+This variable is optional and is the password of the PostgreSQL user (default is blank).
+
+#### `DATABASE_PORT`
-To build and run the app, execute:
+This variable is optional and is the PostgreSQL port (default `5432`).
+
+Development
+-----------
+
+
+
+Requirements
+
+- [Docker]
+- [GNU Bash]
+- [GNU Make]
+- [Node.js]
+
+
+
+The project contains a [Makefile] which uses [Docker Compose] for development and testing.
+
+You can find the possible commands by executing:
```shell
-make prod
+make help
```
-You can now access the entry point at , or view the console at .
-
-Developing
-----------
+### Running the app
To build and run the app for development, execute:
@@ -35,9 +212,105 @@ make dev
You can now access the entry point at , or view the console at .
+
+
+Rebuilding the container
+
+Code is attached to the containers as volumes so most updates are visible without a need to rebuild the container.
+However, changes to NPM dependencies, for example, require a rebuild. So you may need to execute
+
+```shell
+make build
+```
+
+before running further commands.
+
+
+
+### Running the tests
+
+We use [Jest] to test the app. You can run it by executing:
+
+```shell
+make test
+```
+
+You can also run the tests in separate suites:
+
+```shell
+make unit-test
+make integration-test
+```
+
+Integration tests have a `@group integration` annotation, and can access a PostgreSQL instance.
+
+### Linting
+
+We lint the app with [ESLint]. You can run it by:
+
+```shell
+make lint
+```
+
+You can fix problems, where possible, by executing:
+
+```shell
+make fix
+```
+
+Contributing
+------------
+
+Pull requests and other contributions are more than welcome. Please take a look at the [contributing guidelines] for
+further details.
+
Getting help
------------
-- Report a bug or request a feature on [GitHub](https://github.com/libero/publisher/issues/new/choose).
-- Ask a question on the [Libero Community Slack](https://libero.pub/join-slack).
-- Read the [code of conduct](https://libero.pub/code-of-conduct).
+- Report a bug or request a feature on [GitHub][new issue].
+- Ask a question on the [Libero Community Slack].
+- Read the [code of conduct].
+
+License
+-------
+
+We released this software under the [MIT license][license]. Copyright © 2019 [eLife Sciences Publications, Ltd][eLife].
+
+[Build]: https://github.com/libero/article-store/actions?query=branch%3Amaster+workflow%3ACI
+[Build badge]: https://flat.badgen.net/github/checks/libero/article-store?label=build&icon=github
+[Contributing guidelines]: https://github.com/libero/community/blob/master/CONTRIBUTING.md
+[Docker]: https://www.docker.com/
+[Docker CLI]: https://docs.docker.com/engine/reference/commandline/cli/
+[Docker Compose]: https://docs.docker.com/compose/
+[Docker image]: https://hub.docker.com/r/liberoadmin/article-store
+[Docker pulls badge]: https://flat.badgen.net/docker/pulls/liberoadmin/article-store?icon=docker
+[eLife]: https://elifesciences.org/
+[ESLint]: https://eslint.org/
+[Code of conduct]: https://libero.pub/code-of-conduct
+[GNU Bash]: https://www.gnu.org/software/bash/
+[GNU Make]: https://www.gnu.org/software/make/
+[HATEOAS]: https://en.wikipedia.org/wiki/HATEOAS
+[Hydra vocabulary]: https://www.hydra-cg.com/spec/latest/core/
+[Jest]: https://jestjs.io/
+[JSON-LD]: https://json-ld.org/
+[Koa]: https://koajs.com/
+[Libero]: https://libero.pub/
+[Libero API Specification]: https://libero.pub/api
+[Libero Community Slack]: https://libero.pub/join-slack
+[Libero logo]: https://cdn.elifesciences.org/libero/logo/libero-logo-96px.svg
+[License]: LICENSE.md
+[License badge]: https://flat.badgen.net/badge/license/MIT/blue
+[Makefile]: Makefile
+[New issue]: https://github.com/libero/publisher/issues/new/choose
+[Node.js]: https://nodejs.org/
+[Open issues]: https://github.com/libero/publisher/issues?q=is%3Aissue+is%3Aopen+label%3Aarticle-store
+[Open issues badge]: https://flat.badgen.net/github/label-issues/libero/publisher/article-store/open?icon=github&label=open%20issues&color=pink
+[PostgreSQL]: https://www.postgresql.org/
+[RDF 1.1 Primer]: https://www.w3.org/TR/rdf11-primer/
+[RDF graph]: https://www.w3.org/TR/rdf11-concepts/#section-rdf-graph
+[RDF/JS]: https://rdf.js.org/
+[RDF/JS data model]: https://rdf.js.org/data-model-spec/
+[RDF/JS dataset]: https://rdf.js.org/dataset-spec/
+[schema:Article]: https://schema.org/Article
+[Slack badge]: https://flat.badgen.net/badge/icon/libero-community?icon=slack&label=slack&color=orange
+[TypeScript]: https://www.typescriptlang.org/