diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 9a2f90e..0f1ac9d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -35,3 +35,13 @@ test:
wheel_file=${wheels[0]}
python -m pip install --group dev ${wheel_file}
make test
+
+docs:
+ stage: test
+ script:
+ - python -m pip install --group docs .
+ - make docs
+ artifacts:
+ paths:
+ - docs/site/*
+ expire_in: 1 week
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 0000000..ab2c295
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,15 @@
+version: 2
+build:
+ os: ubuntu-24.04
+ tools:
+ python: '3.14'
+ jobs:
+ install:
+ - pip install --upgrade pip
+ - pip install --group 'docs'
+ build:
+ html:
+ - make docs
+ post_build:
+ - mkdir -p $READTHEDOCS_OUTPUT/html/
+ - cp --recursive docs/site/* $READTHEDOCS_OUTPUT/html/
diff --git a/Makefile b/Makefile
index 881dd32..769bfac 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
# Commands used by CI
-.PHONY: format lint build test
+.PHONY: format lint build test docs
format:
ruff check --fix
@@ -17,3 +17,7 @@ build:
test:
pytest
python -m doctest README.md
+
+docs:
+ python docs/make.py
+ zensical build -f docs/zensical.toml --clean
diff --git a/README.md b/README.md
index 4379283..ad0a84c 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,7 @@
[](https://github.com/ValkyrieSystems/jbpy/actions/workflows/test.yml)
**jbpy** is a library for reading and writing Joint BIIF Profile files. Including:
+
* National Imagery Transmission Format (NITF)
* North Atlantic Treaty Organisation (NATO) Secondary Imagery Format (NSIF)
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 0000000..a49ebec
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1,2 @@
+src/api/
+site/
diff --git a/docs/make.py b/docs/make.py
new file mode 100644
index 0000000..97cd1a3
--- /dev/null
+++ b/docs/make.py
@@ -0,0 +1,26 @@
+import pathlib
+import shutil
+
+import pdoc
+import pdoc.render
+
+here = pathlib.Path(__file__).parent
+out = here / "src" / "api"
+if out.exists():
+ shutil.rmtree(out)
+
+# Render parts of pdoc's documentation into src/api...
+pdoc.render.configure(
+ docformat="numpy",
+ template_directory=here / "pdoc-template",
+)
+modules = [
+ "jbpy",
+ "jbpy.core",
+ "jbpy.image_data",
+]
+pdoc.pdoc(*modules, output_directory=out)
+
+# ...and rename the .html files to .md so that zensical picks them up!
+for f in out.glob("**/*.html"):
+ f.rename(f.with_suffix(".md"))
diff --git a/docs/pdoc-template/frame.html.jinja2 b/docs/pdoc-template/frame.html.jinja2
new file mode 100644
index 0000000..9584875
--- /dev/null
+++ b/docs/pdoc-template/frame.html.jinja2
@@ -0,0 +1,20 @@
+---
+title: {{ module.modulename if module else "API Reference" }}
+---
+
+
+ {% block content %}{% endblock %}
+
+ {% filter minify_css %}
+ {% block style %}
+ {#
+ The important part is that we leave out layout.css here.
+ Ideally we would still include Bootstrap Reboot, but that breaks mkdocs' theme.
+
+ #}
+
+
+
+ {% endblock %}
+ {% endfilter %}
+
diff --git a/docs/src/index.md b/docs/src/index.md
new file mode 100644
index 0000000..612c7a5
--- /dev/null
+++ b/docs/src/index.md
@@ -0,0 +1 @@
+--8<-- "README.md"
diff --git a/docs/zensical.toml b/docs/zensical.toml
new file mode 100644
index 0000000..56fb3cc
--- /dev/null
+++ b/docs/zensical.toml
@@ -0,0 +1,64 @@
+[project]
+site_name = "jbpy Documentation"
+site_description = "Documentation for jbpy: a library for reading and writing Joint BIIF Profile files."
+site_author = "Valkyrie Systems Corporation"
+#site_url = "https://www.example.com/" TODO: set once hosted
+repo_name = "ValkyrieSystems/jbpy"
+repo_url = "https://github.com/ValkyrieSystems/jbpy"
+docs_dir = "src"
+use_directory_urls = false
+
+copyright = """
+Copyright © 2026, Valkyrie Systems Corporation
+"""
+
+nav = [
+ { "Get started" = "index.md"},
+ {"API Reference" = [
+ {"jbpy" = "api/jbpy.md"},
+ {"jbpy.core" = "api/jbpy/core.md"},
+ {"jbpy.image_data" = "api/jbpy/image_data.md"},
+ ]}
+]
+
+
+# ----------------------------------------------------------------------------
+# Section for configuring theme options
+# ----------------------------------------------------------------------------
+[project.theme]
+language = "en"
+logo = "https://raw.githubusercontent.com/ValkyrieSystems/sarkit/main/docs/source/_static/sarkit_logo.png"
+
+# Zensical provides a number of feature toggles that change the behavior
+# of the documentation site.
+features = [
+ "announce.dismiss",
+ "content.code.annotate",
+ "content.code.copy",
+ "content.code.select",
+ "content.footnote.tooltips",
+ "content.tabs.link",
+ "content.tooltips",
+ "navigation.footer",
+ "navigation.indexes",
+ "navigation.instant",
+ "navigation.instant.prefetch",
+ "navigation.path",
+ "navigation.sections",
+ "navigation.top",
+ "navigation.tracking",
+ "search.highlight",
+]
+
+[project.theme.icon]
+repo = "fontawesome/brands/github"
+
+[project.markdown_extensions.pymdownx.highlight]
+anchor_linenums = true
+line_spans = "__span"
+pygments_lang_class = true
+[project.markdown_extensions.pymdownx.inlinehilite]
+[project.markdown_extensions.pymdownx.snippets]
+[project.markdown_extensions.pymdownx.superfences]
+[project.markdown_extensions.admonition]
+[project.markdown_extensions.pymdownx.details]
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index bc58abd..16a24e8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -63,6 +63,11 @@ examples = [
"pillow",
]
+docs = [
+ "pdoc>=16.0.0",
+ "zensical>=0.0.18",
+]
+
[project.urls]
Repository = "https://github.com/ValkyrieSystems/jbpy"
"Bug Tracker" = "https://github.com/ValkyrieSystems/jbpy/issues"