diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 149f0473317cd4ffbe6e1f35ed5d2a8f02105369..f928a7f90bbf12c8ec659b838cee07a784d052c4 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -24,6 +24,23 @@ jobs:
                 curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/prepare-and-run-flake8.sh
                 . ./prepare-and-run-flake8.sh sumpy test
 
+    docs:
+        name: Documentation
+        runs-on: ubuntu-latest
+        steps:
+        -   uses: actions/checkout@v2
+        -
+            uses: actions/setup-python@v1
+            with:
+                python-version: '3.x'
+        -   name: "Main Script"
+            run: |
+                CONDA_ENVIRONMENT=.test-conda-env-py3.yml
+                curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/ci-support.sh
+                . ci-support.sh
+                build_py_project_in_conda_env
+                build_docs
+
     pytest3:
         name: Conda Pytest Py3
         runs-on: ubuntu-latest
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 2b81f42666a61e9b026ece1f839a889d3ca63766..32d0401c0d4c963ac7367354a68175456f50b323 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -91,8 +91,6 @@ Documentation:
   - ". ./build-docs.sh"
   tags:
   - python3
-  only:
-  - master
 
 Flake8:
   script:
diff --git a/doc/conf.py b/doc/conf.py
index 4aa98d14668215cd5cfe7ed3f015ed28ed2a6888..55d9766a664f6d04d52b0af1faac279c48673815 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -159,7 +159,7 @@ html_sidebars = {
 # 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']
+# html_static_path = ['_static']
 
 # Add any extra paths that contain custom files (such as robots.txt or
 # .htaccess) here, relative to this directory. These files are copied
@@ -309,12 +309,14 @@ texinfo_documents = [
 
 
 intersphinx_mapping = {
-    'http://docs.python.org/': None,
-    'http://docs.scipy.org/doc/numpy/': None,
-    'http://documen.tician.de/modepy/': None,
-    'http://documen.tician.de/pyopencl/': None,
-    'http://documen.tician.de/pymbolic/': None,
-    'http://documen.tician.de/loopy/': None,
-    'http://documen.tician.de/pytential/': None,
-    'http://documen.tician.de/boxtree/': None,
+    'https://docs.python.org/3/': None,
+    'https://numpy.org/doc/stable/': None,
+    'https://documen.tician.de/modepy/': None,
+    'https://documen.tician.de/pyopencl/': None,
+    'https://documen.tician.de/pymbolic/': None,
+    'https://documen.tician.de/loopy/': None,
+    'https://documen.tician.de/pytential/': None,
+    'https://documen.tician.de/boxtree/': None,
+    'https://docs.sympy.org/latest/': None,
+    'https://matplotlib.org/': None,
     }
diff --git a/doc/index.rst b/doc/index.rst
index 516a51a9217fa1c095d000f23a37a9b35e8bd326..26dab1f8c2c4db257292454de95d5bf3208a09fb 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -1,6 +1,8 @@
 Welcome to sumpy's documentation!
 =================================
 
+.. automodule:: sumpy
+
 Example
 -------
 
diff --git a/doc/misc.rst b/doc/misc.rst
index 113427ede53e0c739dcd764b617b2c7bad0d1717..b728f098a49fced6ae19310234526d6b84823d29 100644
--- a/doc/misc.rst
+++ b/doc/misc.rst
@@ -1,3 +1,9 @@
+Misc Tools
+==========
+
+.. automodule:: sumpy.tools
+
+
 Installation
 ============
 
diff --git a/sumpy/kernel.py b/sumpy/kernel.py
index 53b8a5506d4945fa54fb7229040fd57ee723f6bc..bb96f598fc5ddc60dc6079064b5987c64075d79c 100644
--- a/sumpy/kernel.py
+++ b/sumpy/kernel.py
@@ -81,7 +81,7 @@ class KernelArgument(object):
     """
     .. attribute:: loopy_arg
 
-        A :class:`loopy.Argument` instance describing the type,
+        A :class:`loopy.KernelArgument` instance describing the type,
         name, and other features of this kernel argument when
         passed to a generated piece of code.
     """
diff --git a/sumpy/point_calculus.py b/sumpy/point_calculus.py
index fc164d81b226c0ed2e38f2e60c68d4cd466c8b7e..38a5f05b74f9afcf87094c806278747fa1f0998d 100644
--- a/sumpy/point_calculus.py
+++ b/sumpy/point_calculus.py
@@ -37,9 +37,9 @@ class CalculusPatch(object):
     """Sets up a grid of points on which derivatives can be calculated. Useful
     to verify that an evaluated potential actually solves a PDE.
 
-    .. attribute: dim
+    .. attribute:: dim
 
-    .. attribute: points
+    .. attribute:: points
 
         shape: ``(dim, npoints_total)``
 
@@ -48,7 +48,7 @@ class CalculusPatch(object):
     .. automethod:: diff
     .. automethod:: dx
     .. automethod:: dy
-    .. automethod:: dy
+    .. automethod:: dz
     .. automethod:: laplace
     .. automethod:: div
     .. automethod:: curl
@@ -116,9 +116,9 @@ class CalculusPatch(object):
         return self._vandermonde_1d()[0]
 
     def basis(self):
-        """"
+        """
         :returns: a :class:`list` containing functions that realize
-            a high-order interpolation basis on the :attr:`points`.
+            a high-order interpolation basis on the :py:attr:`points`.
         """
 
         from pytools import indices_in_shape
@@ -211,9 +211,9 @@ class CalculusPatch(object):
         return sum(self.diff(iaxis, f_values, 2) for iaxis in range(self.dim))
 
     def div(self, arg):
-        """
+        r"""
         :arg arg: an object array containing
-            :class:`numpy.ndarrays` with shape ``(npoints_total,)``.
+            :class:`numpy.ndarray`\ s with shape ``(npoints_total,)``.
         """
         result = 0
         for i, arg_i in enumerate(arg):
@@ -222,10 +222,10 @@ class CalculusPatch(object):
         return result
 
     def curl(self, arg):
-        """Take the curl of the vector quantity *arg*.
+        r"""Take the curl of the vector quantity *arg*.
 
         :arg arg: an object array of shape ``(3,)`` containing
-            :class:`numpy.ndarrays` with shape ``(npoints_total,)``.
+            :class:`numpy.ndarray`\ s with shape ``(npoints_total,)``.
         """
         from pytools import levi_civita
         from pytools.obj_array import make_obj_array
diff --git a/sumpy/tools.py b/sumpy/tools.py
index e55906d09ee2cc87672f5040aaab18d2c231066c..2a0a8b2220109ab1fc5c1530a6e261752a60d53d 100644
--- a/sumpy/tools.py
+++ b/sumpy/tools.py
@@ -25,6 +25,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 """
 
+__doc__ = """
+
+ Misc tools
+ ==========
+
+ .. autoclass:: BlockIndexRanges
+ .. autoclass:: MatrixBlockIndexRanges
+"""
+
 import six
 from six.moves import range, zip
 from pytools import memoize_method, memoize_in
@@ -342,6 +351,7 @@ class MatrixBlockIndexRanges(object):
     .. automethod:: block_shape
     .. automethod:: block_take
     .. automethod:: get
+    .. autoattribute:: linear_row_indices
     .. automethod:: take
 
     """
@@ -392,8 +402,8 @@ class MatrixBlockIndexRanges(object):
         friends.
 
         :return: a copy of `self` in which all data lives on the host, i.e.
-        all :class:`pyopencl.array.Array` instances are replaces by
-        :class:`numpy.ndarray` instances.
+                 all :class:`pyopencl.array.Array` instances are replaces by
+                 :class:`numpy.ndarray` instances.
         """
         return MatrixBlockIndexRanges(self.cl_context,
                 row=self.row.get(queue=queue),
diff --git a/sumpy/toys.py b/sumpy/toys.py
index 9bc68ae5e480f043ec4fbc4636839ee0a69d2b45..b7d5c68d35297f4355de9bec9075f105be6ec080 100644
--- a/sumpy/toys.py
+++ b/sumpy/toys.py
@@ -428,7 +428,7 @@ class ExpansionPotentialSource(PotentialSource):
 
     .. attribute:: text_kwargs
 
-       Passed to :method:`matplotlib.pyplot.annotate`. Used for customizing the
+       Passed to :func:`matplotlib.pyplot.annotate`. Used for customizing the
        expansion label. Changing the label text is supported by passing the
        kwarg *s*.  Just for visualization, purely advisory.
     """