diff --git a/docs/source/theming.rst b/docs/source/theming.rst
index a55e2959c4..52639fc7d1 100644
--- a/docs/source/theming.rst
+++ b/docs/source/theming.rst
@@ -1,145 +1,174 @@
-.. raw:: html
-
-
-
-.. _theming:
-
-=======
-Theming
-=======
-
-Setting up your environment
-===========================
-
-In order to theme Converse, you first need to follow the steps for :ref:`setup_dev_environment`, including :ref:`webserver`.
-
-Creating a custom theme
-=======================
-
-Converse can be themed via CSS custom properties (aka CSS variables) and it has
-some themes available in its source repository.
-
-A theme is a CSS file with a specific rule that defines the theme's CSS properties.
-The rule has a specific selector that must include (and determines) the theme name.
-
-Inside this CSS rule, various CSS variables are assigned values.
-The CSS variables mainly refer to the colors that comprise the theme.
-If you don't specify a value for a specific CSS variable, then the value from
-the ``classic`` theme is used, as defined in `classic.scss `_.
-
-The native theme files can be found in `shared/styles/themes `_.
-
-Note, the Converse theme files have a ``.scss`` extension because they are compiled
-by the Sass compiler into normal CSS files. It's however not necessary to use
-Sass, basic CSS files will also suffice.
-
-The theme that Converse uses can be set via the :ref:`theme` configuration
-setting (and the :ref:`dark_theme` configuration setting for dark mode).
-
-How are themes applied?
------------------------
-
-When you set a value for the :ref:`theme` configuration setting, Converse will add
-a class ``theme-${api.settings.get('theme')}`` on the ``converse-root`` DOM
-element.
-
-So, for example, if you set the ``theme`` setting to ``"dracula"``, then the
-``converse-root`` element will get the class ``theme-dracula``.
-
-.. code-block:: javascript
-
- converse.initialize({ theme: "dracula" });
-
-
-.. code-block:: html
-
-
-
-
-The apply a theme, there then needs to be a CSS rule with a selector that matches the
-``theme-dracula`` class on the ``converse-root`` element.
-
-If you take a look at the theme file `dracula.scss `_
-you'll see that it defines a CSS rule with the selector
-``.conversejs.theme-dracula``.
-
-This selector matches any DOM element with both the classes ``.conversejs`` and
-``.theme-dracula``. The ``converse-root`` element will already have the class
-``.conversejs`` and it will have the class ``.theme-dracula`` if the ``theme``
-(or ``dark_theme`` in dark mode) configuration setting is set to ``"dracula"``.
-
-This is how themes are applied, by defining a CSS selector that matches the
-class ``.theme-${name}`` (where ``name`` is a variable containing the name of
-the theme), and then setting the ``theme`` (and/or ``dark_theme``) configuration
-setting.
-
-To create your own theme, you can create a similar CSS rule that matches
-your theme's name and then you set the ``theme`` configuration setting to that
-name. This CSS rule can be in any CSS file that is loaded in your website, or
-you can even put it in the DOM as an inline style.
-
-Modifying the CSS
-=================
-
-To create a new theme with different colors, it should be enough to create a
-theme file that sets the various CSS variables (as described above).
-
-For other CSS-related changes, you can make a specific
-CSS rule with that matches the element you want to change.
-
-Sometimes it might however be necessary to modify the core CSS files from
-Converse, for example if you're developing new features or fixing styling bugs.
-
-The CSS files are generated from `Sass `_ files that end in ``.scss`` and
-which are distributed throughout the source code.
-
-The CSS that is relevant to a particular plugin
-is usually inside the ``./styles`` directory inside the relevant plugin directory.
-
-For example: `src/plugins/controlbox/styles `_.
-
-If you're running ``make watch``, then the CSS will automatically be
-regenerated when you've changed any of the ``.scss``.
-
-You can also manually generate the CSS::
-
- make css
-
-Modifying the HTML templates of Converse
-========================================
-
-Converse uses `lit-html `_ as HTML
-templating library, and the HTML source code is contained in JavaScript ``.js``
-files in various ``./template`` directories in the source code.
-
-Some top-level templates are also in the ``./src/templates`` directory, but
-the templates that are relevant to a specific plugin should be inside that plugin's subdirectory.
-
-For example: `src/plugins/chatview/templates `_.
-
-You can modify HTML markup that Converse generates by modifying these files.
-
-Use webpack aliases to modify templates without changing the original files
----------------------------------------------------------------------------
-
-Generally what I do when creating a modified version of Converse for a project
-or customer, is that I create a new JavaScript package with its own
-``package.json`` and I then add ``converse.js`` as a dependency (e.g. via ``npm
-install --save converse.js``) to the ``package.json``.
-
-Then I add a Webpack configuration and use `webpack aliases `_
-to resolve template paths to my own modified files.
-
-For example, in the webpack configuration snippet below, I add two aliases, so
-that the ``message-body.js`` and ``message.js`` templates can be replaced with
-two of my own custom templates.
-
-.. code-block:: javascript
-
- resolve: {
- extensions: ['.js'],
- alias: {
- './message-body.js': path.resolve(__dirname, 'path/to/my/custom/message-body.js'),
- './templates/message.js': path.resolve(__dirname, 'path/to/my/custom/chat_message.js'),
- }
- }
+.. raw:: html
+
+
+
+.. _theming:
+
+=======
+Theming
+=======
+
+Setting up your environment
+===========================
+
+In order to theme Converse, you first need to follow the steps for :ref:`setup_dev_environment`, including :ref:`webserver`.
+
+Creating a custom theme
+=======================
+
+Converse can be themed via CSS custom properties (aka CSS variables) and it has
+some themes available in its source repository.
+
+A theme is a CSS file with a specific rule that defines the theme's CSS properties.
+The rule has a specific selector that must include (and determines) the theme name.
+
+Inside this CSS rule, various CSS variables are assigned values.
+The CSS variables mainly refer to the colors that comprise the theme.
+If you don't specify a value for a specific CSS variable, then the value from
+the ``classic`` theme is used, as defined in `classic.scss `_.
+
+The native theme files can be found in `shared/styles/themes `_.
+
+Note, the Converse theme files have a ``.scss`` extension because they are compiled
+by the Sass compiler into normal CSS files. It's however not necessary to use
+Sass, basic CSS files will also suffice.
+
+The theme that Converse uses can be set via the :ref:`theme` configuration
+setting (and the :ref:`dark_theme` configuration setting for dark mode).
+
+How are themes applied?
+-----------------------
+
+When you set a value for the :ref:`theme` configuration setting, Converse will add
+a class ``theme-${api.settings.get('theme')}`` on the ``converse-root`` DOM
+element.
+
+So, for example, if you set the ``theme`` setting to ``"dracula"``, then the
+``converse-root`` element will get the class ``theme-dracula``.
+
+.. code-block:: javascript
+
+ converse.initialize({ theme: "dracula" });
+
+
+.. code-block:: html
+
+
+
+
+The apply a theme, there then needs to be a CSS rule with a selector that matches the
+``theme-dracula`` class on the ``converse-root`` element.
+
+If you take a look at the theme file `dracula.scss `_
+you'll see that it defines a CSS rule with the selector
+``.conversejs.theme-dracula``.
+
+This selector matches any DOM element with both the classes ``.conversejs`` and
+``.theme-dracula``. The ``converse-root`` element will already have the class
+``.conversejs`` and it will have the class ``.theme-dracula`` if the ``theme``
+(or ``dark_theme`` in dark mode) configuration setting is set to ``"dracula"``.
+
+This is how themes are applied, by defining a CSS selector that matches the
+class ``.theme-${name}`` (where ``name`` is a variable containing the name of
+the theme), and then setting the ``theme`` (and/or ``dark_theme``) configuration
+setting.
+
+To create your own theme, you can create a similar CSS rule that matches
+your theme's name and then you set the ``theme`` configuration setting to that
+name. This CSS rule can be in any CSS file that is loaded in your website, or
+you can even put it in the DOM as an inline style.
+
+Modifying the CSS
+=================
+
+To create a new theme with different colors, it should be enough to create a
+theme file that sets the various CSS variables (as described above).
+
+For other CSS-related changes, you can make a specific
+CSS rule with that matches the element you want to change.
+
+Sometimes it might however be necessary to modify the core CSS files from
+Converse, for example if you're developing new features or fixing styling bugs.
+
+The CSS files are generated from `Sass `_ files that end in ``.scss`` and
+which are distributed throughout the source code.
+
+The CSS that is relevant to a particular plugin
+is usually inside the ``./styles`` directory inside the relevant plugin directory.
+
+For example: `src/plugins/controlbox/styles `_.
+
+If you're running ``make watch``, then the CSS will automatically be
+regenerated when you've changed any of the ``.scss``.
+
+You can also manually generate the CSS::
+
+ make css
+
+Modifying the HTML templates of Converse
+========================================
+
+Converse uses `lit-html `_ as HTML
+templating library, and the HTML source code is contained in JavaScript ``.js``
+files in various ``./template`` directories in the source code.
+
+Some top-level templates are also in the ``./src/templates`` directory, but
+the templates that are relevant to a specific plugin should be inside that plugin's subdirectory.
+
+For example: `src/plugins/chatview/templates `_.
+
+You can modify HTML markup that Converse generates by modifying these files.
+
+Use webpack aliases to modify templates without changing the original files
+---------------------------------------------------------------------------
+
+Generally what I do when creating a modified version of Converse for a project
+or customer, is that I create a new JavaScript package with its own
+``package.json`` and I then add ``converse.js`` as a dependency (e.g. via ``npm
+install --save converse.js``) to the ``package.json``.
+
+Then I add a Webpack configuration and use `webpack aliases `_
+to resolve template paths to my own modified files.
+
+For example, in the webpack configuration snippet below, I add two aliases, so
+that the ``message-body.js`` and ``message.js`` templates can be replaced with
+two of my own custom templates.
+
+.. code-block:: javascript
+
+ resolve: {
+ extensions: ['.js'],
+ alias: {
+ './message-body.js': path.resolve(__dirname, 'path/to/my/custom/message-body.js'),
+ './templates/message.js': path.resolve(__dirname, 'path/to/my/custom/chat_message.js'),
+ }
+ }
+
+Complete example project
+------------------------
+
+To help you get started with creating custom themes and templates, we have created
+a complete example project that demonstrates:
+
+* Setting up a new JavaScript package with Converse.js as a dependency
+* Configuring Webpack with aliases to override templates
+* Creating a custom theme with CSS variables
+* Creating custom templates for messages
+* Building and running the project
+
+You can find the example project here:
+
+**`converse-custom-theme-example `_**
+
+The example includes:
+
+* ``package.json`` with all necessary dependencies
+* ``webpack.config.js`` with template aliases configured
+* ``src/index.js`` showing how to import and initialize Converse
+* ``src/styles/custom-theme.scss`` - a complete custom theme example
+* ``src/templates/`` - custom message templates
+* Detailed README with step-by-step instructions
+
+We recommend using this example as a starting point for your own custom Converse.js
+projects. You can fork it, modify the theme and templates to your needs, and use
+it as a foundation for your application.