diff --git a/conf.py b/conf.py
index 0b3852f69bbcade9e7cd8f92d2a027caecb44812..947c95f6aa0553577730e923ee17ebd6d93f5b74 100644
--- a/conf.py
+++ b/conf.py
@@ -28,6 +28,7 @@ extensions = [
 ]
 
 myst_enable_extensions = ['dollarmath']
+myst_heading_anchors = 5
 
 # In addition to the ```{mermaid} directive, allow the ```mermaid directive
 myst_fence_as_directive = ["mermaid"]
diff --git a/contribute/index.md b/contribute/index.md
index 321c655d6d0616e926fda16f34f067dcfc81006e..2b5af38d66345f5685f1e90ff01a30f6e25fba9d 100644
--- a/contribute/index.md
+++ b/contribute/index.md
@@ -11,7 +11,7 @@ Please see below for how to get started contributing to Jami!
 
 ## Reporting bugs and issues
 
-Please see the [Bug report guide](user/bug-report-guide.md) for step-by-step instructions on how to report any issue you may encounter with Jami.
+Please see the [Bug report guide](/user/bug-report-guide.md) for step-by-step instructions on how to report any issue you may encounter with Jami.
 
 ## Contributing code
 
@@ -26,7 +26,7 @@ This will enable the developers to guide you through the process.
 A push with a patch to <https://review.jami.net> will be required to integrate the code to Jami.
 
 ```{seealso}
-For more information on how to push a patch, please refer to the [Working with Gerrit](developer/new-developers/working-with-gerrit.md) guide.
+For more information on how to push a patch, please refer to the [Working with Gerrit](/developer/new-developers/working-with-gerrit.md) guide.
 ```
 
 ## Commit message guidelines
@@ -242,7 +242,7 @@ $ git add source/file/you/edited.md
 $ git commit
 ```
 
-Refer to the [commit message guidelines](contribute.md#commit-message-guidelines) for how to write a good commit message.
+Refer to the [commit message guidelines](#commit-message-guidelines) for how to write a good commit message.
 
 ## Submitting a change
 
diff --git a/developer/jami-concepts/account-management.md b/developer/jami-concepts/account-management.md
index 6c288d5ffb669167e627807e2e3ef7c7fd736bea..0522ffead2a2ae130ce57b8e795f48404efcfbaf 100644
--- a/developer/jami-concepts/account-management.md
+++ b/developer/jami-concepts/account-management.md
@@ -15,11 +15,10 @@ This structure allows a company to revoke an entire account if necessary, and en
 
 ## Creating a New Account
 
-### Daemon-side API
+### New account—daemon API
 
 The ConfigurationManager API (cx.ring.Ring.ConfigurationManager) provides the `addAccount` method:
 
-
 ```xml
 <method name="addAccount" tp:name-for-bindings="addAccount">
     <tp:docstring>
@@ -40,9 +39,8 @@ The ConfigurationManager API (cx.ring.Ring.ConfigurationManager) provides the `a
     </arg>
 </method>
 ```
-By default, you can retrieve template parameters using `getAccountTemplate(type)` with `type="JAMI"` or `type="SIP"`.
 
-### Core Implementation
+### New account—core implementation
 
 The core logic for account creation resides in `src/account_factory.cpp`, within the `AccountFactory::createAccount` method.
 
