diff --git a/markup/constants.py b/markup/constants.py
index 88e22ff3aef835f8347ace3c3308f82cac77aefd..6084258ef204c51abdd48e062e84a6c4c561bd78 100644
--- a/markup/constants.py
+++ b/markup/constants.py
@@ -5,15 +5,17 @@ __license__ = "AGPL v3"
 # Dictionary for regex expressions to recognize reStructuredText headers.
 # This follows the Python conventions: order is #, *, =, -, ", ^ and
 # for the first two levels (# and *), over- and underlining are necessary, while
-# only underlining is needed for the lower four levels.
+# only underlining is needed for the lower four levels. In all cases we
+# require the headline title to be at least one character long, and placed
+# right above the lower headline marker.
 # The regex search should use the re.MULTILINE flag.
 ReST_HEADER_REGEX_DICT = {
-    '#': r'^(#{1,}\n).+\n\1', # this makes use of a regex backreference
-    '*': r'^(\*{1,}\n).+\n\1', # this makes use of a regex backreference
-    '=': r'^={1,}\n',
-    '-': r'^-{1,}\n',
-    '"': r'^"{1,}\n',
-    '^': r'^\^{1,}\n'
+    '#': r'^(#{1,}\n).{1,}\n\1',  # this makes use of a regex backreference
+    '*': r'^(\*{1,}\n).{1,}\n\1', # this makes use of a regex backreference
+    '=': r'^.{1,}\n={1,}\n',   # non-empty line followed by line of =
+    '-': r'^.{1,}\n-{1,}\n',   # non-empty line followed by line of -
+    '"': r'^.{1,}\n"{1,}\n',   # non-empty line followed by line of "
+    '^': r'^.{1,}\n\^{1,}\n'   # non-empty line followed by line of ^
 }
 
 # See list at http://docutils.sourceforge.net/0.4/docs/ref/rst/roles.html
@@ -44,73 +46,6 @@ BLEACH_ALLOWED_TAGS = [
 ]
 
 
-MathSnippets = (
-    {
-        'title': 'Inline and online equations',
-        'raw':
-r"""Some say $e^{i\pi} + 1 = 0$ is the most beautiful equation there is.
-
-Simple multiplication: $a * b = c$ and $a < b$ and $c < d$.
-
-Ampersands: & and &amp; are both ampersands. Lesser than: &lt; is <
-and $<$ is OK. What about AT&T?
-
-Do you know this famous Hamiltonian?
-\[
-H = \sum_j {\boldsymbol S}_j \cdot {\boldsymbol S}_{j+1}
-\]
-
-What about this one?
-$$
-H = \int dx \left[ \partial_x \Psi^\dagger \partial_x \Psi
-+ c \Psi^\dagger \Psi^\dagger \Psi \Psi \right]
-$$
-""",
-    },
-    {
-        'title': 'Multiline equations',
-        'raw':
-r"""
-<script>alert("Gotcha!");</script>
-
-$$
-</script><script>alert("Gotcha!");</script><script>
-$$
-
-Maxwell's equations:
-
-\[
-\begin{align*}
-\nabla \cdot {\boldsymbol E} &= \frac{\rho}{\epsilon_0}, &
-\nabla \times {\boldsymbol E} + \frac{\partial \boldsymbol B}{\partial t} &= 0, \\
-\nabla \cdot {\boldsymbol B} &= 0, &
-\nabla \times {\boldsymbol B} - \frac{1}{c^2} \frac{\partial \boldsymbol E}{\partial t}
-&= \mu_0 {\boldsymbol J}
-\end{align*}
-\]
-
-$$
-\begin{align*}
-\nabla \cdot {\boldsymbol E} &= \frac{\rho}{\epsilon_0}, &
-\nabla \times {\boldsymbol E} + \frac{\partial \boldsymbol B}{\partial t} &= 0, \\
-\nabla \cdot {\boldsymbol B} &= 0, &
-\nabla \times {\boldsymbol B} - \frac{1}{c^2} \frac{\partial \boldsymbol E}{\partial t}
-&= \mu_0 {\boldsymbol J}
-\end{align*}
-$$
-
-$$
-\nabla \cdot {\boldsymbol E} = \frac{\rho}{\epsilon_0},
-\nabla \times {\boldsymbol E} + \frac{\partial \boldsymbol B}{\partial t} = 0, \\
-\nabla \cdot {\boldsymbol B} = 0,
-\nabla \times {\boldsymbol B} - \frac{1}{c^2} \frac{\partial \boldsymbol E}{\partial t}
-= \mu_0 {\boldsymbol J}
-\label{eq:Maxwell}
-$$
-"""
-        },
-)
-
 
 PlainTextSnippets = {
     'maths_inline_online':
@@ -366,22 +301,224 @@ since beginning and end markers are not distinguishable):
 $$
 H = \sum_j S^x_j S^x_{j+1} + S^y_j S^y_{j+1} + \Delta S^z_j S^z_{j+1}
 $$
