diff --git a/.bumpversion.cfg b/.bumpversion.cfg
deleted file mode 100644
index 122d3d4..0000000
--- a/.bumpversion.cfg
+++ /dev/null
@@ -1,7 +0,0 @@
-[bumpversion]
-current_version = 1.1.0
-commit = True
-tag = True
-
-[bumpversion:file:cssselect/__init__.py]
-
diff --git a/.gitignore b/.gitignore
index b0ab86a..4598fbe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,12 @@
 /.tox
 /MANIFEST
 /dist
+/build
 /docs/_build
 /.coverage
-.idea
\ No newline at end of file
+.idea
+*.py[co]
+__pycache__
+
+# generated file
+/cssselect/version.py
diff --git a/cssselect/__init__.py b/cssselect/__init__.py
index b41cef9..9042b73 100644
--- a/cssselect/__init__.py
+++ b/cssselect/__init__.py
@@ -17,6 +17,5 @@
                               SelectorError, SelectorSyntaxError)
 from cssselect.xpath import GenericTranslator, HTMLTranslator, ExpressionError
 
-
-VERSION = '1.1.0'
-__version__ = VERSION
+from .version import __version__
+VERSION = __version__
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..8e09dbb
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,7 @@
+[build-system]
+requires = ["setuptools>=44", "wheel", "setuptools_scm[toml]>=3.4.3"]
+build-backend = "setuptools.build_meta"
+
+[tool.setuptools_scm]
+write_to = "cssselect/version.py"
+write_to_template = "__version__ = \"{version}\"\n"
diff --git a/setup.cfg b/setup.cfg
index b8c93b1..ab802cd 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,3 +1,30 @@
+[metadata]
+name = cssselect
+author = Ian Bicking
+author_email = ianb@colorstudy.com
+maintainer = Paul Tremberth
+maintainer_email = paul.tremberth@gmail.com
+license = BSD-3-Clause
+description = cssselect parses CSS3 Selectors and translates them to XPath 1.0
+url = https://github.com/scrapy/cssselect
+long_description = file: README.rst
+long_description_content_type = text/x-rst
+classifiers =
+    Development Status :: 4 - Beta
+    Intended Audience :: Developers
+    License :: OSI Approved :: BSD License
+    Programming Language :: Python :: 2
+    Programming Language :: Python :: 2.7
+    Programming Language :: Python :: 3
+    Programming Language :: Python :: 3.4
+    Programming Language :: Python :: 3.5
+    Programming Language :: Python :: 3.6
+    Programming Language :: Python :: 3.7
+
+[options]
+packages = cssselect
+python_requires = >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
+
 [build_sphinx]
 source-dir = docs
 build-dir  = docs/_build
diff --git a/setup.py b/setup.py
deleted file mode 100644
index de7128d..0000000
--- a/setup.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-import os.path
-try:
-    from setuptools import setup
-    extra_kwargs = {'test_suite': 'cssselect.tests'}
-except ImportError:
-    from distutils.core import setup
-    extra_kwargs = {}
-
-
-ROOT = os.path.dirname(__file__)
-README = open(os.path.join(ROOT, 'README.rst')).read()
-INIT_PY = open(os.path.join(ROOT, 'cssselect', '__init__.py')).read()
-VERSION = re.search("VERSION = '([^']+)'", INIT_PY).group(1)
-
-
-setup(
-    name='cssselect',
-    version=VERSION,
-    author='Ian Bicking',
-    author_email='ianb@colorstudy.com',
-    maintainer='Paul Tremberth',
-    maintainer_email='paul.tremberth@gmail.com',
-    description=
-        'cssselect parses CSS3 Selectors and translates them to XPath 1.0',
-    long_description=README,
-    url='https://github.com/scrapy/cssselect',
-    license='BSD',
-    packages=['cssselect'],
-    python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
-    classifiers=[
-        'Development Status :: 4 - Beta',
-        'Intended Audience :: Developers',
-        'License :: OSI Approved :: BSD License',
-        'Programming Language :: Python :: 2',
-        'Programming Language :: Python :: 2.7',
-        'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.4',
-        'Programming Language :: Python :: 3.5',
-        'Programming Language :: Python :: 3.6',
-        'Programming Language :: Python :: 3.7'
-    ],
-    **extra_kwargs
-)