diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 0000000..4f34320
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,19 @@
+version: 2
+
+build:
+ os: "ubuntu-24.04"
+ tools:
+ python: "mambaforge-4.10"
+
+sphinx:
+ configuration: docs/conf.py
+ fail_on_warning: true
+
+conda:
+ environment: docs/environment.yaml
+
+python:
+ # Install our python package before building the docs
+ install:
+ - method: pip
+ path: .
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..3d51b09
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+SPHINXPROJ = pontibus
+SOURCEDIR = .
+BUILDDIR = _build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs/_ext/sass.py b/docs/_ext/sass.py
new file mode 100644
index 0000000..43888aa
--- /dev/null
+++ b/docs/_ext/sass.py
@@ -0,0 +1,88 @@
+"""
+sphinxcontrib-sass
+https://github.com/attakei-lab/sphinxcontrib-sass
+Kayuza Takei
+Apache 2.0
+
+Modified to:
+- Write directly to Sphinx output directory
+- Infer targets if not given
+- Ensure ``target: Path`` in ``configure_path()``
+- Return version number and thread safety from ``setup()``
+- Use compressed style by default
+- More complete type checking
+"""
+
+from os import PathLike
+from pathlib import Path
+from typing import Optional, Union
+
+
+import sass
+from sphinx.application import Sphinx
+from sphinx.environment import BuildEnvironment
+from sphinx.util import logging
+
+
+logger = logging.getLogger(__name__)
+
+
+def configure_path(conf_dir: str, src: Optional[Union[PathLike, Path]]) -> Path:
+ if src is None:
+ target = Path(conf_dir)
+ else:
+ target = Path(src)
+ if not target.is_absolute():
+ target = Path(conf_dir) / target
+ return target
+
+
+def get_targets(app: Sphinx) -> dict[Path, Path]:
+ src_dir = configure_path(app.confdir, app.config.sass_src_dir)
+ dst_dir = configure_path(app.outdir, app.config.sass_out_dir)
+
+ if isinstance(app.config.sass_targets, dict):
+ targets = app.config.sass_targets
+ else:
+ targets = {
+ path: path.relative_to(src_dir).with_suffix(".css")
+ for path in src_dir.glob("**/[!_]*.s[ca]ss")
+ }
+
+ return {src_dir / src: dst_dir / dst for src, dst in targets.items()}
+
+
+def build_sass_sources(app: Sphinx, env: BuildEnvironment):
+ logger.debug("Building stylesheet files")
+ include_paths = [str(p) for p in app.config.sass_include_paths]
+ targets = get_targets(app)
+ output_style = app.config.sass_output_style
+ # Build css files
+ for src, dst in targets.items():
+ content = src.read_text()
+ css = sass.compile(
+ string=content,
+ output_style=output_style,
+ include_paths=[str(src.parent)] + include_paths,
+ )
+ dst.parent.mkdir(exist_ok=True, parents=True)
+ dst.write_text(css)
+
+
+def setup(app: Sphinx):
+ """
+ Setup function for this extension.
+ """
+ logger.debug(f"Using {__name__}")
+ app.add_config_value("sass_include_paths", [], "html")
+ app.add_config_value("sass_src_dir", None, "html")
+ app.add_config_value("sass_out_dir", None, "html")
+ app.add_config_value("sass_targets", None, "html")
+ app.add_config_value("sass_output_style", "compressed", "html")
+ app.connect("env-updated", build_sass_sources)
+
+ return {
+ "version": "0.3.4ofe",
+ "parallel_read_safe": True,
+ "parallel_write_safe": True,
+ }
diff --git a/docs/_static/API.svg b/docs/_static/API.svg
new file mode 100644
index 0000000..9c2cb31
--- /dev/null
+++ b/docs/_static/API.svg
@@ -0,0 +1 @@
+
diff --git a/docs/_static/CLI.svg b/docs/_static/CLI.svg
new file mode 100644
index 0000000..3d170a9
--- /dev/null
+++ b/docs/_static/CLI.svg
@@ -0,0 +1 @@
+
diff --git a/docs/_static/Cookbook.svg b/docs/_static/Cookbook.svg
new file mode 100644
index 0000000..d2f72b4
--- /dev/null
+++ b/docs/_static/Cookbook.svg
@@ -0,0 +1 @@
+
diff --git a/docs/_static/Download.svg b/docs/_static/Download.svg
new file mode 100644
index 0000000..3e425ca
--- /dev/null
+++ b/docs/_static/Download.svg
@@ -0,0 +1 @@
+
diff --git a/docs/_static/Rocket.svg b/docs/_static/Rocket.svg
new file mode 100644
index 0000000..ae1ed81
--- /dev/null
+++ b/docs/_static/Rocket.svg
@@ -0,0 +1 @@
+
diff --git a/docs/_static/Showcase.svg b/docs/_static/Showcase.svg
new file mode 100644
index 0000000..953eb0d
--- /dev/null
+++ b/docs/_static/Showcase.svg
@@ -0,0 +1,75 @@
+
+
+
+
diff --git a/docs/_static/Squaredcircle.svg b/docs/_static/Squaredcircle.svg
new file mode 100644
index 0000000..0c622a5
--- /dev/null
+++ b/docs/_static/Squaredcircle.svg
@@ -0,0 +1,21 @@
+
+
diff --git a/docs/_static/Tutorial.svg b/docs/_static/Tutorial.svg
new file mode 100644
index 0000000..a42592d
--- /dev/null
+++ b/docs/_static/Tutorial.svg
@@ -0,0 +1 @@
+
diff --git a/docs/_static/UserGuide.svg b/docs/_static/UserGuide.svg
new file mode 100644
index 0000000..e8cf53a
--- /dev/null
+++ b/docs/_static/UserGuide.svg
@@ -0,0 +1 @@
+
diff --git a/docs/_templates/README.md b/docs/_templates/README.md
new file mode 100644
index 0000000..485f82a
--- /dev/null
+++ b/docs/_templates/README.md
@@ -0,0 +1,14 @@
+# Templates Doc Directory
+
+Add any paths that contain templates here, relative to
+the `conf.py` file's directory.
+They are copied after the builtin template files,
+so a file named "page.html" will overwrite the builtin "page.html".
+
+The path to this folder is set in the Sphinx `conf.py` file in the line:
+```python
+html_static_path = ['_templates']
+```
+
+## Examples of file to add to this directory
+* HTML extensions of stock pages like `page.html` or `layout.html`
diff --git a/docs/api.rst b/docs/api.rst
new file mode 100644
index 0000000..236565d
--- /dev/null
+++ b/docs/api.rst
@@ -0,0 +1,9 @@
+API Documentation
+=================
+
+
+.. toctree::
+ :maxdepth: 4
+ :caption: API Contents:
+
+ api/protocols/index
diff --git a/docs/api/protocols/asfe_protocol.rst b/docs/api/protocols/asfe_protocol.rst
new file mode 100644
index 0000000..d4dbf9b
--- /dev/null
+++ b/docs/api/protocols/asfe_protocol.rst
@@ -0,0 +1,40 @@
+Absolute Solvation Free Energy (ASFE) Protocol
+==============================================
+
+.. _asfe protocol api:
+
+A Protocol for running arbitrary solvent solvation free energy calculations.
+
+
+Protocol API Specification
+--------------------------
+
+.. module:: pontibus.protocols.solvation
+
+.. autosummary::
+ :nosignatures:
+ :toctree: generated/
+
+ ASFEProtocol
+ ASFEProtocolResult
+ ASFESettings
+ ASFESolventUnit
+ ASFEVacuumUnit
+
+
+Protocol Settings
+-----------------
+
+.. module:: pontibus.protocols.solvation.settings
+
+.. autopydantic_model:: ASFESettings
+ :model-show-json: False
+ :model-show-field-summary: False
+ :model-show-config-member: False
+ :model-show-config-summary: False
+ :model-show-validator-members: False
+ :model-show-validator-summary: False
+ :field-list-validators: False
+ :inherited-members: SettingsBaseModel
+ :exclude-members: get_defaults
+ :member-order: bysource
diff --git a/docs/api/protocols/index.rst b/docs/api/protocols/index.rst
new file mode 100644
index 0000000..c82b7db
--- /dev/null
+++ b/docs/api/protocols/index.rst
@@ -0,0 +1,10 @@
+.. _api:
+
+
+Pontibus Protocols API Reference
+================================
+
+.. toctree::
+ :maxdepth: 2
+
+ asfe_protocol
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..b94b4cc
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,177 @@
+#
+# Configuration file for the Sphinx documentation builder.
+#
+# This file does only contain a selection of the most common options. For a
+# full list see the documentation:
+# http://www.sphinx-doc.org/en/stable/config
+
+# -- Path setup --------------------------------------------------------------
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+
+# Incase the project was not installed
+import os
+from pathlib import Path
+import shutil
+import sys
+sys.path.insert(0, os.path.abspath('..'))
+
+import pontibus
+
+
+# -- Project information -----------------------------------------------------
+
+project = 'pontibus'
+copyright = ("2024, Open Free Energy.")
+author = 'The OpenFE Development Team'
+
+# The short X.Y version
+version = ''
+# The full version, including alpha/beta/rc tags
+release = ''
+
+
+# -- General configuration ---------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+
+extensions = [
+ "sphinx.ext.autodoc",
+ "sphinx.ext.napoleon",
+ "sphinx_click.ext",
+ "sphinxcontrib.autodoc_pydantic",
+ "sphinx_toolbox.collapse",
+ "sphinx.ext.autosectionlabel",
+ "sphinx_design",
+ "sphinx.ext.intersphinx",
+ "sphinx.ext.autosummary",
+ "docs._ext.sass",
+ "myst_parser",
+ "nbsphinx",
+ "nbsphinx_link",
+ "sphinx.ext.mathjax",
+]
+
+
+intersphinx_mapping = {
+ "python": ("https://docs.python.org/3.10", None),
+ "numpy": ("https://numpy.org/doc/stable", None),
+ "scipy": ("https://docs.scipy.org/doc/scipy", None),
+ "scikit.learn": ("https://scikit-learn.org/stable", None),
+ "openmm": ("http://docs.openmm.org/latest/api-python/", None),
+ "rdkit": ("https://www.rdkit.org/docs", None),
+ "openeye": ("https://docs.eyesopen.com/toolkits/python/", None),
+ "mdtraj": ("https://www.mdtraj.org/1.9.5/", None),
+ "openff.units": ("https://docs.openforcefield.org/projects/units/en/stable", None),
+ "gufe": ("https://gufe.readthedocs.io/en/latest/", None),
+ "openfe": ("https://openfe.readthedocs.io/en/latest/", None),
+}
+
+autoclass_content = "both"
+# Make sure labels are unique
+# https://www.sphinx-doc.org/en/master/usage/extensions/autosectionlabel.html#confval-autosectionlabel_prefix_document
+autosectionlabel_prefix_document = True
+
+autodoc_pydantic_model_show_json = False
+
+autodoc_default_options = {
+ "members": True,
+ "member-order": "bysource",
+ "inherited-members": "GufeTokenizable,BaseModel",
+ "undoc-members": True,
+ "special-members": "__call__",
+}
+toc_object_entries_show_parents = "hide"
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
+exclude_patterns = [
+ "_build",
+ "**/Thumbs.db",
+ "**/.DS_Store",
+ "_ext",
+ "_sass",
+ "README.md",
+ "**/README.md",
+ "ExampleNotebooks",
+]
+
+autodoc_mock_imports = [
+ "matplotlib",
+ "mdtraj",
+ "openmmforcefields",
+ "openmmtools",
+ "pymbar",
+]
+
+# Extensions for the myst parser
+myst_enable_extensions = [
+ "dollarmath",
+ "colon_fence",
+ "smartquotes",
+ "replacements",
+ "deflist",
+ "attrs_inline",
+]
+myst_heading_anchors = 3
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = "ofe_sphinx_theme"
+html_theme_options = {
+ "logo": {"text": "OpenFE GROMACS Protocols"},
+ "icon_links": [
+ {
+ "name": "GitHub",
+ "url": "https://github.com/OpenFreeEnergy/pontibus",
+ "icon": "fa-brands fa-square-github",
+ "type": "fontawesome",
+ }
+ ],
+ "accent_color": "DarkGoldenYellow",
+ "navigation_with_keys": False,
+}
+html_logo = "_static/Squaredcircle.svg"
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+# html_static_path = ['_static']
+
+
+# replace macros
+rst_prolog = """
+.. |rdkit.mol| replace:: :class:`rdkit.Chem.rdchem.Mol`
+"""
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ["_static"]
+
+## Add below when we have notebooks
+#example_notebooks_path = Path("ExampleNotebooks")
+#
+#try:
+# if example_notebooks_path.exists():
+# pass
+# else:
+# source = Path("../examples")
+# shutil.copytree(source, example_notebooks_path)
+#except Exception as e:
+# raise OSError("Could not copy over example notebooks")
diff --git a/docs/environment.yaml b/docs/environment.yaml
new file mode 100644
index 0000000..6ff3691
--- /dev/null
+++ b/docs/environment.yaml
@@ -0,0 +1,28 @@
+name: docs
+channels:
+- conda-forge
+dependencies:
+- autodoc-pydantic<2.0
+- openfe>=1.1.0
+- packaging
+- plugcli
+- python=3.10
+- sphinx<7
+- sphinx-click
+- gitpython
+- libsass
+- nbsphinx
+- nbsphinx-link
+- myst-parser
+- pip:
+ - sphinx-design
+ - sphinx-toolbox
+ - sphinx<7
+ - git+https://github.com/OpenFreeEnergy/ofe-sphinx-theme@main
+
+# These are added automatically by RTD, so we include them here
+# for a consistent environment.
+- mock
+- pillow
+- sphinx
+- sphinx_rtd_theme
diff --git a/docs/getting_started.rst b/docs/getting_started.rst
new file mode 100644
index 0000000..96fa815
--- /dev/null
+++ b/docs/getting_started.rst
@@ -0,0 +1,19 @@
+Getting Started
+===============
+
+This page details how to get started with pontibus.
+
+
+Developer Install
+*****************
+
+To install the development version of the pontibus, you should do a source
+installation in the following manner::
+
+ git clone https://github.com/OpenFreeEnergy/pontibus.git
+
+ cd pontibus
+ mamba env create -f environment.yml
+
+ mamba activate pontibus
+ python -m pip install -e .
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..459416c
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,23 @@
+.. pontibus documentation index
+
+Welcome to pontibus' documentation!
+===================================
+
+Pontibus is a set of experimental OpenFE Free Energy Protocols
+aimed specifically at facilitating the validation of OpenFF Force Fields.
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ getting_started
+ api
+
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
diff --git a/docs/make.bat b/docs/make.bat
new file mode 100644
index 0000000..d3954ea
--- /dev/null
+++ b/docs/make.bat
@@ -0,0 +1,36 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=.
+set BUILDDIR=_build
+set SPHINXPROJ=pontibus
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+
+:end
+popd