diff --git a/.gitignore b/.gitignore
index b81336c6e1871b416a3179940a4b479765f9518b..130bd5618c304135a37e2adaba178dd573d1d0af 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ build/
 /swh/docs/sphinx/__pycache__/
 /version.txt
 apidoc/
+docs/README.*
diff --git a/docs/devel/bin/ln-sphinx-subprojects b/docs/devel/bin/ln-sphinx-subprojects
index edd5d6f38f2d7bb2fa61ba81c19e1c2bb1c41e11..512b04c163ab9686c90b9113ac41c0b31837e0f9 100755
--- a/docs/devel/bin/ln-sphinx-subprojects
+++ b/docs/devel/bin/ln-sphinx-subprojects
@@ -4,9 +4,9 @@ set -e
 create_links () {
     mkdir -p sources
     for pymodule in $(cd ../../../ && bin/ls-py-modules) ; do
-        if [ "$pymodule" = 'swh-docs' ] ; then
-            continue
-        fi
+        case "$pymodule" in
+            "swh-docs"|"swh-icinga-plugins") continue;;
+        esac
         if [ ! -e "$pymodule" -a -d "../../../${pymodule}/docs" ] ; then
             ln -s "../../../${pymodule}/docs" "$pymodule"
         fi
@@ -16,6 +16,14 @@ create_links () {
         if [ -d "../../../${pymodule}/swh" ] ; then
             cp -r -f --symbolic-link $(realpath ../../../${pymodule}/swh/*) sources/swh/
         fi
+        pushd ../../../${pymodule}
+        for EXT in rst md; do
+            if [ -f README.$EXT -a ! -f docs/README.$EXT ] ; then
+                ln -s ../README.$EXT docs
+                break
+            fi
+        done
+        popd
     done
 }
 
diff --git a/docs/index.rst b/docs/index.rst
index ac556989afdceeef2b8d411a62257071d9d3d4f0..af7ff6ff40d33a078d8f8232e8f767f19b653dcf 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -438,3 +438,4 @@ Table of contents
    devel/api-reference
    user/index
    sysadm/index
+   About this documentation project <README>
diff --git a/swh/docs/sphinx/conf.py b/swh/docs/sphinx/conf.py
old mode 100755
new mode 100644
index 0e7986473d9648e4b66bc6f6479ef32f5f4c0eb7..e14a26bff8c16f3aff4fcb7df1c9778cc17c9b85
--- a/swh/docs/sphinx/conf.py
+++ b/swh/docs/sphinx/conf.py
@@ -85,8 +85,7 @@ language = "en"
 # This patterns also effect to html_static_path and html_extra_path
 exclude_patterns = [
     "_build",
-    "**swh-icinga-plugins/index.rst",
-    "**swh.loader.cvs.rcsparse.setup.rst",
+    "**swh-icinga-plugins/*.rst",
     "**/swh/lister/maven/README.md",
     "**/swh/loader/cvs/cvs2gitdump/README.md",
     "**/swh/web/tests/resources/contents/code/extensions/test.md",
@@ -331,7 +330,27 @@ def get_sphinx_warning_handler():
             return handler
 
 
+# before starting building the doc, we want to ensure all the
+# swh-xxx/docs/README.{rst,md} exists, or create a symlink if not. This is only
+# useful when building the documentation of a sw package in isolation; when
+# building the whole swh-docs, then the docs/devel/bin/ln-sphinx-subprojects
+# will take care of these symlinks
+def ensure_readme(app, config):
+    srcpath = app.srcdir
+    if srcpath.name.endswith("swh.docs"):
+        # ln-sphinx-subprojects script should already have done the job
+        return
+    for extension in ("rst", "md"):
+        fname = f"README.{extension}"
+        readme_file = srcpath / ".." / fname
+        symlink = srcpath / fname
+        if readme_file.exists() and not symlink.exists():
+            symlink.symlink_to(readme_file)
+            break
+
+
 def setup(app):
+    app.connect("config-inited", ensure_readme)
     # env-purge-doc event is fired before source-read
     app.connect("env-purge-doc", set_django_settings)
     # add autosimple directive (used in swh-web)