@@ -73,7 +71,7 @@ AccountFactory::createAccount(std::string_view accountType, const std::string& i
 
 After calling `addAccount` (or `createAccount` via the AccountFactory), the `accountsChanged` signal is emitted. Clients should handle this signal and invoke `getAccountList` to update their local state.
 
-### Internal Archive Format
+### Internal archive format
 
 When an account is created, its data is stored in a gzip archive. If a password is provided, the archive is encrypted with AES: `dht::crypto::aesEncrypt(archive, password)` (`dht::crypto::aesEncrypt` is defined in OpenDHT and use `nettle/{aes,gcm}`). Inside the archive, you will find a JSON file containing:
 
@@ -83,12 +81,11 @@ When an account is created, its data is stored in a gzip archive. If a password
 5. The contact list.
 6. The account settings
 
+## Deleting an account
 
-## Deleting an Account
-
-Deleting a Jami account is straightforward: since all key material resides on the local device, removing those key files effectively deletes the account. The only external record is the account’s username on the nameserver, which may persist depending on the server’s policies (for example, `https://ns.jami.net` does not currently support remote name deletion).
+Deleting a Jami account is straightforward: since all key material resides on the local device, removing those key files effectively deletes the account. The only external record is the account’s username on the name server, which may persist depending on the server’s policies (for example, `https://ns.jami.net` does not currently support remote name deletion).
 
-### Daemon-side API
+### Delete account—daemon API
 
 The ConfigurationManager API provides the `removeAccount` method:
 
@@ -108,7 +105,7 @@ The ConfigurationManager API provides the `removeAccount` method:
 When the account is deleted, the signal `accountsChanged` will be emitted. The client should update its internal structure after this signal with other methods in ConfigurationManager.
 
 
-#### Core Implementation
+### Delete account—core implementation
 
 The core removal logic is in `src/accout_factory.cpp` (`AccountFactory::removeAccount`), which deletes the account files and updates the `dring.yml` configuration.
 
@@ -129,7 +126,7 @@ AccountFactory::removeAccount(Account& account)
 ```
 ## Updating the details of an account
 
-### Daemon-side API
+### Update account—daemon API
 
 The ConfigurationManager API provides the `setAccountDetails` method:
 
diff --git a/developer/jami-concepts/calls-in-swarm.md b/developer/jami-concepts/calls-in-swarm.md
index 2a513a871f95290c8161d365ac985d3d6374c8c9..0bd4727c874427b83eef48192d227bf898e50040 100644
--- a/developer/jami-concepts/calls-in-swarm.md
+++ b/developer/jami-concepts/calls-in-swarm.md
@@ -1,5 +1,4 @@
-Calls in Swarm
-==============
+# Calls in Swarm
 
 ## Goals
 
diff --git a/developer/jami-concepts/conference-protocol.md b/developer/jami-concepts/conference-protocol.md
index 24e8ba8417ab5afd970c2423e185c3841c7f4190..f4f457a89085476ac72e9f8ea99f9dea74c588d7 100644
--- a/developer/jami-concepts/conference-protocol.md
+++ b/developer/jami-concepts/conference-protocol.md
@@ -35,11 +35,8 @@ void setConferenceLayout(const std::string& confId, int layout);
 void setActiveParticipant(const std::string& confId, const std::string& participantId);
 ```
 
-### Implementation
-
 The implementation is pretty straightforward. Everything is managed by `conference.cpp` (to link participant to sources) and `video_mixer.cpp` (to render the wanted layout).
 
-
 ## Syncing Conferences Informations
 
 Note: Actually, the word participant is used for callId mixed in a conference. This can lead at first to some problems for the API and must be fixed in the future
@@ -92,7 +89,6 @@ VectorMapStringString getConferenceInfos(const std::string& confId);
 void onConferenceInfosUpdated(const std::string& confId, const VectorMapStringString& infos);
 ```
 
-### Implementation
 
 The `Conference` Object (which only exists if we mix calls, this means that we are the master) manages the information for the whole conference, based on the LayoutInfos of each `Call` object. The getConferenceInfos will retrieve info directly from this object.
 
@@ -141,28 +137,28 @@ For now, there is no action supported, however, in the future `moderator: true/f
 
 ### Example
 
-So, the `application/confOrder+json` will contains:
+So, the `application/confOrder+json` will contain:
 
 ```json
 {
     "989587609427420" : {
-        "moderator": true/false,
+        "moderator": true, /* false  */
         "devices": {
             "40940943604396R64363": {
                 "hangup": true,
-                "raisehand": true/false,
+                "raisehand": true, /* false */
                 "media":{
                     "3532532662432" : {
-                        "muteAudio": true/false,
-                        "muteVideo": true/false,
-                        "active": true/false,
-                        "voiceActivity": true/false
+                        "muteAudio": true, /* false */
+                        "muteVideo": true, /* false */
+                        "active": true, /* false */
+                        "voiceActivity": true /* false */
                     }
                 }
             }
         }
     },
-    "layout": 0/1/2,
+    "layout": 0, /* 1, 2 */
 }
 ```
 
diff --git a/developer/jami-concepts/jami-identifiers.md b/developer/jami-concepts/jami-identifiers.md
index 4b6689fb088a6708b0b9bd347e2ce02a309a0add..f5e4faa00ce45e73cd6b3dbfd147aed9a9f02361 100644
--- a/developer/jami-concepts/jami-identifiers.md
+++ b/developer/jami-concepts/jami-identifiers.md
@@ -1,5 +1,4 @@
-Jami identifiers
-----------------
+# Jami identifiers
 
 There are many identifiers in Jami. We need to unify the naming of these
 identifiers between all implementations. This page reference various kind of
diff --git a/developer/jami-concepts/name-server-protocol.md b/developer/jami-concepts/name-server-protocol.md
index ad4ae4d3c45366185993ef57e45799317b408e43..f231c04a850f06a05efff51aa0d10533056ec59d 100644
--- a/developer/jami-concepts/name-server-protocol.md
+++ b/developer/jami-concepts/name-server-protocol.md
@@ -6,14 +6,13 @@ HTTP
 API answering requests with JSON documents and regular HTTP status
 codes.
 
-The public nameserver is hosted at `ns.jami.net` and uses a blockchain
-as its backend.  Another implementation could use any other database
-or directory service making the nameserver protocol reusable.
+The public name server is hosted at `ns.jami.net`. Another implementation could use any other database
+or directory service making the name server protocol reusable.
 
-If you run your own nameserver, looking up a username in the form of
+If you run your own name server, looking up a username in the form of
 `username@example.com` will look up the name `username` with the
-nameserver at `example.com`.  (There is no need to add `@ns.jami.net`
-to use the default nameserver.)
+name server at `example.com` (there is no need to add `@ns.jami.net`
+to use the default name server).
 
 ## Rules on name formatting
 
@@ -29,19 +28,18 @@ format:
 This is the main service provided by a name server.  It enables
 getting the Jami ID corresponding to a username.
 
-### Request
+### Request name
 
-A request for the name `foobar` is a `GET` request with
-`/name/`*`foobar`* as the URI.
+A request for the name `foobar` is a `GET` request with `/name/foobar`* as the URI.
 
-### Response (Success)
+### Response name (Success)
 
-If the name is found, a response with status code `200` `OK` must be
+If the name is found, a response with status code `200 OK` must be
 sent to the client with a `Content-type` field set as
 `application/json`.
 
 The body is a JSON documents with 2 string attributes : `name` and
-`addr`.  `name` is equal to the one requested and `addr` is an
+`addr`. `name` is equal to the one requested and `addr` is a
 hexadecimal representation of the Jami ID prefixed with `0x`.
 
 In our example, the JSON answer would be:
@@ -53,10 +51,9 @@ In our example, the JSON answer would be:
 }
 ```
 
-### Response (Not found)
+### Response name (Not found)
 
-If the name is not found, a response with status code `404` `Not`
-`Found` must be sent to the client with a `Content-type` field set as
+If the name is not found, a response with status code `404 Not Found` must be sent to the client with a `Content-type` field set as
 `application/json`.
 
 The body is a JSON documents with 1 string attribute : `error`.  This
@@ -76,16 +73,16 @@ On the reference implementation, the returned document is:
 This service is a reverse lookup.  You query for an address and a
 username is returned if one is registered on the name server.
 
-### Request
+### Request address
 
 A request for the ID `jami:29347542eb07159f316577e1ae16243d152f6b7b`
 is a `GET` request with
-`/addr/`*`29347542eb07159f316577e1ae16243d152f6b7b`* as the URI.
+`/addr/29347542eb07159f316577e1ae16243d152f6b7b` as the URI.
 
-### Response (Success)
+### Response address (Success)
 
 If the address corresponds to a username, a response with status code
-`200` `OK` must be sent to the client with a `Content-type` field set
+`200 OK` must be sent to the client with a `Content-type` field set
 as `application/json`.
 
 The body is a JSON documents with 1 string attribute : `name`.  The
@@ -99,10 +96,9 @@ In our example, the JSON answer would be:
 }
 ```
 
-### Response (Not found)
+### Response address (Not found)
 