+
+Multiline equations can be obtained by using the ``\\`` carriage return as usual;
+to align your equations, use the ``align`` environment. For example:
+
+\[
+\begin{align*}
+\nabla \cdot {\boldsymbol E} &= \frac{\rho}{\epsilon_0}, &
+\nabla \times {\boldsymbol E} + \frac{\partial \boldsymbol B}{\partial t} &= 0, \\
+\nabla \cdot {\boldsymbol B} &= 0, &
+\nabla \times {\boldsymbol B} - \frac{1}{c^2} \frac{\partial \boldsymbol E}{\partial t}
+&= \mu_0 {\boldsymbol J}
+\end{align*}
+\]
 """},
 )
 
 
-ReStructuredTextSnippets = {
-    'maths_inline_online':
-r"""Inline maths
-============
+ReStructuredTextSnippets = (
+    {
+        'id': 'paragraphs',
+        'title': 'Paragraphs and line breaks',
+        'raw':
+"""Including an empty line between two blocks of text separates those into
+
+two different paragraphs.
+
+Typing text on consecutive lines separated
+by linebreaks
+will merge the lines into one
+paragraph.
+
+As in Python, indentation is significant, so lines of a paragraph have to be
+indented to the same level.""",},
+
+    {
+        'id': 'headlines',
+        'title': 'Headlines',
+        'raw':
+"""##################
+Level 1 (html h1)
+##################
+
+Topmost headline
+
+*****************
+Level 2 (h2)
+*****************
+
+two
+
+Level 3 (h3)
+==================
+
+three
+
+Level 4 (h4)
+-------------------
+
+four
+
+Level 5 (h5)
+\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"
+
+five
+
+Level 6 (h6)
+^^^^^^^^^^^^^^^^^^^
+
+six, lowest level available.""",},
+
+    {
+        'id': 'emphasis',
+        'title': 'Emphasis',
+        'raw':
+"""You can obtain italics with *asterisks*,
+boldface using **double asterisks** and code samples using ``double backquotes``.
+Note that these cannot be nested, and that there must not be a space at the
+start or end of the contents.
+
+If you need to explicitly use these characters (namely \*),
+you can escape them with a backslash.""",},
+
+    {
+        'id': 'blockquotes',
+        'title': 'Blockquotes',
+        'raw':
+"""It is often handy to use blockquotes.
+
+ This is a blockquote with two paragraphs, obtained by simple
+ indentation from the surrounding text. For multiple lines,
+ each line should be indented the same.
+
+ Here is the second paragraph, with lines indented
+ to the same level as the previous ones to preserve the
+ blockquote.
+
+To preserve line breaks, you can use line blocks:
+
+| Here is
+| a small paragraph
+| with linebreaks preserved.
+
+""",},
+
+    {
+        'id': 'lists',
+        'title': 'Lists',
+        'raw':
+"""reStructuredText supports unordered (bulleted) and ordered (numbered) lists.
+
+Unordered list items are marked with asterisk:
+
+* first item
+* second item
+* third item
+
+Ordered list items are marked by a number or # followed by a period:
+
+1. first item
+2. second item
+3. third item
+
+
+Nested lists can be obtained by indentation:
+
+* First mainlist item
+
+  * first sublist item
+  * second sublist item
+* Second mainlist item
+
+
+There are also *definition lists* obtained like this:
+
+term (up to a line of text)
+   Definition of the term, which must be indented
+
+   and can even consist of multiple paragraphs
+
+next term
+   Description.
+""",},
+
+    {
+        'id': 'code',
+        'title': 'Code',
+        'raw':
+"""An inline code span, to mention simple things like the
+``print()`` function, is obtained by wrapping it with double backticks.
+
+A code block is obtained by the ``::`` marker followed by the indented code::
 
-For inline equations, you must use the :code:`math` role, for example :math:`E = mc^2`.
+    from django import forms
 
-On-line maths
-=============
+    class MarkupTextForm(forms.Form):
+        markup_text = forms.CharField()
 
-For on-line display of equations, the :code:`math` directive must be used:
+        def get_processed_markup(self):
+            text = self.cleaned_data['markup_text']
+
+which can then be followed by normal text.""",},
+
+    {
+        'id': 'tables',
+        'title': 'Tables',
+        'raw':
+"""
+A grid table can be written by "painting" it directly:
+
++------------------------+------------+----------+----------+
+| Header row, column 1   | Header 2   | Header 3 | Header 4 |
+| (header rows optional) |            |          |          |
++========================+============+==========+==========+
+| body row 1, column 1   | column 2   | column 3 | column 4 |
++------------------------+------------+----------+----------+
+| body row 2             | ...        | ...      |          |
++------------------------+------------+----------+----------+
+
+""",},
+
+    {
+        'id': 'links',
+        'title': 'Links',
+        'raw':
+"""Here is an example of an inline link to the `SciPost homepage <https://scipost.org/>`_.
+
+For example, one can also link to
+a specific `Submission <https://scipost.org/submissions/1509.04230v5/>`_
+or a specific `Report <https://scipost.org/submissions/1509.04230v4/#report_2>`_.
+
+You can also use reference-style links when citing this `resource`_, the reference
+will be resolved provided you define the link label somewhere
+in your text.
+
+.. _resource: https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html""",},
+
+    {
+        'id': 'mathematics',
+        'title': 'Mathematics',
+        'raw':
+"""
+For simple inline equations, use the :code:`math` role like this: :math:`E = mc^2`.
+
+For displayed maths, the :code:`math` directive must be used:
 
 .. math::
-  H = \sum_j {\boldsymbol S}_j \cdot {\boldsymbol S}_{j+1}"""
-}
+  H = \sum_j {\\boldsymbol S}_j \cdot {\\boldsymbol S}_{j+1}
+
+Multiline equations can be obtained by using the ``\\`` carriage return as usual;
+to align your equations, use the ``align`` environment. For example:
+
+.. math::
+  \\nabla \\cdot {\\boldsymbol E} = \\frac{\\rho}{\\epsilon_0},
+  \\nabla \\times {\\boldsymbol E} + \\frac{\\partial \\boldsymbol B}{\\partial t} = 0, \\\\
+  \\nabla \\cdot {\\boldsymbol B} = 0,
+  \\nabla \\times {\\boldsymbol B} - \\frac{1}{c^2} \\frac{\\partial \\boldsymbol E}{\\partial t}
+  = \\mu_0 {\\boldsymbol J}
+
+
+"""},
+)
diff --git a/markup/templates/markup/markdown_help.html b/markup/templates/markup/markdown_help.html
index 5e0c4aea99e44a9b826bd65f714b501ddde1dffb..2f3e9bc637c62d307873770b74925a05a98a03a0 100644
--- a/markup/templates/markup/markdown_help.html
+++ b/markup/templates/markup/markdown_help.html
@@ -43,24 +43,4 @@
     </div>
   </div>
 
-  {% with language='Markdown' %}
-    <div class="row">
-      <div class="col-12">
-	<h3 class="highlight">Math snippets</h3>
-	{{ math_snippets.length }}
-	{% for snippet in math_snippets %}
-	  <h4>{{ snippet.title }}</h4>
-	  <div class="row">
-	    <div class="col-lg-6">
-	      <pre>{{ snippet.raw }}</pre>
-	    </div>
-	    <div class="col-lg-6">
-	      {{ snippet.raw|automarkup:language }}
-	    </div>
-	  </div>
-	{% endfor %}
-      </div>
-    </div>
-  {% endwith %}
-
 {% endblock content %}
diff --git a/markup/templates/markup/plaintext_help.html b/markup/templates/markup/plaintext_help.html
index 5a5a3acd0ca82678a9aeebc0acb25078512a1512..9282ee990a0c59491ccfd126f7e6831dbe2565a0 100644
--- a/markup/templates/markup/plaintext_help.html
+++ b/markup/templates/markup/plaintext_help.html
@@ -39,24 +39,4 @@
     </div>
   </div>
 
-  {% with language='plain' %}
-    <div class="row">
-      <div class="col-12">
-	<h3 class="highlight">Math snippets</h3>
-	{{ math_snippets.length }}
-	{% for snippet in math_snippets %}
-	  <h4>{{ snippet.title }}</h4>
-	  <div class="row">
-	    <div class="col-lg-6">
-	      <pre>{{ snippet.raw }}</pre>
-	    </div>
-	    <div class="col-lg-6">
-	      {{ snippet.raw|automarkup:language }}
-	    </div>
-	  </div>
-	{% endfor %}
-      </div>
-    </div>
-  {% endwith %}
-
 {% endblock content %}
diff --git a/markup/templates/markup/restructuredtext_help.html b/markup/templates/markup/restructuredtext_help.html
index e61967296f00942d0c956e7aadf0d5118af8c509..e6c4fcb272553bf050593b9a9aa4412f9bf7513d 100644
--- a/markup/templates/markup/restructuredtext_help.html
+++ b/markup/templates/markup/restructuredtext_help.html
@@ -16,43 +16,33 @@
     <div class="col-12">
       <h2 class="highlight">reStructuredText help</h2>
 
-      <h3 class="highlight" id="Mathematics">Mathematics</h3>
-
-      <p>
-	For mathematics in reStructuredText, you must use the <code>math</code>
-	directive/role.
-      </p>
-      <div class="row">
-	<div class="col-6">
-	  <h4><strong>If you write:</strong></h4>
-	  <pre>{{ snippets.maths_inline_online }}</pre>
-	</div>
-	<div class="col-6">
-	  <h4><strong>You will get:</strong></h4>
-	  {{ snippets.maths_inline_online|automarkup:'reStructuredText' }}
+      <p>You will find below a quick summary of reStructuredText basics,
+	as enabled here at SciPost.</p>
+      <p>You can find more details about reStructuredText's syntax
+	for example at <a href="https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html">this page</a>.</p>
+
+      <h3>Quick links</h3>
+      <ul>
+	{% for snippet in snippets %}
+	  <li><a href="#{{ snippet.id }}">{{ snippet.title }}</a></li>
+	{% endfor %}
+      </ul>
+
+      {% for snippet in snippets %}
+	<h3 class="highlight" id="{{ snippet.id }}">{{ snippet.title }}</h3>
+	<div class="row">
+	  <div class="col-6">
+	    <h3><strong>If you write:</strong></h3>
+	    <pre>{{ snippet.raw }}</pre>
+	  </div>
+	  <div class="col-6">
+	    <h3><strong>You will get:</strong></h3>
+	    {{ snippet.raw|automarkup:'reStructuredText' }}
+	  </div>
 	</div>
-      </div>
-    </div>
-  </div>
+      {% endfor %}
 
-  {% with language='reStructuredText' %}
-    <div class="row">
-      <div class="col-12">
-	<h3 class="highlight">Math snippets</h3>
-	{{ math_snippets.length }}
-	{% for snippet in math_snippets %}
-	  <h4>{{ snippet.title }}</h4>
-	  <div class="row">
-	    <div class="col-lg-6">
-	      <pre>{{ snippet.raw }}</pre>
-	    </div>
-	    <div class="col-lg-6">
-	      {{ snippet.raw|automarkup:language }}
-	    </div>
-	  </div>
-	{% endfor %}
-      </div>
     </div>
-  {% endwith %}
+  </div>
 
 {% endblock content %}
diff --git a/markup/utils.py b/markup/utils.py
index 7b36be083175aa46f55056d9f17895b0b8db574b..3e04875101947c9cb966722af7f0b496872a9185 100644
--- a/markup/utils.py
+++ b/markup/utils.py
@@ -48,7 +48,7 @@ def match_md_header(text, level=None):
         raise TypeError('level must be an int')
     if level < 1 or level > 6:
         raise ValueError('level must be an integer from 1 to 6')
-    return re.search(r'^#{' + str(level) + ',}[ ].+$', text)
+    return re.search(r'^#{' + str(level) + ',}[ ].+$', text, re.MULTILINE)
 
 def match_md_blockquote(text):
     """Return first match of regex search for Markdown blockquote."""
@@ -88,10 +88,9 @@ def match_rst_directive(text, directive=None):
         return none
     if directive not in ReST_DIRECTIVES:
         raise ValueError('this directive is not listed in ReST directives')
-    print('regex = %s' % r'^\.\. ' + directive + '::(.+)*(\n(.+)*){1,3}')
     return re.search(r'^\.\. ' + directive + '::(.+)*(\n(.+)*){1,3}', text, re.MULTILINE)
 
-def match_rst_header(text, symbol):
+def match_rst_header(text, symbol=None):
     """
     Return first match object of regex search for reStructuredText header.
 
@@ -99,8 +98,17 @@ def match_rst_header(text, symbol):
     both over and underline (of equal length, so faulty ones are not matched),
     while the others (``=``, ``-``, ``"`` and ``^``) only have the underline.
     """
+    if not symbol:
+        for newsymbol in ['#', '*', '=', '-', '"', '^']:
+            match = match_rst_header(text, newsymbol)
+            if match:
+                return match
+        return None
     if symbol not in ReST_HEADER_REGEX_DICT.keys():
         raise ValueError('symbol is not a ReST header symbol')
+    print('Looking for %s in rst: %s' % (
+        symbol,
+        re.search(ReST_HEADER_REGEX_DICT[symbol], text, re.MULTILINE)))
     return re.search(ReST_HEADER_REGEX_DICT[symbol], text, re.MULTILINE)
 
 
@@ -161,6 +169,8 @@ def detect_markup_language(text):
         'errors': None
     }
 
+    # Step 1: check maths
+
     # Inline maths is of the form $ ... $ or \( ... \)
     inline_math = match_inline_math(text)
 
@@ -170,9 +180,6 @@ def detect_markup_language(text):
     rst_math_role = match_rst_role(text, 'math')
     rst_math_directive = match_rst_directive(text, 'math')
 
-    md_header = match_md_header(text)
-    md_blockquote = match_md_blockquote(text)
-
     if rst_math_role or rst_math_directive:
         # reStructuredText presumed; check for errors
         if inline_math:
@@ -185,20 +192,39 @@ def detect_markup_language(text):
                 'You have mixed displayed maths ($$ ... $$ or \[ ... \]) with '
                 'reStructuredText markup.\n\nPlease use one or the other, but not both!')
             return detector
-        elif md_header:
-            detector['errors'] = (
-                'You have mixed Markdown headers with reStructuredText math roles/directives.'
-                '\n\nPlease use one language only.')
-        elif md_blockquote:
-            detector['errors'] = (
-                'You have mixed Markdown blockquotes with reStructuredText math roles/directives.'
-                '\n\nPlease use one language only.')
         else:
             detector['language'] = 'reStructuredText'
+            return detector
+
+    # no rst math from here onwards
+
+    # Step 2: check headers and blockquotes
+
+    md_header = match_md_header(text)
+    print('md_header: %s' % md_header)
+    md_blockquote = match_md_blockquote(text)
+
+    rst_header = match_rst_header(text)
+    print('rst_header: %s' % rst_header)
+
+    if md_header or md_blockquote:
+        if rst_math_role or rst_math_directive:
+            if md_header:
+                detector['errors'] = (
+                    'You have mixed Markdown headers with reStructuredText math '
+                    'roles/directives.\n\nPlease use one language only.')
+            elif md_blockquote:
+                detector['errors'] = (
+                    'You have mixed Markdown blockquotes with reStructuredText math '
+                    'roles/directives.\n\nPlease use one language only.')
+        detector['language'] = 'Markdown'
 
     elif md_header or md_blockquote:
         detector['language'] = 'Markdown'
 
+    elif rst_header:
+        detector['language'] = 'reStructuredText'
+
     return detector
 
 
@@ -321,6 +347,10 @@ def detect_markup_language_old(text):
 
 
 def apply_markdown_preserving_displayed_maths_bracket(text):
+    """
+    Subsidiary function called by ``apply_markdown_preserving_displayed_maths``.
+    See explanations in docstring of that method.
+    """
     part = text.partition(r'\[')
     part2 = part[2].partition(r'\]')
     return '%s%s%s%s%s' % (
diff --git a/markup/views.py b/markup/views.py
index ea4fea6026df25dba6e5933eaec91711395957b0..b5e254e44f6b62d6f280e389d3853179470aa461 100644
--- a/markup/views.py
+++ b/markup/views.py
@@ -6,8 +6,7 @@ from django.contrib.auth.decorators import login_required
 from django.http import JsonResponse
 from django.shortcuts import render
 
-from .constants import MathSnippets, PlainTextSnippets,\
-    MarkdownSnippets, ReStructuredTextSnippets
+from .constants import PlainTextSnippets, MarkdownSnippets, ReStructuredTextSnippets
 from .forms import MarkupTextForm
 
 
@@ -39,7 +38,6 @@ def plaintext_help(request):
     Help page for plain text.
     """
     context = {
-        'math_snippets': MathSnippets,
         'snippets': PlainTextSnippets,
     }
     return render(request, 'markup/plaintext_help.html', context)
@@ -49,7 +47,6 @@ def markdown_help(request):
     Help page for Markdown.
     """
     context = {
-        'math_snippets': MathSnippets,
         'snippets': MarkdownSnippets,
     }
     return render(request, 'markup/markdown_help.html', context)
@@ -60,7 +57,6 @@ def restructuredtext_help(request):
     Help page for reStructuredText.
     """
     context = {
-        'math_snippets': MathSnippets,
         'snippets': ReStructuredTextSnippets,
     }
     return render(request, 'markup/restructuredtext_help.html', context)