Repository: sphinx-gallery/sphinx-gallery

Issue:
Rename README.rst to gallery_header.rst
Using the name `README` for the gallery header is slightly misleading. READMEs typically contain instructions/context information directed at the user of the source code. But as it is used in sphinx gallery, it’s just regular content to be inserted into the gallery overview page.

I suggest to introduce a more telling name, e.g. `gallery_header.txt/rst` and advertise it as the recommended name. README may continue as a fallback to maintain backward compatibility.

Discussion:
lucyleeow: For these name change improvements (also #1315) I wonder if we should go through a deprecation cycle and then deprecate the old names?
timhoffm: I wasn't sure how much effort you want burden on existing projects. Sure, the change is quite easy and projects should be able to control which version they use for building.
Deprecation would make the docs simpler, because we don't have to keep the filename variants around. It also makes it easier not to support `GALLERY_HEADER.txt`, which I've basically accepted for simplicity of the code. And finally, we may get away with just switching the tests to `GALLERY_HEADER` and leave `README` untested for the deprecation period.

If a deprecation is acceptable, I'm happy to add it.
timhoffm: Ok, let's not deprecate for now. Could be a v1.0 topic.

Patch:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..f9b4761
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,12 @@
+version: 2
+updates:
+  - package-ecosystem: "github-actions"
+    directory: "/"
+    schedule:
+      interval: "weekly"
+    groups:
+      actions:
+        patterns:
+          - "*"
+    labels:
+      - "maintenance"
diff --git a/.github/release.yml b/.github/release.yml
new file mode 100644
index 0000000..9d1e098
--- /dev/null
+++ b/.github/release.yml
@@ -0,0 +1,5 @@
+changelog:
+  exclude:
+    authors:
+      - dependabot
+      - pre-commit-ci
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 8e2a33a..d52778a 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -19,9 +19,9 @@ jobs:
   package:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Set up Python
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: '3.10'
       - name: Install dependencies
@@ -35,7 +35,7 @@ jobs:
       - name: Check env vars
         run: |
           echo "Triggered by: ${{ github.event_name }}"
-      - uses: actions/upload-artifact@v3
+      - uses: actions/upload-artifact@v4
         with:
           name: dist
           path: dist
@@ -46,7 +46,7 @@ jobs:
     runs-on: ubuntu-latest
     if: github.event_name == 'release'
     steps:
-      - uses: actions/download-artifact@v3
+      - uses: actions/download-artifact@v4
         with:
           name: dist
           path: dist
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 0456cad..48188eb 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,6 +1,6 @@
 repos:
   - repo: https://github.com/astral-sh/ruff-pre-commit
-    rev: v0.4.7
+    rev: v0.4.8
     hooks:
       - id: ruff-format
         exclude: plot_syntaxerror
diff --git a/MANIFEST.in b/MANIFEST.in
index 4d9f0d3..9c70a8e 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -8,7 +8,7 @@ include sphinx_gallery/_static/jupyterlite_badge_logo.svg
 include sphinx_gallery/components/sg_download_links.html
 include sphinx_gallery/components/sg_launcher_links.html
 recursive-include examples *.py
-recursive-include examples *.txt
+recursive-include examples *.rst
 recursive-include tutorials *.py
 recursive-include tutorials *.txt
 recursive-include plotly_examples *.py
diff --git a/doc/configuration.rst b/doc/configuration.rst
index bd1efbc..3fbb259 100644
--- a/doc/configuration.rst
+++ b/doc/configuration.rst
@@ -2376,8 +2376,11 @@ Nesting gallery sections
 
 By default, ``nested_sections=True``.
 In this case, for each folder present in the gallery's root folder,
-Sphinx-Gallery expects to find a readme and uses it to build
-a specific index file for this subsection.
+Sphinx-Gallery expects to find a file ``GALLERY_HEADER.[ext]``, where
+``[ext]`` is 'txt' or an entry in ``sphinx_gallery_conf["source_suffix"]``
+(or ``README.[ext]`` for backward-compatibility). Default recommendation
+is to use ``GALLERY_HEADER.rst``. Sphinx-gallery uses that file
+to build a specific index file for this subsection.
 This index file will contain the section's description and a toctree
 linking to each gallery item which belongs to this subsection.
 
@@ -2409,7 +2412,8 @@ Manually passing files
 
 By default, Sphinx-Gallery creates all the files that are written in the
 sphinx-build directory, either by generating rst and images from a ``*.py``
-in the gallery-source, or from  creating ``index.rst`` from ``README.txt``
+in the gallery-source, or from  creating ``index.rst`` from
+``GALLERY_HEADER.rst`` (or ``README.[rst/txt]`` for backward-compatibility)
 in the gallery-source.  However, sometimes it is desirable to pass files
 from the gallery-source to the sphinx-build.  For example, you may want
 to pass an image that a gallery refers to, but does not generate itself.
@@ -2427,15 +2431,15 @@ across rst files. ::
 Note that if you copy across files rst files, for instance, it is your
 responsibility to ensure that they are in a sphinx ``toctree`` somewhere
 in your document.  You can, of course, add a ``toctree`` to your
-``README.txt``.
+``GALLERY_HEADER.rst``.
 
 Manually passing ``index.rst``
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 You can bypass Sphinx-Gallery automatically creating an  ``index.rst`` from a
-``README.txt`` in a gallery directory or subdirectory. If your
+``GALLERY_HEADER.rst`` in a gallery directory or subdirectory. If your
 ``copyfile_regex`` includes ``index.rst``, and you have an ``index.rst`` in the
-gallery-source instead of the README, Sphinx-Gallery will use that instead of
+gallery-source instead of the 'GALLERY_HEADER' file, Sphinx-Gallery will use that instead of
 the index it automatically makes.  If you do this, you are responsible for
 adding your own Sphinx ``toctree`` in that index (or elsewhere in your Sphinx
 documentation) that includes any gallery items or other files in that
diff --git a/doc/getting_started.rst b/doc/getting_started.rst
index 2eb6c44..9bfc128 100644
--- a/doc/getting_started.rst
+++ b/doc/getting_started.rst
@@ -54,7 +54,7 @@ Let's say your Python project has the following structure:
     └── examples
         ├── plot_example.py
         ├── example.py
-        └── README.txt (or .rst)
+        └── GALLERY_HEADER.rst (or README.rst/.txt)
 
 * ``doc`` is the Sphinx 'source directory'. It contains the Sphinx base
   configuration files. Default versions of these base files can obtained from
@@ -80,7 +80,8 @@ Structure the examples folder
 In order for Sphinx-Gallery to build a gallery from your ``examples`` folder,
 this folder must have the following things:
 
-* **The gallery header**: A file named ``README.txt`` or ``README.rst`` that
+* **The gallery header**: A file named ``GALLERY_HEADER.rst`` (or for
+  backward-compatibility ``README.rst/.txt``) that
   contains reST to be used as a header for the gallery welcome page, which will
   also include thumbnails generated from this folder. It must have at least a
   title. For example::
@@ -106,7 +107,8 @@ this folder must have the following things:
       tuned. See :ref:`capture_repr`.
     * You can have sub-directories in your ``examples`` directory. These will be
       included as sub-sections of your gallery. They **must** contain their own
-      ``README.txt`` or ``README.rst`` file as well.
+      ``GALLERY_HEADER.rst`` (or for backward-compatibility ``README.rst/.txt``)
+      file as well.
 
 .. warning::
 
diff --git a/examples/README.txt b/examples/GALLERY_HEADER.rst
similarity index 86%
rename from examples/README.txt
rename to examples/GALLERY_HEADER.rst
index b03e64f..cd6a0c6 100644
--- a/examples/README.txt
+++ b/examples/GALLERY_HEADER.rst
@@ -11,10 +11,10 @@ this gallery looks like this:
 .. code-block:: none
 
     examples/           # base 'Basics Gallery with Matplotlib' directory
-    ├── README.txt
+    ├── GALLERY_HEADER.rst
     ├── <.py files>
     └── no_output/      # generates the 'No image output examples' sub-gallery
-        ├── README.txt
+        ├── GALLERY_HEADER.rst
         └── <.py files>
 
 .. _general_examples:
@@ -23,4 +23,4 @@ General examples
 ----------------
 
 This gallery consists of introductory examples and examples demonstrating
-specific features of Sphinx-Gallery.
\ No newline at end of file
+specific features of Sphinx-Gallery.
diff --git a/examples/no_output/README.txt b/examples/no_output/GALLERY_HEADER.rst
similarity index 100%
rename from examples/no_output/README.txt
rename to examples/no_output/GALLERY_HEADER.rst
diff --git a/plotly_examples/README.rst b/plotly_examples/GALLERY_HEADER.rst
similarity index 100%
rename from plotly_examples/README.rst
rename to plotly_examples/GALLERY_HEADER.rst
diff --git a/pyvista_examples/README.rst b/pyvista_examples/GALLERY_HEADER.rst
similarity index 100%
rename from pyvista_examples/README.rst
rename to pyvista_examples/GALLERY_HEADER.rst
diff --git a/sphinx_gallery/gen_gallery.py b/sphinx_gallery/gen_gallery.py
index 91f9479..a4e7090 100644
--- a/sphinx_gallery/gen_gallery.py
+++ b/sphinx_gallery/gen_gallery.py
@@ -28,7 +28,7 @@ from .backreferences import _finalize_backreferences
 from .gen_rst import (
     generate_dir_rst,
     SPHX_GLR_SIG,
-    _get_readme,
+    _get_gallery_header,
     _get_class,
     _get_callables,
     _get_call_memory_and_base,
@@ -474,7 +474,7 @@ def get_subsections(srcdir, examples_dir, gallery_conf, check_for_index=True):
     gallery_conf : Dict[str, Any]
         Sphinx-Gallery configuration dictionary.
     check_for_index : bool
-        only return subfolders with a ReadMe, default True
+        only return subfolders contain a GALLERY_HEADER file, default True
 
     Returns
     -------
@@ -492,7 +492,7 @@ def get_subsections(srcdir, examples_dir, gallery_conf, check_for_index=True):
         subfolders = [
             subfolder
             for subfolder in subfolders
-            if _get_readme(
+            if _get_gallery_header(
                 os.path.join(examples_dir, subfolder), gallery_conf, raise_error=False
             )
             is not None
@@ -605,7 +605,7 @@ def generate_gallery_rst(app):
             include_toctree=False,
         )
 
-        has_readme = this_content is not None
+        has_gallery_header = this_content is not None
         costs += this_costs
         write_computation_times(gallery_conf, gallery_dir_abs_path, this_costs)
 
@@ -632,7 +632,7 @@ def generate_gallery_rst(app):
             app.builder.srcdir,
             examples_dir_abs_path,
             gallery_conf,
-            check_for_index=has_readme,
+            check_for_index=has_gallery_header,
         )
         for subsection in subsecs:
             src_dir = os.path.join(examples_dir_abs_path, subsection)
@@ -664,9 +664,9 @@ def generate_gallery_rst(app):
                 )
 
                 indexst += subsection_index_content
-                has_readme_subsection = True
+                has_subsection_header = True
             else:
-                has_readme_subsection = False
+                has_subsection_header = False
 
             # Write subsection toctree in main file only if
             # nested_sections is False or None, and
@@ -679,7 +679,7 @@ def generate_gallery_rst(app):
                     indexst += subsection_index_toctree
             # Otherwise, a new index.rst.new file should
             # have been created and it needs to be parsed
-            elif has_readme_subsection:
+            elif has_subsection_header:
                 _replace_md5(subsection_index_path, mode="t")
 
             costs += subsection_costs
@@ -740,7 +740,7 @@ def generate_gallery_rst(app):
         if app.config.sphinx_gallery_conf["show_signature"]:
             indexst += SPHX_GLR_SIG
 
-        if has_readme:
+        if has_gallery_header:
             index_rst_new = os.path.join(gallery_dir_abs_path, "index.rst.new")
             with codecs.open(index_rst_new, "w", encoding="utf-8") as fhindex:
                 fhindex.write(indexst)
diff --git a/sphinx_gallery/gen_rst.py b/sphinx_gallery/gen_rst.py
index a38709b..7a5ca75 100644
--- a/sphinx_gallery/gen_rst.py
+++ b/sphinx_gallery/gen_rst.py
@@ -427,24 +427,25 @@ def save_thumbnail(image_path_template, src_file, script_vars, file_conf, galler
     _replace_md5(thumb_file, fname_old=fname_old)
 
 
-def _get_readme(dir_, gallery_conf, raise_error=True):
+def _get_gallery_header(dir_, gallery_conf, raise_error=True):
     # first check if there is an index.rst and that index.rst is in the
     # copyfile regexp:
     if re.match(gallery_conf["copyfile_regex"], "index.rst"):
         fpth = os.path.join(dir_, "index.rst")
         if os.path.isfile(fpth):
             return None
-    # now look for README.txt, README.rst etc...
+    # now look for GALLERY_HEADER.txt, GALLERY_HEADER.rst, and
+    # for backward-compatibility README.txt, README.rst etc...
     extensions = [".txt"] + sorted(gallery_conf["source_suffix"])
     for ext in extensions:
-        for fname in ("README", "readme"):
+        for fname in ("GALLERY_HEADER", "README", "readme"):
             fpth = os.path.join(dir_, fname + ext)
             if os.path.isfile(fpth):
                 return fpth
     if raise_error:
         raise ExtensionError(
-            "Example directory {} does not have a README file with one "
-            "of the expected file extensions {}. Please write one to "
+            "Example directory {} does not have a GALLERY_HEADER file with "
+            "one of the expected file extensions {}. Please write one to "
             "introduce your gallery.".format(dir_, extensions)
         )
     return None
@@ -494,12 +495,12 @@ def generate_dir_rst(
     head_ref = os.path.relpath(target_dir, gallery_conf["src_dir"])
 
     subsection_index_content = ""
-    subsection_readme_fname = _get_readme(src_dir, gallery_conf)
+    subsection_header_fname = _get_gallery_header(src_dir, gallery_conf)
     have_index_rst = False
-    if subsection_readme_fname:
-        with codecs.open(subsection_readme_fname, "r", encoding="utf-8") as fid:
-            subsection_readme_content = fid.read()
-            subsection_index_content += subsection_readme_content
+    if subsection_header_fname:
+        with codecs.open(subsection_header_fname, "r", encoding="utf-8") as fid:
+            subsection_header_content = fid.read()
+            subsection_index_content += subsection_header_content
     else:
         have_index_rst = True
 
@@ -598,10 +599,12 @@ def generate_dir_rst(
     copyregex = gallery_conf["copyfile_regex"]
     if copyregex:
         listdir = [fname for fname in os.listdir(src_dir) if re.match(copyregex, fname)]
-        readme = _get_readme(src_dir, gallery_conf, raise_error=False)
-        # don't copy over the readme
-        if readme:
-            listdir = [fname for fname in listdir if fname != os.path.basename(readme)]
+        header_fname = _get_gallery_header(src_dir, gallery_conf, raise_error=False)
+        # don't copy over the gallery_header file
+        if header_fname:
+            listdir = [
+                fname for fname in listdir if fname != os.path.basename(header_fname)
+            ]
         for fname in listdir:
             src_file = os.path.normpath(os.path.join(src_dir, fname))
             target_file = os.path.join(target_dir, fname)
diff --git a/tutorials/README.txt b/tutorials/README.txt
index 43b6f8e..d205b16 100644
--- a/tutorials/README.txt
+++ b/tutorials/README.txt
@@ -1,3 +1,7 @@
+.. This gallery header file is intentionally kept as README.txt and not
+   renamed to GALLERY_HEADER.rst to test the backward compatibility for
+   using README.txt as gallery header during doc build.
+
 .. _notebook_examples:
 
 Notebook-style Narrative Gallery


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 59efa7b..777e450 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -66,7 +66,7 @@ jobs:
           qt: true
           pyvista: false
       # Python (if pip)
-      - uses: actions/setup-python@v4
+      - uses: actions/setup-python@v5
         with:
           python-version: ${{ env.PYTHON_VERSION }}
         if: matrix.distrib != 'mamba'
@@ -108,4 +108,4 @@ jobs:
         if: matrix.distrib != 'minimal' && matrix.sphinx_version != '4'
       - run: make -C doc SPHINXOPTS= html -j 2
         if: matrix.distrib != 'minimal' && matrix.sphinx_version != '4'
-      - uses: codecov/codecov-action@v3
+      - uses: codecov/codecov-action@v4
diff --git a/sphinx_gallery/tests/conftest.py b/sphinx_gallery/tests/conftest.py
index 82b1f27..b7c0a28 100644
--- a/sphinx_gallery/tests/conftest.py
+++ b/sphinx_gallery/tests/conftest.py
@@ -193,7 +193,7 @@ def sphinx_app_wrapper(tmpdir, conf_file, req_mpl, req_pil):
 import os
 import sphinx_gallery
 extensions = {conf_file['extensions']!r}
-exclude_patterns = ['_build']
+exclude_patterns = ['_build', 'src']
 source_suffix = '.rst'
 master_doc = 'index'
 # General information about the project.
diff --git a/sphinx_gallery/tests/test_full.py b/sphinx_gallery/tests/test_full.py
index 57fd8f6..cc1f7ab 100644
--- a/sphinx_gallery/tests/test_full.py
+++ b/sphinx_gallery/tests/test_full.py
@@ -33,19 +33,26 @@ import pytest
 
 # file inventory for tinybuild:
 
-# total number of plot_*.py files in tinybuild/examples + examples_rst_index
-# + examples_with_rst
-N_EXAMPLES = 15 + 3 + 2
+# The following numbers accumulate values across the sub-galleries
+# - tinybuild/examples
+# - tinybuild/examples_rst_index
+# - tinybuild/examples_with_rst
+# - tinybuild/examples_README_header
+#
+# total number of plot_*.py files in
+# (examples + examples_rst_index + examples_with_rst + examples_README_header)
+N_EXAMPLES = 15 + 3 + 2 + 1
 N_FAILING = 2
 N_GOOD = N_EXAMPLES - N_FAILING  # galleries that run w/o error
-# passthroughs and non-executed examples in examples + examples_rst_index
-# + examples_with_rst
-N_PASS = 3 + 0 + 2
-# indices SG generates  (extra non-plot*.py file)
-# + examples_rst_index + examples_with_rst
-N_INDEX = 2 + 1 + 3
-# SG execution times (examples + examples_rst_index + examples_with_rst + root-level)
-N_EXECUTE = 2 + 3 + 1 + 1
+# passthroughs and non-executed examples in
+# (examples + examples_rst_index + examples_with_rst + examples_README_header)
+N_PASS = 3 + 0 + 2 + 0
+# indices SG generates  (extra non-plot*.py file) in
+# (examples + examples_rst_index + examples_with_rst + examples_README_header)
+N_INDEX = 2 + 1 + 3 + 1
+# SG execution times
+# (examples + examples_rst_index + examples_with_rst + examples_README_header + root-level)
+N_EXECUTE = 2 + 3 + 1 + 1 + 1
 # gen_modules + sg_api_usage + doc/index.rst + minigallery.rst
 N_OTHER = 9 + 1 + 1 + 1 + 1
 N_RST = N_EXAMPLES + N_PASS + N_INDEX + N_EXECUTE + N_OTHER
@@ -233,6 +240,7 @@ def test_run_sphinx(sphinx_app):
     assert "auto_examples" in out_files
     assert "auto_examples_with_rst" in out_files
     assert "auto_examples_rst_index" in out_files
+    assert "auto_examples_README_header" in out_files
     generated_examples_dir = op.join(out_dir, "auto_examples")
     assert op.isdir(generated_examples_dir)
     # make sure that indices are properly being passed forward...
diff --git a/sphinx_gallery/tests/test_gen_gallery.py b/sphinx_gallery/tests/test_gen_gallery.py
index cd70c17..c8ac792 100644
--- a/sphinx_gallery/tests/test_gen_gallery.py
+++ b/sphinx_gallery/tests/test_gen_gallery.py
@@ -329,7 +329,7 @@ def test_collect_gallery_files(tmpdir, gallery_conf):
     rel_filepaths = [
         "examples/file1.py",
         "examples/test.rst",
-        "examples/README.txt",
+        "examples/GALLERY_HEADER.rst",
         "examples/folder1/file1.py",
         "examples/folder1/file2.py",
         "examples/folder2/file1.py",
diff --git a/sphinx_gallery/tests/test_gen_rst.py b/sphinx_gallery/tests/test_gen_rst.py
index ed909a6..d7e4c54 100644
--- a/sphinx_gallery/tests/test_gen_rst.py
+++ b/sphinx_gallery/tests/test_gen_rst.py
@@ -623,23 +623,38 @@ def test_exclude_implicit(gallery_conf, exclusion, expected, monkeypatch, req_pi
     assert mock_write_backreferences.call_args.args[0] == expected
 
 
-@pytest.mark.parametrize("ext", (".txt", ".rst", ".bad"))
-def test_gen_dir_rst(gallery_conf, ext):
+@pytest.mark.parametrize(
+    "gallery_header",
+    [
+        "GALLERY_HEADER.rst",
+        "README.txt",
+        "README.rst",
+    ],
+)
+def test_gen_dir_rst(gallery_conf, gallery_header):
     """Test gen_dir_rst."""
-    print(os.listdir(gallery_conf["examples_dir"]))
-    fname_readme = os.path.join(gallery_conf["src_dir"], "README.txt")
-    with open(fname_readme, "wb") as fid:
+    with open(os.path.join(gallery_conf["src_dir"], gallery_header), "wb") as fid:
         fid.write("Testing\n=======\n\nÓscar here.".encode())
-    fname_out = os.path.splitext(fname_readme)[0] + ext
-    if fname_readme != fname_out:
-        shutil.move(fname_readme, fname_out)
-    args = (gallery_conf["src_dir"], gallery_conf["gallery_dir"], gallery_conf, [])
-    if ext == ".bad":  # not found with correct ext
-        with pytest.raises(ExtensionError, match="does not have a README"):
-            generate_dir_rst(*args)
-    else:
-        out = generate_dir_rst(*args)
-        assert "Óscar here" in out[1]
+    out = generate_dir_rst(
+        gallery_conf["src_dir"], gallery_conf["gallery_dir"], gallery_conf, []
+    )
+    assert "Óscar here" in out[1]
+
+
+@pytest.mark.parametrize(
+    "gallery_header",
+    [
+        "GALLERY_HEADER.bad",
+        "README.bad",
+    ],
+)
+def test_gen_dir_rst_invalid_header(gallery_conf, gallery_header):
+    with open(os.path.join(gallery_conf["src_dir"], gallery_header), "wb") as fid:
+        fid.write("Testing\n=======\n\nÓscar here.".encode())
+    with pytest.raises(ExtensionError, match="does not have a GALLERY_HEADER"):
+        generate_dir_rst(
+            gallery_conf["src_dir"], gallery_conf["gallery_dir"], gallery_conf, []
+        )
 
 
 def test_pattern_matching(gallery_conf, log_collector, req_pil):
diff --git a/sphinx_gallery/tests/testconfs/src/README.txt b/sphinx_gallery/tests/testconfs/src/GALLERY_HEADER.rst
similarity index 100%
rename from sphinx_gallery/tests/testconfs/src/README.txt
rename to sphinx_gallery/tests/testconfs/src/GALLERY_HEADER.rst
diff --git a/sphinx_gallery/tests/tinybuild/doc/conf.py b/sphinx_gallery/tests/tinybuild/doc/conf.py
index a6cdc3a..f25b083 100644
--- a/sphinx_gallery/tests/tinybuild/doc/conf.py
+++ b/sphinx_gallery/tests/tinybuild/doc/conf.py
@@ -54,7 +54,12 @@ sphinx_gallery_conf = {
     "jupyterlite": {
         "notebook_modification_function": f"{util_root}.notebook_modification_function",
     },
-    "examples_dirs": ["../examples/", "../examples_with_rst/", "../examples_rst_index"],
+    "examples_dirs": [
+        "../examples/",
+        "../examples_with_rst/",
+        "../examples_rst_index",
+        "../examples_README_header",
+    ],
     "example_extensions": {".py", ".cpp", ".m", ".jl"},
     "filetype_parsers": {".m": "Matlab"},
     "reset_argv": f"{util_root}.reset_argv",
@@ -63,6 +68,7 @@ sphinx_gallery_conf = {
         "auto_examples",
         "auto_examples_with_rst",
         "auto_examples_rst_index",
+        "auto_examples_README_header",
     ],
     "backreferences_dir": "gen_modules/backreferences",
     "subsection_order": f"{util_root}.noop_key",
diff --git a/sphinx_gallery/tests/tinybuild/doc/index.rst b/sphinx_gallery/tests/tinybuild/doc/index.rst
index b607dae..5325592 100644
--- a/sphinx_gallery/tests/tinybuild/doc/index.rst
+++ b/sphinx_gallery/tests/tinybuild/doc/index.rst
@@ -38,3 +38,4 @@ This tests that mini-gallery reference labels work:
    auto_examples/index.rst
    auto_examples_with_rst/index.rst
    auto_examples_rst_index/index.rst
+   auto_examples_README_header/index.rst
diff --git a/sphinx_gallery/tests/tinybuild/examples/README.txt b/sphinx_gallery/tests/tinybuild/examples/GALLERY_HEADER.rst
similarity index 100%
rename from sphinx_gallery/tests/tinybuild/examples/README.txt
rename to sphinx_gallery/tests/tinybuild/examples/GALLERY_HEADER.rst
diff --git a/sphinx_gallery/tests/tinybuild/examples_README_header/README.txt b/sphinx_gallery/tests/tinybuild/examples_README_header/README.txt
new file mode 100644
index 0000000..eac51ba
--- /dev/null
+++ b/sphinx_gallery/tests/tinybuild/examples_README_header/README.txt
@@ -0,0 +1,7 @@
+=========================================
+Example with README.txt as gallery header
+=========================================
+
+This is a backward compatibility test. The recommended gallery header file is
+``GALLERY_HEADER.rst`` nowadays. But we continue to support the older
+``README.txt``.
\ No newline at end of file
diff --git a/sphinx_gallery/tests/tinybuild/examples_README_header/plot_exp.py b/sphinx_gallery/tests/tinybuild/examples_README_header/plot_exp.py
new file mode 100644
index 0000000..ec003c7
--- /dev/null
+++ b/sphinx_gallery/tests/tinybuild/examples_README_header/plot_exp.py
@@ -0,0 +1,14 @@
+"""
+Plot exponential
+================
+
+"""
+
+import numpy as np
+import matplotlib.pyplot as plt
+
+x = np.linspace(-2, 2, 41)
+
+plt.plot(x, np.exp(x))
+# To avoid matplotlib text output
+plt.show()
diff --git a/sphinx_gallery/tests/tinybuild/examples_with_rst/README.txt b/sphinx_gallery/tests/tinybuild/examples_with_rst/GALLERY_HEADER.rst
similarity index 98%
rename from sphinx_gallery/tests/tinybuild/examples_with_rst/README.txt
rename to sphinx_gallery/tests/tinybuild/examples_with_rst/GALLERY_HEADER.rst
index 14c90a5..dbd3d94 100644
--- a/sphinx_gallery/tests/tinybuild/examples_with_rst/README.txt
+++ b/sphinx_gallery/tests/tinybuild/examples_with_rst/GALLERY_HEADER.rst
@@ -36,4 +36,4 @@ Rst files
     rst_example2
 
 Sphinx-gallery files
-====================
\ No newline at end of file
+====================