-If the address is not found, a response with status code `404` `Not`
-`Found` must be sent to the client with a `Content-type` field set as
+If the address is not found, a response with status code `404 Not Found` must be sent to the client with a `Content-type` field set as
 `application/json`.
 
 The body is a JSON documents with 1 string attribute : `error`.  This
@@ -123,7 +119,7 @@ This part of the protocol is used to register a new name/address pair.
 It is used on the main public registry but may be optional in a custom
 implementation.
 
-### Request
+### Request register
 
 A request for registering the name `foobar` is a `POST` request with
 `/name/`*`foobar`* as the URI. The header attribute `Content-type` must
@@ -142,10 +138,10 @@ An example for `foobar` could be:
 }
 ```
 
-### Response (Success)
+### Response register (Success)
 
 If the name/address pair is successfully registered, a response with
-status code `200` `OK` must be sent to the client with a `Content-type`
+status code `200 OK` must be sent to the client with a `Content-type`
 field set as `application/json`.
 
 The body contain a JSON document with 1 boolean attribute `success` set
@@ -162,11 +158,11 @@ As an example:
 Further attempts to query the name or the address should then be
 successful.
 
-### Response (Bad request)
+### Response register (Bad request)
 
 If the registration cannot be achieved because of an error in the
 request (formatting, missing attribute, etc.), a response with status
-code `400` `Bad` `Request` must be sent to the client with a
+code `400 Bad Request` must be sent to the client with a
 `Content-type` field set as `application/json`.
 
 The body is a JSON documents with 2 attributes: `success` which is a
@@ -183,10 +179,10 @@ For an invalid formatting of the username, the body could be:
 }
 ```
 
-### Response (Forbidden)
+### Response register (Forbidden)
 
 If the registration cannot be achieved because the name is already
-taken, a response with status code `403` `Forbidden` must be sent to
+taken, a response with status code `403 Forbidden` must be sent to
 the client with a `Content-type` field set as `application/json`.
 
 The body is a JSON documents with 3 attributes: `success` which is a
