diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index e16e10cb4..000000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,165 +0,0 @@
-# Thank you!
-
-First off, thank you for considering contributing to beets! It's people like you that make beets continue to succeed.
-
-These guidelines describe how you can help most effectively. By following these guidelines, you can make life easier for the development team as it indicates you respect the maintainers' time; in return, the maintainers will reciprocate by helping to address your issue, review changes, and finalize pull requests.
-
-# Types of Contributions
-
-We love to get contributions from our community—you! There are many ways to contribute, whether you're a programmer or not.
-
-## Non-Programming
-
-* Promote beets! Help get the word out by telling your friends, writing a blog
- post, or discussing it on a forum you frequent.
-* Improve the [documentation][docs]. It's incredibly easy to contribute here:
- just find a page you want to modify and hit the "Edit on GitHub" button in
- the upper-right. You can automatically send us a pull request for your
- changes.
-* GUI design. For the time being, beets is a command-line-only affair. But
- that's mostly because we don't have any great ideas for what a good GUI
- should look like. If you have those great ideas, please get in touch.
-* Benchmarks. We'd like to have a consistent way of measuring speed
- improvements in beets' tagger and other functionality as well as a way of
- comparing beets' performance to other tools. You can help by compiling a
- library of freely-licensed music files (preferably with incorrect metadata)
- for testing and measurement.
-* Think you have a nice config or cool use-case for beets? We'd love to hear about it! Submit a post to our [our forums][forum] under the "Show and Tell" category for a chance to get featured in [the docs][advanced].
-* Consider helping out in [our forums][forum] by responding to support requests or driving some new discussions.
-
-[docs]: http://beets.readthedocs.org/
-[forum]: https://discourse.beets.io/
-[advanced]: https://beets.readthedocs.io/en/stable/guides/advanced.html
-
-## Programming
-
-* As a programmer (even if you're just a beginner!), you have a ton of opportunities to get your feet wet with beets.
-* For developing plugins, or hacking away at beets, there's some good information in the ["For Developers" section of the docs][dev-docs].
-
-[dev-docs]: https://beets.readthedocs.io/en/stable/dev/
-
-### Getting the Source
-
-The easiest way to get started with the latest beets source is to use [pip][] to install an "editable" package. This can be done with one command:
-
- $ pip install -e git+https://github.com/beetbox/beets.git#egg=beets
-
-Or, equivalently:
-
- $ git clone https://github.com/beetbox/beets.git
- $ cd beets
- $ pip install -e .
-
-If you already have a released version of beets installed, you may need to
-remove it first by typing `pip uninstall beets`. The pip command above will put
-the beets source in a `src/beets` directory and install the `beet` CLI script to
-a standard location on your system. You may want to use the `--src` option to specify
-the parent directory where the source will be checked out and the `--user` option
-such that the package will be installed to your home directory (compare with the output of
-`pip install --help`).
-
-[pip]: https://pip.pypa.io/
-
-### Code Contribution Ideas
-
-* We maintain a set of [issues marked as "bite-sized"](https://github.com/beetbox/beets/labels/bitesize). These are issues that would serve as a good introduction to the codebase. Claim one and start exploring!
-* Like testing? Our [test coverage](https://codecov.io/github/beetbox/beets) is somewhat low. You can help out by finding low-coverage modules or checking out other [testing-related issues](https://github.com/beetbox/beets/labels/testing).
-* There are several ways to improve the tests in general (see [Testing](https://github.com/beetbox/beets/wiki/Testing)) and some places to think about performance optimization (see [Optimization](https://github.com/beetbox/beets/wiki/Optimization)).
-* Not all of our code is up to our coding conventions. In particular, the [API documentation](https://beets.readthedocs.io/en/stable/dev/api.html) are currently quite sparse. You can help by adding to the docstrings in the code and to the documentation pages themselves. beets follows [PEP-257](https://www.python.org/dev/peps/pep-0257/) for docstrings and in some places, we also sometimes use [ReST autodoc syntax for Sphinx](https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html) to, for example, refer to a class name.
-
-## Your First Contribution
-
-If this is your first time contributing to an open source project, welcome! If you are confused at all about how to contribute or what to contribute, take a look at [this great tutorial](http://makeapullrequest.com/), or stop by our [forums](https://discourse.beets.io/) if you have any questions.
-
-We maintain a list of issues we reserved for those new to open source labeled ["first timers only"](https://github.com/beetbox/beets/issues?q=is%3Aopen+is%3Aissue+label%3A%22first+timers+only%22). Since the goal of these issues is to get users comfortable with contributing to an open source project, please do not hesitate to ask any questions.
-
-## How to Submit Your Work
-
-Do you have a great bug fix, new feature, or documentation expansion you'd like to contribute? Follow these steps to create a GitHub pull request and your code will ship in no time.
-
-1. Fork the beets repository and clone it (see above) to create a workspace.
-2. Make your changes.
-3. Add tests. If you've fixed a bug, write a test to ensure that you've actually fixed it. If there's a new feature or plugin, please contribute tests that show that your code does what it says.
-4. Add documentation. If you've added a new command flag, for example, find the appropriate page under `docs/` where it needs to be listed.
-5. Add a changelog entry to `docs/changelog.rst` near the top of the document.
-6. Run the tests and style checker. The easiest way to run the tests is to use [tox](https://tox.readthedocs.org/en/latest/). For more information on running tests, see our [Testing wiki page](https://github.com/beetbox/beets/wiki/Testing).
-7. Push to your fork and open a pull request! We'll be in touch shortly.
-8. If you add commits to a pull request, please add a comment or re-request a review after you push them since GitHub doesn't automatically notify us when commits are added.
-
-Remember, code contributions have four parts: the code, the tests, the documentation, and the changelog entry. Thank you for contributing!
-
-
-# The Code
-
-The documentation has an [API section](https://beets.readthedocs.io/en/stable/dev/api.html) that serves as an introduction to beets' design.
-
-## Coding Conventions
-
-There are a few coding conventions we use in beets:
-
-* Whenever you access the library database, do so through the provided Library
- methods or via a Transaction object. Never call `lib.conn.*` directly.
- For example, do this:
- ```
- with g.lib.transaction() as tx:
- rows = tx.query('SELECT DISTINCT "{0}" FROM "{1}" ORDER BY "{2}"'
- .format(field, model._table, sort_field))
- ```
- To fetch Item objects from the database, use lib.items(...) and supply a query as an argument. Resist the urge to write raw SQL for your query. If you must use lower-level queries into the database, do this:
- ```
- with lib.transaction() as tx:
- rows = tx.query('SELECT …')
- ```
- Transaction objects help control concurrent access to the database and assist in debugging conflicting accesses.
-* Always use the [future imports][] `print_function`, `division`, and
- `absolute_import`, but *not* `unicode_literals`. These help keep your code
- modern and will help in the eventual move to Python 3.
-* `str.format()` should be used instead of the `%` operator
-* Never `print` informational messages; use the [logging][] module instead. In
- particular, we have our own logging shim, so you'll see `from beets import
- logging` in most files.
- * Always log Unicode strings (e.g., `log.debug(u"hello world")`).
- * The loggers use [str.format][]-style logging instead of ``%``-style, so
- you can type `log.debug(u"{0}", obj)` to do your formatting.
-* Exception handlers must use `except A as B:` instead of `except A, B:`.
-
-[future imports]: http://docs.python.org/library/__future__.html
-[logging]: http://docs.python.org/library/logging.html
-[str.format]: http://docs.python.org/library/stdtypes.html#str.format
-[modformat]: http://docs.python.org/library/stdtypes.html#string-formatting-operations
-
-We follow [PEP 8](http://www.python.org/dev/peps/pep-0008/) for style. You can use `tox -e lint` to check your code for any style errors.
-
-## Handling Paths
-
-A great deal of convention deals with the handling of **paths**. Paths are
-stored internally—in the database, for instance—as byte strings (i.e., `bytes` instead of `str` in Python 3). This is because POSIX operating systems' path names are only
-reliably usable as byte strings—operating systems typically recommend but do not require that filenames use a given encoding, so violations of any reported encoding are inevitable.
-On Windows, the strings are always encoded with UTF-8; on
-Unix, the encoding is controlled by the filesystem. Here are some guidelines to
-follow:
-
-* If you have a Unicode path or you're not sure whether something is Unicode or
- not, pass it through `bytestring_path` function in the `beets.util` module to
- convert it to bytes.
-* Pass every path name trough the `syspath` function (also in `beets.util`)
- before sending it to any *operating system* file operation (`open`, for
- example). This is necessary to use long filenames (which, maddeningly, must
- be Unicode) on Windows. This allows us to consistently store bytes in the
- database but use the native encoding rule on both POSIX and Windows.
-* Similarly, the `displayable_path` utility function converts bytestring paths
- to a Unicode string for displaying to the user. Every time you want to print
- out a string to the terminal or log it with the `logging` module, feed it
- through this function.
-
-## Editor Settings
-
-Personally, I work on beets with [vim](http://www.vim.org/). Here are some
-`.vimrc` lines that might help with PEP 8-compliant Python coding:
-
- filetype indent on
- autocmd FileType python setlocal shiftwidth=4 tabstop=4 softtabstop=4 expandtab shiftround autoindent
-
-Consider installing [this alternative Python indentation
-plugin](https://github.com/mitsuhiko/vim-python-combined). I also like
-[neomake](https://github.com/neomake/neomake) with its flake8 checker.
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
new file mode 100644
index 000000000..6c024e3d9
--- /dev/null
+++ b/CONTRIBUTING.rst
@@ -0,0 +1,372 @@
+############
+Contributing
+############
+
+.. contents::
+ :depth: 3
+
+Thank you!
+==========
+
+First off, thank you for considering contributing to beets! It’s people
+like you that make beets continue to succeed.
+
+These guidelines describe how you can help most effectively. By
+following these guidelines, you can make life easier for the development
+team as it indicates you respect the maintainers’ time; in return, the
+maintainers will reciprocate by helping to address your issue, review
+changes, and finalize pull requests.
+
+Types of Contributions
+======================
+
+We love to get contributions from our community—you! There are many ways
+to contribute, whether you’re a programmer or not.
+
+Non-Programming
+---------------
+
+- Promote beets! Help get the word out by telling your friends, writing
+ a blog post, or discussing it on a forum you frequent.
+- Improve the `documentation `__. It’s
+ incredibly easy to contribute here: just find a page you want to
+ modify and hit the “Edit on GitHub” button in the upper-right. You
+ can automatically send us a pull request for your changes.
+- GUI design. For the time being, beets is a command-line-only affair.
+ But that’s mostly because we don’t have any great ideas for what a
+ good GUI should look like. If you have those great ideas, please get
+ in touch.
+- Benchmarks. We’d like to have a consistent way of measuring speed
+ improvements in beets’ tagger and other functionality as well as a
+ way of comparing beets’ performance to other tools. You can help by
+ compiling a library of freely-licensed music files (preferably with
+ incorrect metadata) for testing and measurement.
+- Think you have a nice config or cool use-case for beets? We’d love to
+ hear about it! Submit a post to our `our
+ forums `__ under the “Show and Tell”
+ category for a chance to get featured in `the
+ docs `__.
+- Consider helping out in `our forums `__
+ by responding to support requests or driving some new discussions.
+
+Programming
+-----------
+
+- As a programmer (even if you’re just a beginner!), you have a ton of
+ opportunities to get your feet wet with beets.
+- For developing plugins, or hacking away at beets, there’s some good
+ information in the `“For Developers” section of the
+ docs `__.
+
+Getting the Source
+^^^^^^^^^^^^^^^^^^
+
+The easiest way to get started with the latest beets source is to use
+`pip `__ to install an “editable” package. This
+can be done with one command:
+
+.. code-block:: bash
+
+ $ pip install -e git+https://github.com/beetbox/beets.git#egg=beets
+
+Or, equivalently:
+
+.. code-block:: bash
+
+ $ git clone https://github.com/beetbox/beets.git
+ $ cd beets
+ $ pip install -e .
+
+If you already have a released version of beets installed, you may need
+to remove it first by typing ``pip uninstall beets``. The pip command
+above will put the beets source in a ``src/beets`` directory and install
+the ``beet`` CLI script to a standard location on your system. You may
+want to use the ``--src`` option to specify the parent directory where
+the source will be checked out and the ``--user`` option such that the
+package will be installed to your home directory (compare with the
+output of ``pip install --help``).
+
+Code Contribution Ideas
+^^^^^^^^^^^^^^^^^^^^^^^
+
+- We maintain a set of `issues marked as
+ “bite-sized” `__.
+ These are issues that would serve as a good introduction to the
+ codebase. Claim one and start exploring!
+- Like testing? Our `test
+ coverage `__ is somewhat
+ low. You can help out by finding low-coverage modules or checking out
+ other `testing-related
+ issues `__.
+- There are several ways to improve the tests in general (see :ref:`testing` and some
+ places to think about performance optimization (see
+ `Optimization `__).
+- Not all of our code is up to our coding conventions. In particular,
+ the `API
+ documentation `__
+ are currently quite sparse. You can help by adding to the docstrings
+ in the code and to the documentation pages themselves. beets follows
+ `PEP-257 `__ for
+ docstrings and in some places, we also sometimes use `ReST autodoc
+ syntax for
+ Sphinx `__
+ to, for example, refer to a class name.
+
+Your First Contribution
+=======================
+
+If this is your first time contributing to an open source project,
+welcome! If you are confused at all about how to contribute or what to
+contribute, take a look at `this great
+tutorial `__, or stop by our
+`forums `__ if you have any questions.
+
+We maintain a list of issues we reserved for those new to open source
+labeled `“first timers
+only” `__.
+Since the goal of these issues is to get users comfortable with
+contributing to an open source project, please do not hesitate to ask
+any questions.
+
+How to Submit Your Work
+=======================
+
+Do you have a great bug fix, new feature, or documentation expansion
+you’d like to contribute? Follow these steps to create a GitHub pull
+request and your code will ship in no time.
+
+1. Fork the beets repository and clone it (see above) to create a
+ workspace.
+2. Make your changes.
+3. Add tests. If you’ve fixed a bug, write a test to ensure that you’ve
+ actually fixed it. If there’s a new feature or plugin, please
+ contribute tests that show that your code does what it says.
+4. Add documentation. If you’ve added a new command flag, for example,
+ find the appropriate page under ``docs/`` where it needs to be
+ listed.
+5. Add a changelog entry to ``docs/changelog.rst`` near the top of the
+ document.
+6. Run the tests and style checker. The easiest way to run the tests is
+ to use `tox `__. For more
+ information on running tests, see :ref:`testing`.
+7. Push to your fork and open a pull request! We’ll be in touch shortly.
+8. If you add commits to a pull request, please add a comment or
+ re-request a review after you push them since GitHub doesn’t
+ automatically notify us when commits are added.
+
+Remember, code contributions have four parts: the code, the tests, the
+documentation, and the changelog entry. Thank you for contributing!
+
+The Code
+========
+
+The documentation has an `API
+section `__ that
+serves as an introduction to beets’ design.
+
+Coding Conventions
+==================
+
+General
+-------
+There are a few coding conventions we use in beets:
+
+- Whenever you access the library database, do so through the provided
+ Library methods or via a Transaction object. Never call
+ ``lib.conn.*`` directly. For example, do this:
+
+ .. code-block:: python
+
+ with g.lib.transaction() as tx:
+ rows = tx.query('SELECT DISTINCT "{0}" FROM "{1}" ORDER BY "{2}"'
+ .format(field, model._table, sort_field))
+
+ To fetch Item objects from the database, use lib.items(…) and supply
+ a query as an argument. Resist the urge to write raw SQL for your
+ query. If you must use lower-level queries into the database, do
+ this:
+
+ .. code-block:: python
+
+ with lib.transaction() as tx:
+ rows = tx.query('SELECT …')
+
+ Transaction objects help control concurrent access to the database
+ and assist in debugging conflicting accesses.
+- Always use the `future
+ imports `__
+ ``print_function``, ``division``, and ``absolute_import``, but *not*
+ ``unicode_literals``. These help keep your code modern and will help
+ in the eventual move to Python 3.
+- ``str.format()`` should be used instead of the ``%`` operator
+- Never ``print`` informational messages; use the
+ `logging `__ module
+ instead. In particular, we have our own logging shim, so you’ll see
+ ``from beets import logging`` in most files.
+
+ - Always log Unicode strings (e.g., ``log.debug(u"hello world")``).
+ - The loggers use
+ `str.format `__-style
+ logging instead of ``%``-style, so you can type
+ ``log.debug(u"{0}", obj)`` to do your formatting.
+
+- Exception handlers must use ``except A as B:`` instead of
+ ``except A, B:``.
+
+Style
+-----
+We follow `PEP 8 `__ for
+style. You can use ``tox -e lint`` to check your code for any style
+errors.
+
+Handling Paths
+--------------
+
+A great deal of convention deals with the handling of **paths**. Paths
+are stored internally—in the database, for instance—as byte strings
+(i.e., ``bytes`` instead of ``str`` in Python 3). This is because POSIX
+operating systems’ path names are only reliably usable as byte
+strings—operating systems typically recommend but do not require that
+filenames use a given encoding, so violations of any reported encoding
+are inevitable. On Windows, the strings are always encoded with UTF-8;
+on Unix, the encoding is controlled by the filesystem. Here are some
+guidelines to follow:
+
+- If you have a Unicode path or you’re not sure whether something is
+ Unicode or not, pass it through ``bytestring_path`` function in the
+ ``beets.util`` module to convert it to bytes.
+- Pass every path name trough the ``syspath`` function (also in
+ ``beets.util``) before sending it to any *operating system* file
+ operation (``open``, for example). This is necessary to use long
+ filenames (which, maddeningly, must be Unicode) on Windows. This
+ allows us to consistently store bytes in the database but use the
+ native encoding rule on both POSIX and Windows.
+- Similarly, the ``displayable_path`` utility function converts
+ bytestring paths to a Unicode string for displaying to the user.
+ Every time you want to print out a string to the terminal or log it
+ with the ``logging`` module, feed it through this function.
+
+Editor Settings
+^^^^^^^^^^^^^^^
+
+Personally, I work on beets with `vim `__. Here are
+some ``.vimrc`` lines that might help with PEP 8-compliant Python
+coding::
+
+ filetype indent on
+ autocmd FileType python setlocal shiftwidth=4 tabstop=4 softtabstop=4 expandtab shiftround autoindent
+
+Consider installing `this alternative Python indentation
+plugin `__. I also
+like `neomake `__ with its flake8
+checker.
+
+.. _testing:
+
+Testing
+=======
+
+Running the Tests
+-----------------
+
+To run the tests for multiple Python versions, compile the docs, and
+check style, use `tox`_. Just type ``tox`` or use something like
+``tox -e py27`` to test a specific configuration. `detox`_ makes this go
+faster.
+
+You can disable a hand-selected set of "slow" tests by setting the
+environment variable SKIP_SLOW_TESTS before running them.
+
+Other ways to run the tests:
+
+- ``python testall.py`` (ditto)
+- ``python -m unittest discover -p 'test_*'`` (ditto)
+- `pytest`_
+
+You can also see the latest test results on `Linux`_ and on `Windows`_.
+
+Coverage
+^^^^^^^^
+
+``tox -e cov`` will add coverage info for tests: Coverage is pretty low
+still -- see the current status on `Codecov`_.
+
+Red Flags
+^^^^^^^^^
+
+The `pytest-random`_ plugin makes it easy to randomize the order of
+tests. ``py.test test --random`` will occasionally turn up failing tests
+that reveal ordering dependencies—which are bad news!
+
+Test Dependencies
+^^^^^^^^^^^^^^^^^
+
+The tests have a few more dependencies than beets itself. (The
+additional dependencies consist of testing utilities and dependencies of
+non-default plugins exercised by the test suite.) The dependencies are
+listed under 'test' in ``extras_require`` in `setup.py`_.
+To install the test dependencies, run ``python -m pip install .[test]``.
+Or, just run a test suite with ``tox`` which will install them
+automatically.
+
+.. _setup.py: https://github.com/beetbox/beets/blob/master/setup.py#L99`
+
+Writing Tests
+-------------
+
+Writing tests is done by adding or modifying files in folder `test`_.
+Take a look at
+`https://github.com/beetbox/beets/blob/master/test/test_template.py#L224`_
+to get a basic view on how tests are written. Despite using ``pytest``
+as a test runner, we prefer to write tests using the standard
+`unittest`_ testing framework.
+
+Any tests that involve sending out network traffic e.g. an external API
+call, should be skipped normally and run under our weekly `integration
+test`_ suite. These tests can be useful in detecting external changes
+that would affect ``beets``. In order to do this, simply add the
+following snippet before the applicable test case:
+
+.. code-block:: python
+
+ @unittest.skipUnless(
+ os.environ.get('INTEGRATION_TEST', '0') == '1',
+ 'integration testing not enabled')
+
+If you do this, it is also advised to create a similar test that 'mocks'
+the network call and can be run under normal circumstances by our CI and
+others. See `unittest.mock`_ for more info.
+
+Basics
+^^^^^^
+
+- Your file should contain a class derived from unittest.TestCase
+- Each method in this class which name starts with the letters *test*
+ will be executed to test functionality
+- Errors are raised with these methods:
+
+ - ``self.assertEqual``
+ - ``self.assertTrue``
+ - ``self.assertFalse``
+ - ``self.assertRaises``
+
+- For detailed information see `Python unittest`_
+- **AVOID** using the ``start()`` and ``stop()`` methods of
+ ``mock.patch``, as they require manual cleanup. Use the annotation or
+ context manager forms instead.
+
+.. _Python unittest: https://docs.python.org/2/library/unittest.html
+.. _Codecov: https://codecov.io/github/beetbox/beets
+.. _pytest-random: https://github.com/klrmn/pytest-random
+.. _tox: http://tox.readthedocs.org
+.. _detox: https://pypi.python.org/pypi/detox/
+.. _pytest: http://pytest.org
+.. _Linux: https://github.com/beetbox/beets/actions
+.. _Windows: https://ci.appveyor.com/project/beetbox/beets/
+.. _`https://github.com/beetbox/beets/blob/master/setup.py#L99`: https://github.com/beetbox/beets/blob/master/setup.py#L99
+.. _test: https://github.com/beetbox/beets/tree/master/test
+.. _`https://github.com/beetbox/beets/blob/master/test/test_template.py#L224`: https://github.com/beetbox/beets/blob/master/test/test_template.py#L224
+.. _unittest: https://docs.python.org/3.8/library/unittest.html
+.. _integration test: https://github.com/beetbox/beets/actions?query=workflow%3A%22integration+tests%22
+.. _unittest.mock: https://docs.python.org/3/library/unittest.mock.html
+.. _Python unittest: https://docs.python.org/2/library/unittest.html
diff --git a/README.rst b/README.rst
index d57afa933..4a2d8cb10 100644
--- a/README.rst
+++ b/README.rst
@@ -90,9 +90,9 @@ Check out the `Getting Started`_ guide for more information.
Contribute
----------
-Thank you for considering contributing to ``beets``! Whether you're a programmer or not, you should be able to find all the info you need at `CONTRIBUTING.md`_.
+Thank you for considering contributing to ``beets``! Whether you're a programmer or not, you should be able to find all the info you need at `CONTRIBUTING.rst`_.
-.. _CONTRIBUTING.md: https://github.com/beetbox/beets/blob/master/CONTRIBUTING.md
+.. _CONTRIBUTING.rst: https://github.com/beetbox/beets/blob/master/CONTRIBUTING.rst
Read More
---------
diff --git a/docs/contributing.rst b/docs/contributing.rst
new file mode 100644
index 000000000..6af7deaef
--- /dev/null
+++ b/docs/contributing.rst
@@ -0,0 +1,3 @@
+.. contributing:
+
+.. include:: ../CONTRIBUTING.rst
diff --git a/docs/index.rst b/docs/index.rst
index 62c87461b..1d03a0f27 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -32,6 +32,7 @@ Contents
reference/index
plugins/index
faq
+ contributing
dev/index
.. toctree::