diff --git a/docs/writing_plugins.rst b/docs/writing_plugins.rst
index a84789b5..a4c96011 100644
--- a/docs/writing_plugins.rst
+++ b/docs/writing_plugins.rst
@@ -325,3 +325,60 @@ This object is exposed in templates as the ``urls`` variable, which can be used
Back to the Homepage
See :ref:`internals_datasette_urls` for full details on this object.
+
+.. _writing_plugins_extra_hooks:
+
+Plugins that define new plugin hooks
+------------------------------------
+
+Plugins can define new plugin hooks that other plugins can use to further extend their functionality.
+
+`datasette-graphql `__ is one example of a plugin that does this. It defines a new hook called ``graphql_extra_fields``, `described here `__, which other plugins can use to define additional fields that should be included in the GraphQL schema.
+
+To define additional hooks, add a file to the plugin called ``datasette_your_plugin/hookspecs.py`` with content that looks like this:
+
+.. code-block:: python
+
+ from pluggy import HookspecMarker
+
+ hookspec = HookspecMarker("datasette")
+
+ @hookspec
+ def name_of_your_hook_goes_here(datasette):
+ "Description of your hook."
+
+You should define your own hook name and arguments here, following the documentation for `Pluggy specifications `__. Make sure to pick a name that is unlikely to clash with hooks provided by any other plugins.
+
+Then, to register your plugin hooks, add the following code to your ``datasette_your_plugin/__init__.py`` file:
+
+.. code-block:: python
+
+ from datasette.plugins import pm
+ from . import hookspecs
+
+ pm.add_hookspecs(hookspecs)
+
+This will register your plugin hooks as part of the ``datasette`` plugin hook namespace.
+
+Within your plugin code you can trigger the hook using this pattern:
+
+.. code-block:: python
+
+ from datasette.plugins import pm
+
+ for plugin_return_value in pm.hook.name_of_your_hook_goes_here(
+ datasette=datasette
+ ):
+ # Do something with plugin_return_value
+
+Other plugins will then be able to register their own implementations of your hook using this syntax:
+
+.. code-block:: python
+
+ from datasette import hookimpl
+
+ @hookimpl
+ def name_of_your_hook_goes_here(datasette):
+ return "Response from this plugin hook"
+
+These plugin implementations can accept 0 or more of the named arguments that you defined in your hook specification.