diff --git a/README.md b/README.md
deleted file mode 100644
index 67dbf07..0000000
--- a/README.md
+++ /dev/null
@@ -1,90 +0,0 @@
-# ModelArrayIO
-
-**ModelArrayIO** is a Python package that converts between neuroimaging formats (fixel `.mif`, voxel NIfTI, CIFTI-2 dscalar) and the HDF5 (`.h5`) layout used by the R package [ModelArray](https://pennlinc.github.io/ModelArray/). It can also write ModelArray statistical results back to imaging formats.
-
-**Relationship to ConFixel:** The earlier project [**ConFixel**](https://github.com/PennLINC/ConFixel) is superseded by ModelArrayIO. The ConFixel repository is retained for history (including links from publications) and will be archived; new work should use this repository.
-
-Documentation for installation and usage: [ModelArrayIO on GitHub](https://github.com/PennLINC/ModelArrayIO#installation) (this README). For conda, HDF5 libraries, and installing the ModelArray R package, see the ModelArray vignette [Installation](https://pennlinc.github.io/ModelArray/articles/installations.html).
-
-
-
-
-
-
-
-ModelArrayIO provides three converter areas, each with import and export commands:
-
-After [installation](#installation), these commands are available in your terminal:
-
-* **Fixel-wise** data (MRtrix `.mif`):
- * `.mif` → `.h5`: `confixel` (CLI name kept for compatibility with earlier ConFixel workflows)
- * `.h5` → `.mif`: `fixelstats_write`
-* **Voxel-wise** data (NIfTI):
- * NIfTI → `.h5`: `convoxel`
- * `.h5` → NIfTI: `volumestats_write`
-* **Greyordinate-wise** data (CIFTI-2):
- * CIFTI-2 → `.h5`: `concifti`
- * `.h5` → CIFTI-2: `ciftistats_write`
-
-## Installation
-### Install dependent software MRtrix (only required for fixel-wise data `.mif`)
-For fixel-wise `.mif` conversion, the `confixel` / `fixelstats_write` tools use MRtrix `mrconvert`. Install MRtrix from [MRtrix’s webpage](https://www.mrtrix.org/download/) if needed. Run `mrview` in the terminal to verify the installation.
-
-If your data are voxel-wise or CIFTI only, you can skip this step.
-
-### Install ModelArrayIO
-You may want a conda environment first—see [ModelArray: Installation](https://pennlinc.github.io/ModelArray/articles/installations.html). If MRtrix is installed in that environment, install ModelArrayIO in the same environment.
-
-Install from GitHub:
-
-``` console
-git clone https://github.com/PennLINC/ModelArrayIO.git
-cd ModelArrayIO
-pip install . # build via pyproject.toml
-```
-
-Editable install for development:
-
-``` console
-# From the repository root
-pip install -e .
-```
-
-With `hatch` installed, you can build wheels/sdist locally:
-
-``` console
-hatch build
-pip install dist/*.whl
-```
-
-## How to use
-We provide a [walkthrough for fixel-wise data](notebooks/walkthrough_fixel-wise_data.md) (`confixel` / `fixelstats_write`) and a [walkthrough for voxel-wise data](notebooks/walkthrough_voxel-wise_data.md) (`convoxel` / `volumestats_write`).
-
-Together with [ModelArray](https://pennlinc.github.io/ModelArray/), see the [combined walkthrough](https://pennlinc.github.io/ModelArray/articles/walkthrough.html) with example fixel-wise data (ModelArray + ModelArrayIO).
-
-CLI help:
-
-``` console
-confixel --help
-```
-
-Use the same pattern for `convoxel`, `concifti`, `fixelstats_write`, `volumestats_write`, and `ciftistats_write`.
-
-## Storage backends: HDF5 and TileDB
-
-ModelArrayIO supports two on-disk backends for the subject-by-element matrix:
-
-- HDF5 (default), implemented in `modelarrayio/h5_storage.py`
-- TileDB, implemented in `modelarrayio/tiledb_storage.py`
-
-Both backends expose a similar API:
-
-- create a dense 2D array `(subjects, items)` and write all values at once
-- create an empty array with the same shape and write by column stripes
-- write/read column names alongside the data
-
-Notes and minor differences:
-- Chunking vs tiling: HDF5 uses chunks; TileDB uses tiles. We compute tile sizes analogous to chunk sizes to keep write/read patterns similar.
-- Compression: HDF5 uses `gzip` by default; TileDB defaults to `zstd`+shuffle for better speed/ratio. You can switch to `gzip` for parity.
-- Metadata: HDF5 stores `column_names` as a dataset attribute; TileDB stores names as JSON metadata on the array/group.
-- Layout: Both backends keep dimensions in the same order and use zero-based indices.
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..e8ec4e3
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,109 @@
+============
+ModelArrayIO
+============
+
+**ModelArrayIO** is a Python package that converts between neuroimaging formats (fixel ``.mif``, voxel NIfTI, CIFTI-2 dscalar) and the HDF5 (``.h5``) layout used by the R package `ModelArray `_. It can also write ModelArray statistical results back to imaging formats.
+
+**Relationship to ConFixel:** The earlier project `ConFixel `_ is superseded by ModelArrayIO. The ConFixel repository is retained for history (including links from publications) and will be archived; new work should use this repository.
+
+Documentation for installation and usage: `ModelArrayIO on GitHub `_ (this README). For conda, HDF5 libraries, and installing the ModelArray R package, see the ModelArray vignette `Installation `_.
+
+.. readme-overview-figure-placeholder
+
+.. image:: docs/_static/overview_structure.png
+ :align: center
+ :alt: Overview
+
+.. readme-overview-figure-end
+
+ModelArrayIO provides three converter areas, each with import and export commands:
+
+Once ModelArrayIO is installed, these commands are available in your terminal:
+
+* **Fixel-wise** data (MRtrix ``.mif``):
+
+ * ``.mif`` → ``.h5``: ``confixel`` (CLI name kept for compatibility with earlier ConFixel workflows)
+ * ``.h5`` → ``.mif``: ``fixelstats_write``
+
+* **Voxel-wise** data (NIfTI):
+
+ * NIfTI → ``.h5``: ``convoxel``
+ * ``.h5`` → NIfTI: ``volumestats_write``
+
+* **Greyordinate-wise** data (CIFTI-2):
+
+ * CIFTI-2 → ``.h5``: ``concifti``
+ * ``.h5`` → CIFTI-2: ``ciftistats_write``
+
+Installation
+============
+
+MRtrix (required for fixel ``.mif`` only)
+-----------------------------------------
+
+For fixel-wise ``.mif`` conversion, the ``confixel`` / ``fixelstats_write`` tools use MRtrix ``mrconvert``. Install MRtrix from `MRtrix’s webpage `_ if needed. Run ``mrview`` in the terminal to verify the installation.
+
+If your data are voxel-wise or CIFTI only, you can skip this step.
+
+Install ModelArrayIO
+--------------------
+
+You may want a conda environment first—see `ModelArray: Installation `_. If MRtrix is installed in that environment, install ModelArrayIO in the same environment.
+
+Install from GitHub:
+
+.. code-block:: console
+
+ git clone https://github.com/PennLINC/ModelArrayIO.git
+ cd ModelArrayIO
+ pip install . # build via pyproject.toml
+
+Editable install for development:
+
+.. code-block:: console
+
+ # From the repository root
+ pip install -e .
+
+With ``hatch`` installed, you can build wheels/sdist locally:
+
+.. code-block:: console
+
+ hatch build
+ pip install dist/*.whl
+
+How to use
+==========
+
+We provide a `walkthrough for fixel-wise data `_ (``confixel`` / ``fixelstats_write``) and a `walkthrough for voxel-wise data `_ (``convoxel`` / ``volumestats_write``).
+
+Together with `ModelArray `_, see the `combined walkthrough `_ with example fixel-wise data (ModelArray + ModelArrayIO).
+
+CLI help:
+
+.. code-block:: console
+
+ confixel --help
+
+Use the same pattern for ``convoxel``, ``concifti``, ``fixelstats_write``, ``volumestats_write``, and ``ciftistats_write``.
+
+Storage backends: HDF5 and TileDB
+=================================
+
+ModelArrayIO supports two on-disk backends for the subject-by-element matrix:
+
+* HDF5 (default), implemented in ``modelarrayio/h5_storage.py``
+* TileDB, implemented in ``modelarrayio/tiledb_storage.py``
+
+Both backends expose a similar API:
+
+* create a dense 2D array ``(subjects, items)`` and write all values at once
+* create an empty array with the same shape and write by column stripes
+* write/read column names alongside the data
+
+Notes and minor differences:
+
+* Chunking vs tiling: HDF5 uses chunks; TileDB uses tiles. We compute tile sizes analogous to chunk sizes to keep write/read patterns similar.
+* Compression: HDF5 uses ``gzip`` by default; TileDB defaults to ``zstd`` with shuffle for better speed/ratio. You can switch to ``gzip`` for parity.
+* Metadata: HDF5 stores ``column_names`` as a dataset attribute; TileDB stores names as JSON metadata on the array/group.
+* Layout: Both backends keep dimensions in the same order and use zero-based indices.
diff --git a/overview_structure.png b/docs/_static/overview_structure.png
similarity index 100%
rename from overview_structure.png
rename to docs/_static/overview_structure.png
diff --git a/docs/conf.py b/docs/conf.py
index 20c4183..ee1eb27 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -2,8 +2,10 @@
# https://www.sphinx-doc.org/en/master/usage/configuration.html
import os
+import shutil
import sys
from datetime import UTC, datetime
+from pathlib import Path
project = 'ModelArrayIO'
copyright = f'2017-{datetime.now(tz=UTC).strftime("%Y")}, PennLINC developers'
@@ -50,3 +52,22 @@
'modelarrayio',
'https://github.com/pennlinc/ModelArrayIO/blob/{revision}/{package}/{path}#L{lineno}',
)
+
+
+def _sync_overview_figure(app) -> None:
+ """Ensure docs/_static/overview_structure.png exists for the figure in index.rst.
+
+ README.rst references the same path for GitHub/PyPI. The canonical file may live
+ at the repository root (historical layout); copy it into _static before the build
+ when needed so Sphinx can embed it.
+ """
+ docs_dir = Path(app.srcdir).resolve()
+ root_png = docs_dir.parent / 'overview_structure.png'
+ static_png = docs_dir / '_static' / 'overview_structure.png'
+ if root_png.is_file():
+ static_png.parent.mkdir(parents=True, exist_ok=True)
+ shutil.copyfile(root_png, static_png)
+
+
+def setup(app):
+ app.connect('builder-inited', _sync_overview_figure)
diff --git a/docs/index.rst b/docs/index.rst
index 10d33f1..4efddc6 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,4 +1,12 @@
-.. include:: ../README.md
+.. include:: ../README.rst
+ :end-before: .. readme-overview-figure-placeholder
+
+.. figure:: _static/overview_structure.png
+ :align: center
+ :alt: Overview
+
+.. include:: ../README.rst
+ :start-after: .. readme-overview-figure-end
.. toctree::
:maxdepth: 2
diff --git a/notebooks/walkthrough_fixel-wise_data.md b/notebooks/walkthrough_fixel-wise_data.md
index 91f5851..6cfc6a6 100644
--- a/notebooks/walkthrough_fixel-wise_data.md
+++ b/notebooks/walkthrough_fixel-wise_data.md
@@ -1,6 +1,6 @@
# Walkthrough for fixel-wise data conversion
-For fixel-wise data, use the **`confixel`** command (from the **ModelArrayIO** Python package) to convert between MRtrix `.mif` files and the HDF5 file format (`.h5`) that ModelArray uses. This guide assumes you followed the [installation guide](../README.md#installation), installed **ModelArrayIO**, and installed **MRtrix** for fixel-wise workflows.
+For fixel-wise data, use the **`confixel`** command (from the **ModelArrayIO** Python package) to convert between MRtrix `.mif` files and the HDF5 file format (`.h5`) that ModelArray uses. This guide assumes you followed the [installation guide](../README.rst#installation), installed **ModelArrayIO**, and installed **MRtrix** for fixel-wise workflows.
## Prepare data
diff --git a/pyproject.toml b/pyproject.toml
index 9be0db2..9b8dd7a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
[project]
name = "modelarrayio"
description = "ModelArrayIO: convert fixel, voxel, and greyordinate neuroimaging data to/from HDF5 for the ModelArray R package"
-readme = "README.md"
+readme = "README.rst"
requires-python = ">=3.11"
license = { file = "LICENSE" }
authors = [