diff --git a/developer/jami-concepts/swarm.md b/developer/jami-concepts/swarm.md
index 5e199c8c300b01cd0f79da292ed6ea1c2e3b8f65..ac33f209960f12ca2dfc96dde75fa1ea176f5669 100644
--- a/developer/jami-concepts/swarm.md
+++ b/developer/jami-concepts/swarm.md
@@ -726,13 +726,13 @@ Group chat can be based on the same work we already have for multi-devices (but
 
 Like a DHT with a superuser. (Not convinced)
 
-## File transfer
+## What's next for file transfers
 
-Currently, the file transfer algorithm is based on a TURN connection (See {doc}`file-transfer`). In the case of a big group, this will be bad. We first need a p2p implement for the file transfer. Implement the RFC for p2p transfer.
+Currently, the file transfer algorithm is based on a TURN connection (See {doc}`file-transfer`). In the case of a big group, this will be bad. We first need a [P2P connection](https://wikipedia.org/wiki/Peer-to-peer) for the file transfer. Implement the RFC for P2P transfer.
 
-Other problem: currently there is no implementation for TCP support for ICE in PJSIP. This is mandatory for this point (in PJSIP or homemade)
+Other problem: currently there is no implementation for TCP support for ICE in PJSIP. This is mandatory for this point (in [PJSIP](https://www.pjsip.org/) or homemade)
 
 ## Resources
 
 + <https://eprint.iacr.org/2017/666.pdf>
-+ Robust distributed synchronization of networked linear systems with intermittent information (Sean Phillips and Ricardo G.Sanfelice)
++ [Robust distributed synchronization of networked linear systems with intermittent information (Sean Phillips and Ricardo G.Sanfelice)](https://www.sciencedirect.com/science/article/abs/pii/S0005109819301414)
diff --git a/developer/jami-concepts/synchronization-protocol.md b/developer/jami-concepts/synchronization-protocol.md
index 38444d6e07837e4e931ad4eeffd54843b156fed1..778af3ae0de9459b12e053b01ab4ad3b1ee666ca 100644
--- a/developer/jami-concepts/synchronization-protocol.md
+++ b/developer/jami-concepts/synchronization-protocol.md
@@ -46,14 +46,18 @@ This value is a JSON containing:
 {
     "contacts": [/* Contacts (TODO) */],
     "conversation": [
-        { "id":"convID", "created":TIMESTAMP, "removed":OPTIONAL_TIMESTAMP },
-        { "id":"convID2", "created":TIMESTAMP2, "removed":OPTIONAL_TIMESTAMP2 } /* ... */
+        { "id":"convID", "created":"<TIMESTAMP>", "removed":"<OPTIONAL_TIMESTAMP>" },
+        { "id":"convID2", "created":"<TIMESTAMP2>", "removed":"<OPTIONAL_TIMESTAMP2>" }
+        /* ... */
     ],
+
     "conversationsRequests": [
-        { "id":"convID", "received":TIMESTAMP, "declined":OPTIONAL_TIMESTAMP,
-          "members":[], "metadatas:[] },
-        { "id":"convID2", "received":TIMESTAMP2, "declined":OPTIONAL_TIMESTAMP2
-          "members":[], "metadatas:[] } /* ... */
+
+        { "id":"convID", "received":"<TIMESTAMP>", "declined":"<OPTIONAL_TIMESTAMP>",
+          "members":[], "metadatas":[] },
+        { "id":"convID2", "received":"<TIMESTAMP2>", "declined":"<OPTIONAL_TIMESTAMP2>",
+          "members":[], "metadatas":[] }
+        /* ... */
     ],
 }
 ```
diff --git a/developer/jami-concepts/synchronizing-profiles.md b/developer/jami-concepts/synchronizing-profiles.md
index f8dff2978d629ba0d5a90e8392247df90cf83954..174e682aa7571fb3b227768863ec5db3cfe194eb 100644
--- a/developer/jami-concepts/synchronizing-profiles.md
+++ b/developer/jami-concepts/synchronizing-profiles.md
@@ -26,15 +26,8 @@ However, this method should be removed in favor of the other located in the daem
 
 ### Send to contact's devices
 
-When connecting to a new device, a SIP or a sync channel is done.
-When this channel is ready, we check if we need to send the profile.
-To do this, the hash of the profile is compared to the one in the cache (`${cacheDir}/${accId}/vcard/sha3` like `~/.cache/jami/xxxxx/vcard/sha3` on GNU/Linux), and the `${cacheDir}/${accId}/vcard/deviceId` file is checked.
-Cf. `JamiAccount::needToSendProfile()`.
-If not present, the profile of the account is sent.
-Typically, the name of the channel will be "vcard://xxx" where the issuer is the one sending the profile.
+When connecting to new devices, a SIP or a sync channel is opened. When this channel is ready, we check if we need to send the profile. To do this, the hash of the profile is compared to the one in the cache (`${cacheDir}/${accId}/vcard/sha3` like `~/.cache/jami/xxxxx/vcard/sha3`on GNU/Linux, and the file `${cacheDir}/${accId}/vcard/deviceId` is checked). cf. `JamiAccount::needToSendProfile()`. If not present, the profile of the account is sent. Typically, the name of the channel will be `vcard://xxx` where the issuer is the one sending the profile.
 
 ### Multiple devices
 
-If the profile is sent and the device is from the same account, conversations are checked, and we send profiles of all members.
-The channel name will be "${conversationId}/profile/${memberUri}.vcf".
-Behavior tested in `daemon/test/unitTest/syncHistory/syncHistory.cpp`.
+If the profile is sent and the device is from the same account, conversations are checked and we send profiles of all members. The channel name will be `${conversationId}/profile/${memberUri}.vcf`. Behavior tested in `daemon/test/unitTest/syncHistory/syncHistory.cpp`
diff --git a/developer/new-developers/debugging-tools.md b/developer/new-developers/debugging-tools.md
index 45c342867b5a9723b43e988429b625b5b913b9cc..4f728e18525450d7dce3eccd3ef73a473a021535 100644
--- a/developer/new-developers/debugging-tools.md
+++ b/developer/new-developers/debugging-tools.md
@@ -47,12 +47,6 @@ Other flags like `tsan` may be useful.
 `valgrind --tool=callgrind ./jami -d`.
 This will make the application very slow but can provide useful reports about memory allocation/performance usage (**KCacheGrind** can be used to read reports).
 
-## Tests
-
-Daemon has many tests and coverage enabled.
-If the daemon is built in static (else private symbols will not be available), adding new tests can help to reproduce bugs, solve bugs, and avoid any regression.
-(cf. `daemon/tests/unitTests`)
-
 ## Agent
 
 Tests are only using one daemon to simulate both peers.
@@ -67,6 +61,7 @@ The advantage of [LTTng](https://lttng.org/) is that it is quicker than logs, ca
 
 ## Tests
 
-Both clients and daemon have tests.
+Both clients and daemon have tests. Coverage is enabled.
 Daemon's tests are written in C++ and use the `cppunit` framework.
-They are located in the `daemon/tests` directory.
\ No newline at end of file
+They are located in the `daemon/tests` directory.
+If the daemon is statically built (else the private symbols will be unavailable), adding new tests can help to reproduce bugs, solve bugs, and avoid any regression.
\ No newline at end of file
diff --git a/developer/new-developers/qt-qml-testing-tools.md b/developer/new-developers/qt-qml-testing-tools.md
index 82377e3cc320466e66e02ca515de24bb4017f1b0..a8180c56846947b49bcf1d196a682b5cb9796b8f 100644
--- a/developer/new-developers/qt-qml-testing-tools.md
+++ b/developer/new-developers/qt-qml-testing-tools.md
@@ -1,6 +1,6 @@
 # Qt and QML testing tools
 
-## QML
+## QML tests
 
 qml_tests launch all the tests related to the interface.
 The daemon and libclient SHOULD be trusted in this part; hence, connectivity test scenarios are not required.
@@ -58,7 +58,7 @@ The best way is to add this data to a variable or to a separate js file
 (cf. <https://doc.qt.io/qt-6/qtqml-documents-networktransparency.html>).
 An example of using the data in a test:
 
-```qml
+```cpp
 TestWrapper {
     AccountComboBoxPopup {
         id: uut
@@ -83,18 +83,18 @@ TestWrapper {
 }
 ```
 
-## C++
+## Tests
 
 ### GoogleTest
 
 [GoogleTest](https://google.github.io/googletest/) is Google’s C++ testing and mocking framework.
 
-#### Installation
+#### GoogleTest installation
 - Ubuntu / Debian:
 `apt install googletest libgtest-dev`
 
-### Example main.cpp
-```
+Example main.cpp
+```cpp
 #include <gtest/gtest.h>
 
 TEST(Test, Test1)
@@ -112,15 +112,16 @@ int main(int argc, char *argv[])
 }
 ```
 
-## QML
-
 ### QtQuickTest
 
-#### Installation
+QtQuickTest integrates QML testing.
+
+#### QtQuickTest installation
+
 - Ubuntu / Debian: `apt install qml-module-qqtest libqt5quicktest5`
 
-- Example main.cpp
-```
+Example main.cpp:
+```cpp
 #include <QtQuickTest/quicktest.h>
 #include <QQmlEngine>
 
diff --git a/developer/new-developers/submitting-your-first-patch.md b/developer/new-developers/submitting-your-first-patch.md
index 3cec65a118020e6269acc73808a58cb38a48185e..a15c497a8328d8373323e33d0f421353e3ce5a7d 100644
--- a/developer/new-developers/submitting-your-first-patch.md
+++ b/developer/new-developers/submitting-your-first-patch.md
@@ -5,7 +5,7 @@ Set up Git and SSH to work smoothly with Gerrit.
 First see [Creating a gerrit review](working-with-gerrit).
 ```
 
-### SSH setup
+## SSH setup
 
 <https://review.jami.net/Documentation/user-upload.html#ssh>
 
@@ -23,7 +23,7 @@ Your public key has been saved in `jami_gerrit_review.pub`.
 3. Set up your local SSH (via `ssh-add` or in `~/.ssh/config`).
 4. Test all of the above (SSH on the service or just try to clone a repo on Gerrit via SSH).
 
-### Your repository
+## Your repository
 
 ```{important}
 This *assumes* you have moved any existing project clone out of the way.
diff --git a/developer/processes/release-process.md b/developer/processes/release-process.md
index 89508369bb604f8406956d7082b00feff4a7a939..55aaefd95407d2c3028e57dcb5260e746137ed37 100644
--- a/developer/processes/release-process.md
+++ b/developer/processes/release-process.md
@@ -1,5 +1,4 @@
-Release process
-===============
+# Release process
 
 Each Jami sub-project has its own repository, build process, integration
 cycle and so on. More over the **Jami architecture is split into two
@@ -23,20 +22,14 @@ Redmine Ticket |Repository Preparation |Testing |Push tags |Packaging | Advertis
 
 ------------------------------------------------------------------------
 
-Redmine Ticket
---------------
+## Redmine Ticket
 
 Create a new Task on redmine attached to the release story, for the
 right sub-module. Set the title to "Release Major.Minor.Micro", with the
 appropriate version number.
 
-Repository Preparation
-----------------------
 
-**This section was outdated and removed**
-
-Testing
--------
+## Testing
 
 * Remove any existing Jami installations from your machine.
 * Start with clean git tree by running `git clean -d -f -x` from the top
@@ -51,12 +44,6 @@ Linphone), as well as hardware VoIP phones.
     * To catch uninitialized values being used, memory leaks, invalid frees,
 etc. run `valgrind --track-origins=yes --db-attach=yes ./bin/dring`
 
-Push tags
---------
-
-`git push --tags`
-
-Packaging
----------
+## Push tags
 
-cf [This page](/contribute#Packaging)
\ No newline at end of file
+`git push --tags`
\ No newline at end of file
diff --git a/extension/creating-jami-extensions.md b/extension/creating-jami-extensions.md
index 697198697d7eca5ba71de1cfd07cb6073fe0ea67..922bca8abd3006393ba55f6bbff72ce181445e80 100644
--- a/extension/creating-jami-extensions.md
+++ b/extension/creating-jami-extensions.md
@@ -5,6 +5,7 @@ This page introduces the Jami Plugin SDK.
 ```
 
 ## Jami extensions
+
 In September 2020, the Jami team added extensions as a call feature for GNU/Linux, Windows, macOS, and Android users.
 This enables personalized call and chat experiences by using available extensions.
 Additionally, anyone is also able to transform awesome ideas into brand new Jami extensions!
@@ -15,11 +16,10 @@ The text is organized as:
 * An example of how to create a base extension with the Jami Plugin SDK - [#Create my first extension](#create-my-first-extension).
 
 ### SDK
-An Extension System for Jami was developed and there are extensions available to be used.
-However as an open-source project, it allows users to create, use, and distribute their own extensions.
-To achieve that goal, a Jami Plugin SDK was also developed.
-This kit is written in Python, and can be invoked running [pluginMainSDK.py]('') from `<plugins>` folder.
-Requirement to get started:
+
+Jami has an extension system. There are many [Jami extensions available](/setup/index.md#jami-extensions).
+A Jami Plugin SDK is available. It is written in Python and can be invoked by running the `pluginMainSDK.py` script file from the `<plugins>` folder.
+Requirements to get started:
 
 ```bash
 git clone https://review.jami.net/jami-plugins plugins
@@ -32,8 +32,8 @@ python3 SDK/pluginMainSDK.py
 Notice that this script will generate a Jami Plugin SDK shell that allows users to:
 
 * [Create full extension skeleton](#create-full-extension-skeleton);
-* [Create, modify or delete a manifest.json](#create-modify-or-delete-manifest-json);
-* [Create a package.json](#create-a-package-json);
+* [Managing the manifest](#managing-the-manifest);
+* [Create a package.json](#create-a-packagejson);
 * [Create or delete a preference](#create-or-delete-a-preference);
 * [Create functionality](#create-functionality);
 * [Create main](#create-main);
@@ -45,6 +45,7 @@ Each one of these functionalities will be detailed next.
 The importance of the files it generates is explained and any related SDK limitations.
 
 #### Create full extension skeleton
+
 This option performs a sequence of actions to properly create all base files needed to start an extension development.
 The steps are:
 
@@ -74,7 +75,8 @@ To fully create a basic extension with pre-implementation of desired functionali
 
 The SDK will ask other information needed to correctly accomplish the task.
 
-#### Create, modify or delete manifest.json
+#### Managing the manifest
+
 Every extension must have a manifest.
 This file contains the official name, a description, and carries the extension build version as in the example below.
 Without it, the Extension System is unable to find the extension library it should load.
@@ -96,6 +98,7 @@ To create/modify (or to delete) a manifest.json, from inside Jami Plugin SDK she
 The SDK will ask other information needed to correctly accomplish the task.
 
 #### Create a package.json
+
 Jami currently supports extensions for GNU/Linux, macOS, Windows, and Android.
 For Windows, the build system used is the same as for Jami, it is, the extension build is called using a Python script.
 This script will look for a `package.json` file to acquire build information and commands.
@@ -148,6 +151,7 @@ To create a package.json, from inside the Jami Plugin SDK shell, the user must c
 The SDK will ask other information needed to correctly accomplish the task. After the base package.json creation, the user must add or modify any information not previewed by the SDK process.
 
 #### Create or delete a preference
+
 A preference is a internal variable that will be used upon loading or while running the extension.
 There is limited types of preferences supported by the Extension System and each of them must contain generic and specific information. Those information must be placed under a certain structure that will form one preference and each preference must be listed inside a `preference.json` file.
 
@@ -194,6 +198,7 @@ If a preference is created from outside a functionality creation pipeline, any A
 Thus, if value changes are allowed at runtime, functionality implementation may require manual modification to satisfy runtime change conditions.
 
 #### Create functionality
+
 A Jami extension may wrap one or multiple functionalities.
 It is, the same extension may have a functionality to change background and to draw a circle to a video for example.
 Each functionality must implement an abstract API class defined by the Jami Extension System.
@@ -212,6 +217,7 @@ To create a functionality, from inside the Jami Plugin SDK shell, the user must
 The SDK will ask other information needed to correctly accomplish the task.
 
 #### Create main
+
 This option creates `main.cpp` for the extension.
 A file that implements the extension external loading function that the Jami Extension System will call to initialize and register all functionalities for latter use.
 
@@ -226,6 +232,7 @@ To create a `main.cpp`, from inside the Jami Plugin SDK shell, the user must cal
 The SDK will ask other information needed to correctly accomplish the task.
 
 #### Assemble files
+
 The final extension file is an archive compressed to a `JPL` (Jami PLugin) format.
 This archive contains libraries, manifest.json, preferences.json, icons and other custom important files for the extension.
 OBS.: files added by the developer must be organized under the `data/` folder.
@@ -252,6 +259,7 @@ To compress all assembled to a jpl archive, from inside the Jami Plugin SDK shel
 The SDK will ask other information needed to correctly accomplish the task.
 
 #### Build
+
 The SDK build option has two different behaviors:
 
 * it creates basic CMakeLists.txt file;
@@ -274,6 +282,7 @@ For the moment, the build option does not support cross-compilation neither non
 If build variables are set differently to the default option, please directly use the `<plugins>/build-plugin.py` script.
 
 ##### CMakeLists.txt
+
 This file is used in every Jami build pipeline, i.e. GNU/Linux, macOS, Windows, and Android.
 Extensions are unavailable on iOS due to the Apple App Store security policy.
 
@@ -288,13 +297,14 @@ For POST_BUILD, it must copy the built library to the build folder and call the
 In the end, the jpl archive will be located in `<plugins>/build`.
 The CMakeLists.txt file automatically created by the Jami Plugin SDK, already respects these constraints.
 
-#### Merge jpl files
-If there is more than one jpl archive, like one build for Android and another for GNU/Linux platforms, they can be merged into one to ease its distribution.
-However, it is important to note that merging two or more jpl files may overwrite some of the files inside them if they are not equal for all archives.
+#### Merge JPL files
+
+If there is more than one JPL file, like one build for Android and another for GNU/Linux platforms, they can be merged into one to ease its distribution.
+However, it is important to note that merging two or more JPL files may overwrite some of the files inside them if they are not equal for all archives.
 The only files that may not present conflicting contents are the ones that do not repeat themselves.
-If conflicts occur, files from the first jpl in the arguments will prevail over the others.
+If conflicts occur, files from the first JPL in the arguments will prevail over the others.
 
-To merge two or more jpl files, from inside the Jami Plugin SDK shell, the user must simple call:
+To merge two or more JPL files, from inside the Jami Plugin SDK shell, the developer must call:
 ```
 (Jami Plugin SDK) merge
 ```
@@ -302,6 +312,7 @@ To merge two or more jpl files, from inside the Jami Plugin SDK shell, the user
 The SDK will ask other information needed to correctly accomplish the task.
 
 ### Create my first extension
+
 Through this section we will present a step-by-step construction of a `HelloWorld` extension using the Jami Plugin SDK.
 The goal is to print a colored circle in the middle of the video frames using **OpenCV**.
 The color of that circle will be defined by a preference which will be changeable at runtime.
@@ -310,6 +321,7 @@ We can define a second functionality that will always draw a circle in the right
 At the end we will exemplify how to build extensions with and without the SDK.
 
 #### Step 1 - prepare development environment
+
 The first step towards extension development is to properly prepare the environment.
 
 ```bash
@@ -436,15 +448,17 @@ for the centerCircle functionality? [y/n] y
 
 > CMakeLists.txt OK.
 
-
 * modify CenterCircleMediaHandler.cpp, CenterCircleVideoSubscriver.h, CenterCircleVideoSubscriber.cpp;
 * Modifying package.json and CMakeLists.txt is required to add OpenCV dependencies.
 
 All final files can be found {gitlab-project}`here <jami-plugins>`.
 
-
 #### Step 3 - build
-Before building the HelloWorld, FFmpeg and OpenCV dependencies should be compiled. This can be achieved by following the build instructions for OpenCV {doc}`here <jami-plugins>`. FFmpeg will build automatically if you follow those instructions.
+
+Before building the HelloWorld, [FFmpeg](https://ffmpeg.org/) and [OpenCV](https://opencv.org/) dependencies should be compiled.
+This can be achieved by following the build instructions for OpenCV [here](/extension/how-to-build.md).
+FFmpeg will build automatically if you follow those instructions.
+
 To build the extension, either:
 * Call the build from the Jami Plugin SDK (works for GNU/Linux and Windows):
 
@@ -469,6 +483,7 @@ python3 SDK/pluginMainSDK.py
 OBS: For Android, set `ANDROID_ABI` environment variable to the ABI required to build. Currently Jami supports `x86_64`, `armeabi-v7a`, and `arm64-v8a`. Extensions will be build for the three options by default.
 
 #### Step 4 - create another functionality for HelloWorld and rebuild
+
 Once HelloWorld is working and passed testing, attempt adding another functionality.
 
 ``` python
diff --git a/extension/extension-store-jami-client.md b/extension/extension-store-jami-client.md
index 7ec46c9a756e81a2e12918babf4f7df2a3d54db4..5e574c35884671e8afc6fb61861c083cac3b8511 100644
--- a/extension/extension-store-jami-client.md
+++ b/extension/extension-store-jami-client.md
@@ -5,7 +5,7 @@ This page describes how the Jami Extension Store works and how to use it.
 ```
 
 The Jami team has introduced extension as a call/chat feature for GNU/Linux, Windows, macOS, and Android, providing users with the ability to personalize their call/chat experience.
-If you want to learn more about Jami extensions, please refer to the [Jami Extensions](how-it-work.md) page.
+If you want to learn more about Jami extensions, please refer to the [Jami Extensions](how-it-works.md) page.
 
 To enhance the extension ecosystem, the Jami team has decided to include a Jami Extension Store where they can distribute both their own extensions and third-party extensions.
 However, before a third party can add an extension to the store, they must request a certificate signed by the certificate authority.
diff --git a/extension/how-to-build.md b/extension/how-to-build.md
index f725df3a6864a51cc889773d1039949211857965..94adbd60111b802f374522e36992766662e4652a 100644
--- a/extension/how-to-build.md
+++ b/extension/how-to-build.md
@@ -13,10 +13,12 @@ Before working on the plugin, you must first build its dependencies.
 You can find it in `daemon/contrib/src/`
 
 ## Dependencies
+
 Here we give you the steps to build [OpenCV](https://opencv.org/) and [ONNX](https://www.onnxruntime.ai/) but do not feel limited to these libraries.
 Other libraries should work as long they and the plugin are correctly built!
 
 ### Requirements:
+
 - git
 - docker
 
@@ -28,20 +30,23 @@ ONNX can take a long time so if you don't need it feel free to disable it.
 Examples of dependencies built include: FFmpeg, fmt, msgpack, OpenCV, OpenDHT, ONNX, opus, and FreeType.
 
 ### Update daemon
+
 Before anything, update the submodule `daemon` (from [jami-daemon](https://git.jami.net/savoirfairelinux/jami-daemon)) in `jami-plugins`
 
 ```bash
 git submodule update --init
 ```
 
-### Windows
+#### On Windows
+
 ```bash
 set DAEMON=<path/to/daemon>
 cd ${DAEMON}/compat/msvc
 python3 winmake.py -fb opencv
 ```
 
-### Linux
+#### On Linux
+
 With Docker (recommended):
 
 ```bash
@@ -90,7 +95,8 @@ make fetch opencv opencv_contrib
 make -j$(nproc)
 ```
 
-### Android
+#### On Android
+
 Using Docker (recommended):
 
 Change the android ABI between `arm64-v8a`, `armeabi-v7a` and `x86_64`.
@@ -136,6 +142,7 @@ The following links may be very helpful:
 * https://developer.nvidia.com/cudnn
 
 ### Linux and Android
+
 We added ONNX Runtime as a contrib in [daemon](https://git.jami.net/savoirfairelinux/jami-daemon/tree/master/contrib).
 This way you can easily build ONNX Runtime for Android, and Linux.
 
@@ -228,9 +235,11 @@ cp -r ./include/onnxruntime/core/ ../onnxruntime/include/
 For further build instructions, please visit the official ONNX Runtime instructions at [GitHub](https://github.com/microsoft/onnxruntime/blob/master/BUILD.md).
 
 ## Plugin
+
 To exemplify a plugin build, we will use the GreenScreen plugin available [here](https://git.jami.net/savoirfairelinux/jami-plugins).
 
-### Linux/Android
+### Plugin build on Linux/Android
+
 First you need to go to the plugins repository in your cloned jami-plugins:
 
 - Linux - Nvidia GPU
@@ -286,17 +295,16 @@ PLATFORM_TYPE="ANDROID" ANDROID_ABI="<android-architecture-separate-by-space>" p
 
 The GreenScreen.jpl file will be available under `<build/>`.
 
-### Windows
+### Plugin build on Windows
+
 Windows build of plugins are linked with the daemon repository and its build scripts. So to build our example plugins you have to:
 
 ```bash
 cd daemon/compat/msvc
 python3 winmake.py -fb GreenScreen
 ```
-
 The GreenScreen.jpl file will be available under `<build/>`.
 
-
-Related articles:
+## Related articles:
 
 - <https://jami.net/plugins-sdk/>
diff --git a/extension/index.md b/extension/index.md
index e8ea12dd5095e79c2ec6f2df3fb4dce538e28621..270ed1118d7f2ed9c0172e40ce69a86200b8577e 100644
--- a/extension/index.md
+++ b/extension/index.md
@@ -15,6 +15,7 @@ Jami source code also uses the term “plugin” to refer to “extension”.
 how-it-works
 how-to-build
 how-to-publish
+ask-to-publish
 creating-jami-extensions
 jami-extension-certificate
 extension-store-jami-client
diff --git a/extension/jami-extension-certificate.md b/extension/jami-extension-certificate.md
index 9f896b4ec9df5e1476b774dc0d9c57962295309c..7e5b762a600e65d2b9f6fcd101381ffbb3d76e9f 100644
--- a/extension/jami-extension-certificate.md
+++ b/extension/jami-extension-certificate.md
@@ -122,7 +122,7 @@ The steps to validate the signature of files are:
 5. If the certificate chain is verified and trusted, the extension can be installed.
 6. If one of the certificates that compose the certificate chain is revoked, all the files of the Green Screen extension are removed.
 
-## Sign an organization certificate
+## Sign Organization Certificate
 
 ### Install dependencies
 
@@ -134,94 +134,84 @@ pip install -r <requirements.txt> &&
 pip install -r <certificate_requirements.txt>
 ```
 
-## Create certificate
+### Create certificate
 
-### Create a self-signed certificate
+#### Self-signed certificate
 
 ```bash
 python3 ./SDK/certKey.py create --subject <subject-name> <path-to-save-certificate/privatekey>
 ```
 
-### Create a certificate with an issuer
+#### Certificate with issuer
 
 ```bash
 python3 ./SDK/certKey.py create --issuer <path-to-delegate-certificate> \
 --subject <subject-name> <path-to-save-certificate/privatekey>
 ```
 
-### Create an organization certificate for the Extension Store
+#### Organization Certificate for the Extension Store
 
 ```bash
 python3 ./SDK/certKey.py create --organization --issuer <path-to-delegate-certificate> \
 --subject <subject-name> <path-to-save-certificate/privatekey>
 ```
 
-### Create a certificate signing request
+#### Certificate Signing Request (CSR)
 
 ```bash
 python3 ./SDK/certKey.py --req create --subject <subject-name> <path-to-save-certificate/privatekey>
 ```
 
-### Create an organization certificate signing request
+#### Organization Certificate Signing Request (OCSR)
 
 ```bash
 python3 ./SDK/certKey.py --req create --organization --subject <subject-name> <path-to-save-certificate/privatekey>
 ```
 
-## Sign an extension
+### Sign an extension
 
-### Install dependencies
-
-```bash
-git clone git@git.jami.net:savoirfairelinux/jami-plugins.git &&
-sudo apt install python3 python3-pip &&
-cd <path-to-jami-plugins/SDK> &&
-pip install -r <requirements.txt> &&
-pip install -r <certificate_requirements.txt>
-```
-
-### Sign JPL archive file
+#### Sign JPL archive file
 
 ```bash
 python3 ./SDK/certKey.py --plugin sign --issuer <path-to-plugin-certificate>\
 --path <path-to-archive> <path-to-save-archive-copy>
 ```
 
-## Revoke a certificate
+### Revoke a certificate
 
-### Create CRL
+#### Create a Certificate Revocation List (CRL)
 
 ```bash
 python3 ./certKey.py crl create --crl --issuer <path-to-ca> --subject crl <path-to-save-crl>
 ```
 
-### Add revoked certificate to CRL
+#### Add revoked Certificate to the CRL
 
 ```bash
 python3 ./certKey.py revoke --crl <path-to-crl> --subject <path-to-certificate-to-revoke> --issuer <path-to-ca> [--reason REASON]
 ```
 
-## Verify certificate
+### Certificate verification
 
-### Verify certificate signing request
+#### Verify a Certificate Signing Request
 
 ```bash
 python3 ./certKey.py --req [--archive] verify --path <path-to-csr> --issuer <path-to-issuer>
 ```
 
-### Verify certificate
+#### Verify a Certificate
 
 ```bash
 python3 ./certKey.py [--archive] verify --path <path-to-certificate> --issuer <path-to-issuer>
 ```
 
-### Verify Jami extension
+#### Verify a Jami extension
 
 ```bash
 python3 ./certKey.py [--archive] --plugin verify --path <path-to-extension>
 ```
 
-## Example
+## Examples
 
 ### Create a signed foo extension to test
 
diff --git a/extension/tensorflow-extension.md b/extension/tensorflow-extension.md
index 558ff2816e35296c4de408e3eb94c5821999ef18..49d39c45bb3cc70e6c53588cf30fee84a93d6814 100644
--- a/extension/tensorflow-extension.md
+++ b/extension/tensorflow-extension.md
@@ -6,6 +6,7 @@ LiteRT (short for Lite Runtime) is the new name for TensorFlow Lite (TFLite).
 ```
 
 ## TensorFlow 2.1.0
+
 A challenge with working with TensorFlow is how to properly build it.
 To reduce the building challenges, Docker images have been created with CUDA and TensorFlow libraries available for
 GNU/Linux builds [here](https://hub.docker.com/repository/docker/sflagsantos/tensorflow-cuda) and for
@@ -31,6 +32,7 @@ However, if a different version of TensorFlow is used or assembling TensorFlow f
 instructions to assemble TensorFlow Lite Native and C++ API are shown in the `README_ASSEMBLE` file available at {gitlab-project}`jami-plugins`.
 
 ### GNU/Linux
+
 LiteRT does not support desktop GPUs.
 Consider using the TensorFlow C++ API if desktop GPU support is required.
 
@@ -60,6 +62,7 @@ Set up the build options with `./configure`.
     ```
 
 ### Windows
+
 LiteRT does not support desktop GPUs.
 Consider using the TensorFlow C++ API if desktop GPU support is required.
 
@@ -90,9 +93,10 @@ Set up the build options with `python3 configure.py`.
 There may be some missing references while compiling an extension with the TensorFlow C++ API.
 If this occurs, rebuild TensorFlow and explicitly export the missing symbols.
 Fortunately, TensorFlow now has an easy workaround.
-Feed [this]("https://github.com/tensorflow/tensorflow/blob/v2.2.0/tensorflow/tools/def_file_filter/def_file_filter.py.tpl") file with the required symbols.
+Feed [this](https://github.com/tensorflow/tensorflow/blob/v2.2.0/tensorflow/tools/def_file_filter/def_file_filter.py.tpl) file with the required symbols.
 
 ### Android – LiteRT Native
+
 For mobile applications, it is suggested that LiteRT is the only option to consider to successfully build TensorFlow. Additional requirements are:
 
 * Android NDK 18r
diff --git a/user/jami-distributed-network.md b/user/jami-distributed-network.md
index 2b6b8a81fc88639cc875d0c85bb261500705476e..01c12cbf83b75e6b5d7ec8c2bce5f820de9c118b 100644
--- a/user/jami-distributed-network.md
+++ b/user/jami-distributed-network.md
@@ -1,10 +1,8 @@
-Jami distributed network
-========================
+# Jami distributed network
 
-### Connectivity
+## Connectivity
 
-Jami relies on a [distributed
-network](tutorials/Jami-distributed-network), that brings multiple
+Jami relies on a distributed network, that brings multiple
 advantages when compared to federated networks:
 
 -   No point of failure,
@@ -12,7 +10,7 @@ advantages when compared to federated networks:
 -   Do not depend on anything other than its users,
 -   Trust amongst nodes is not necessary.
 
-![Network-topo](https://git.jami.net/savoirfairelinux/jami-project/uploads/9b725e440c2705a2a3c4d0a3df092066/Network-topo.png)
+![Network topographies](https://git.jami.net/savoirfairelinux/jami-project/uploads/9b725e440c2705a2a3c4d0a3df092066/Network-topo.png)
 
 This network forms a Distributed Hash Table (DHT)
 
@@ -28,8 +26,7 @@ Jami is built on two distinct distributed networks:
     establishment and message distribution,
 -   the JamiNS blockchain to provide distributed name registration.
 
-The OpenDHT network
--------------------
+## The OpenDHT network
 
 See
 [<https://github.com/savoirfairelinux/opendht>](https://github.com/savoirfairelinux/opendht)
@@ -68,8 +65,7 @@ Stable community-run DHT nodes will be added to the default bootstrap
 list at the request of their owner, as more bootstrap nodes means a more
 resilient, independent network.
 
-The JamiNS blockchain
----------------------
+## The JamiNS blockchain
 
 The JamiNS blockchain is experimental and its architecture is expected
 to evolve.
@@ -97,6 +93,7 @@ NodeJS module (HTTP server) can be found here :
 ### Running a Jami Node
 
 #### Pre-requisites:
+
 1. Geth 1.8.23+ (download from [HERE](https://geth.ethereum.org/downloads/))
 2. Jami genesis file (download from [HERE](https://git.jami.net/savoirfairelinux/jami-nameservice/blob/master/instructions/genesis.json))
 
@@ -113,7 +110,7 @@ The process of joining the Jami network is similar to the process of joining a r
 3. Use geth to initialize the directory you created in (2) by running ```./geth --datadir /home/username/jamichain  init genes is.json ```
 4. You can now start geth with the command-line options you need and specifying one of Jami's bootnodes as follows:
 
-```
+```bash
 geth --datadir=/home/username/jamichain --syncmode=full --networkid 1551 --bootnodes "enode://11ba6d3bfdc29a8afb24dcfcf9a08c8008005ead62756eadb363523c2ca8b819efbb264053db3d73949f1375bb3f03090f44cacfb88bade38bb6fc2cb3d890a5@173.231.120.228:30301" console
 ```
 This will start a geth daemon with an attached console which is now syncing with Jami's network.