diff --git a/python/ipywidgets/pyproject.toml b/python/ipywidgets/pyproject.toml
index 88a94d6b91..f315c8c934 100644
--- a/python/ipywidgets/pyproject.toml
+++ b/python/ipywidgets/pyproject.toml
@@ -1,5 +1,71 @@
 [build-system]
-# These are the assumed default build requirements from pip:
-# https://pip.pypa.io/en/stable/reference/pip/#pep-517-and-518-support
-requires = ["setuptools>=40.8.0", "wheel"]
-build-backend = "setuptools.build_meta"
\ No newline at end of file
+requires = ["setuptools>=61.2"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "ipywidgets"
+authors = [{name = "Jupyter Development Team", email = "jupyter@googlegroups.com"}]
+description = "Jupyter interactive widgets"
+keywords = ["Interactive", "Interpreter", "Shell", "Web", "ipython", "widgets", "Jupyter"]
+license = {text = "BSD 3-Clause License"}
+classifiers = [
+    "Intended Audience :: Developers",
+    "Intended Audience :: System Administrators",
+    "Intended Audience :: Science/Research",
+    "License :: OSI Approved :: BSD License",
+    "Programming Language :: Python",
+    "Programming Language :: Python :: 3",
+    "Programming Language :: Python :: 3.7",
+    "Programming Language :: Python :: 3.8",
+    "Programming Language :: Python :: 3.9",
+    "Programming Language :: Python :: 3.10",
+    "Programming Language :: Python :: 3.11",
+    "Programming Language :: Python :: 3 :: Only",
+    "Framework :: Jupyter",
+]
+urls = {Homepage = "http://jupyter.org"}
+requires-python = ">=3.7"
+dependencies = [
+    "comm>=0.1.3",
+    "ipython>=6.1.0",
+    "traitlets>=4.3.1",
+    "widgetsnbextension~=4.0.10",
+    "jupyterlab_widgets~=3.0.10",
+]
+dynamic = ["version"]
+
+[project.readme]
+file = "README.md"
+content-type = "text/markdown"
+
+[project.optional-dependencies]
+test = [
+    "jsonschema",
+    "ipykernel",
+    "pytest>=3.6.0",
+    "pytest-cov",
+    "pytz",
+]
+
+[tool.setuptools]
+zip-safe = false
+# include_package_data = True
+platforms = ["Linux", "Mac OS X", "Windows"]
+license-files = ["LICENSE"]
+include-package-data = false
+
+[tool.setuptools.packages]
+find = {namespaces = false}
+
+[tool.setuptools.package-data]
+ipywidgets = [
+    "state.schema.json",
+    "view.schema.json",
+]
+# Test data needs to be packaged until tests are moved out of module
+"ipywidgets.widgets.tests" = [
+    "data/jupyter-logo-transparent.png"
+]
+
+[tool.setuptools.dynamic]
+version = {attr = "ipywidgets._version.__version__"}
diff --git a/python/ipywidgets/setup.cfg b/python/ipywidgets/setup.cfg
deleted file mode 100644
index 130fbe6b85..0000000000
--- a/python/ipywidgets/setup.cfg
+++ /dev/null
@@ -1,58 +0,0 @@
-[metadata]
-name = ipywidgets
-version = attr: ipywidgets._version.__version__
-author = Jupyter Development Team
-author_email = jupyter@googlegroups.com
-license_files = LICENSE
-description = Jupyter interactive widgets
-long_description = file: README.md
-long_description_content_type = text/markdown
-url = http://jupyter.org
-keywords = Interactive, Interpreter, Shell, Web, ipython, widgets, Jupyter
-platforms = Linux, Mac OS X, Windows
-license = BSD 3-Clause License
-classifiers =
-  Intended Audience :: Developers
-  Intended Audience :: System Administrators
-  Intended Audience :: Science/Research
-  License :: OSI Approved :: BSD License
-  Programming Language :: Python
-  Programming Language :: Python :: 3
-  Programming Language :: Python :: 3.7
-  Programming Language :: Python :: 3.8
-  Programming Language :: Python :: 3.9
-  Programming Language :: Python :: 3.10
-  Programming Language :: Python :: 3.11
-  Programming Language :: Python :: 3 :: Only
-  Framework :: Jupyter
-
-[options]
-python_requires = >=3.7
-
-zip_safe = False
-# include_package_data = True
-packages = find:
-
-install_requires =
-  comm>=0.1.3
-  ipython>=6.1.0
-  traitlets>=4.3.1
-  widgetsnbextension~=4.0.10
-  jupyterlab_widgets~=3.0.10
-
-[options.extras_require]
-test =
-  jsonschema
-  ipykernel
-  pytest>=3.6.0
-  pytest-cov
-  pytz
-
-[options.package_data]
-ipywidgets =
-  state.schema.json
-  view.schema.json
-
-# Test data needs to be packaged until tests are moved out of module
-ipywidgets.widgets.tests =
-  data/jupyter-logo-transparent.png
diff --git a/python/jupyterlab_widgets/pyproject.toml b/python/jupyterlab_widgets/pyproject.toml
index 36b51e6609..8a9248fd53 100644
--- a/python/jupyterlab_widgets/pyproject.toml
+++ b/python/jupyterlab_widgets/pyproject.toml
@@ -1,7 +1,48 @@
 [build-system]
-requires = ["jupyter_packaging~=0.10,<2", "jupyterlab~=4.0"]
+requires = [
+    "jupyter_packaging~=0.10,<2",
+    "jupyterlab~=4.0"
+]
 build-backend = "jupyter_packaging.build_api"
 
+[project]
+name = "jupyterlab_widgets"
+authors = [{name = "Jupyter Development Team", email = "jupyter@googlegroups.com"}]
+description = "Jupyter interactive widgets for JupyterLab"
+license = {text = "BSD-3-Clause"}
+keywords = ["Interactive", "Interpreter", "Shell", "Web", "notebook", "widgets", "Jupyter", "JupyterLab", "JupyterLab3"]
+classifiers = [
+    "Intended Audience :: Developers",
+    "Intended Audience :: System Administrators",
+    "Intended Audience :: Science/Research",
+    "License :: OSI Approved :: BSD License",
+    "Programming Language :: Python",
+    "Programming Language :: Python :: 3",
+    "Programming Language :: Python :: 3.7",
+    "Programming Language :: Python :: 3.8",
+    "Programming Language :: Python :: 3.9",
+    "Programming Language :: Python :: 3.10",
+    "Programming Language :: Python :: 3.11",
+    "Programming Language :: Python :: 3 :: Only",
+    "Framework :: Jupyter",
+    "Framework :: Jupyter :: JupyterLab",
+    "Framework :: Jupyter :: JupyterLab :: 3",
+    "Framework :: Jupyter :: JupyterLab :: Extensions",
+    "Framework :: Jupyter :: JupyterLab :: Extensions :: Prebuilt",
+]
+requires-python = ">=3.7"
+dynamic = ["version"]
+
+[project.readme]
+file = "README.md"
+content-type = "text/markdown"
+
+[project.urls]
+Homepage = "https://github.com/jupyter-widgets/ipywidgets"
+
+[tool.check-manifest]
+ignore = ["labextension/**", "yarn.lock", ".*", "package-lock.json"]
+
 [tool.jupyter-packaging.options]
 skip-if-exists = ["labextension/package.json"]
 ensured-targets = ["labextension/package.json"]
@@ -13,5 +54,14 @@ factory = "jupyter_packaging.npm_builder"
 build_cmd = "build:prod"
 npm = ["jlpm"]
 
-[tool.check-manifest]
-ignore = ["labextension/**", "yarn.lock", ".*", "package-lock.json"]
+[tool.setuptools]
+zip-safe = false
+include-package-data = true
+platforms = ["Linux", "Mac OS X", "Windows"]
+license-files = ["LICENSE"]
+
+[tool.setuptools.packages]
+find = {namespaces = false}
+
+[tool.setuptools.dynamic]
+version = {attr = "jupyterlab_widgets._version.__version__"}
diff --git a/python/jupyterlab_widgets/setup.cfg b/python/jupyterlab_widgets/setup.cfg
deleted file mode 100644
index 8cf3577ac0..0000000000
--- a/python/jupyterlab_widgets/setup.cfg
+++ /dev/null
@@ -1,37 +0,0 @@
-[metadata]
-name = jupyterlab_widgets
-version = attr: jupyterlab_widgets._version.__version__
-author = Jupyter Development Team
-author_email = jupyter@googlegroups.com
-url = https://github.com/jupyter-widgets/ipywidgets
-description = Jupyter interactive widgets for JupyterLab
-long_description = file: README.md
-long_description_content_type = text/markdown
-license_files = LICENSE
-license = BSD-3-Clause
-platforms = Linux, Mac OS X, Windows
-keywords = Interactive, Interpreter, Shell, Web, notebook, widgets, Jupyter, JupyterLab, JupyterLab3
-classifiers =
-  Intended Audience :: Developers
-  Intended Audience :: System Administrators
-  Intended Audience :: Science/Research
-  License :: OSI Approved :: BSD License
-  Programming Language :: Python
-  Programming Language :: Python :: 3
-  Programming Language :: Python :: 3.7
-  Programming Language :: Python :: 3.8
-  Programming Language :: Python :: 3.9
-  Programming Language :: Python :: 3.10
-  Programming Language :: Python :: 3.11
-  Programming Language :: Python :: 3 :: Only
-  Framework :: Jupyter
-  Framework :: Jupyter :: JupyterLab
-  Framework :: Jupyter :: JupyterLab :: 3
-  Framework :: Jupyter :: JupyterLab :: Extensions
-  Framework :: Jupyter :: JupyterLab :: Extensions :: Prebuilt
-
-[options]
-python_requires = >=3.7
-zip_safe=False
-include_package_data = True
-packages = find:
diff --git a/python/widgetsnbextension/pyproject.toml b/python/widgetsnbextension/pyproject.toml
index b289136f7e..e1902fb810 100644
--- a/python/widgetsnbextension/pyproject.toml
+++ b/python/widgetsnbextension/pyproject.toml
@@ -1,7 +1,38 @@
 [build-system]
-# These are the assumed default build requirements from pip:
-# https://pip.pypa.io/en/stable/reference/pip/#pep-517-and-518-support
 requires = ["jupyter_packaging~=0.10,<2"]
+build-backend = "jupyter_packaging.build_api"
+
+[project]
+name = "widgetsnbextension"
+authors = [{name = "Jupyter Development Team", email = "jupyter@googlegroups.com"}]
+description = "Jupyter interactive widgets for Jupyter Notebook"
+license = {text = "BSD 3-Clause License"}
+keywords = ["Interactive", "Interpreter", "Shell", "Web", "notebook", "widgets", "Jupyter"]
+classifiers = [
+    "Intended Audience :: Developers",
+    "Intended Audience :: System Administrators",
+    "Intended Audience :: Science/Research",
+    "License :: OSI Approved :: BSD License",
+    "Programming Language :: Python",
+    "Programming Language :: Python :: 3",
+    "Programming Language :: Python :: 3.7",
+    "Programming Language :: Python :: 3.8",
+    "Programming Language :: Python :: 3.9",
+    "Programming Language :: Python :: 3.10",
+    "Programming Language :: Python :: 3.11",
+    "Programming Language :: Python :: 3 :: Only",
+    "Framework :: Jupyter",
+]
+urls = {Homepage = "http://jupyter.org"}
+requires-python = ">=3.7"
+dynamic = ["version"]
+
+[project.readme]
+file = "README.md"
+content-type = "text/markdown"
+
+[tool.check-manifest]
+ignore = ["widgetnbextension/static/**", "yarn.lock", ".*", "package-lock.json"]
 
 [tool.jupyter-packaging.options]
 skip-if-exists = ["widgetnbextension/static/extension.js"]
@@ -14,5 +45,17 @@ factory = "jupyter_packaging.npm_builder"
 build_cmd = "build"
 npm = ["yarn"]
 
-[tool.check-manifest]
-ignore = ["widgetnbextension/static/**", "yarn.lock", ".*", "package-lock.json"]
+[tool.setuptools]
+zip-safe = false
+include-package-data = true
+platforms = ["Linux", "Mac OS X", "Windows"]
+license-files = ["LICENSE"]
+
+[tool.setuptools.packages]
+find = {namespaces = false}
+
+[tool.setuptools.package-data]
+widgetsnbextension = ["widgetsnbextension/static/extension.js"]
+
+[tool.setuptools.dynamic]
+version = {attr = "widgetsnbextension._version.__version__"}
diff --git a/python/widgetsnbextension/setup.cfg b/python/widgetsnbextension/setup.cfg
deleted file mode 100644
index 864cab574e..0000000000
--- a/python/widgetsnbextension/setup.cfg
+++ /dev/null
@@ -1,37 +0,0 @@
-[metadata]
-name = widgetsnbextension
-version = attr: widgetsnbextension._version.__version__
-author = Jupyter Development Team
-author_email = jupyter@googlegroups.com
-url = http://jupyter.org
-description = Jupyter interactive widgets for Jupyter Notebook
-long_description = file: README.md
-long_description_content_type = text/markdown
-license_files = LICENSE
-license = BSD 3-Clause License
-platforms = Linux, Mac OS X, Windows
-keywords = Interactive, Interpreter, Shell, Web, notebook, widgets, Jupyter
-classifiers =
-  Intended Audience :: Developers
-  Intended Audience :: System Administrators
-  Intended Audience :: Science/Research
-  License :: OSI Approved :: BSD License
-  Programming Language :: Python
-  Programming Language :: Python :: 3
-  Programming Language :: Python :: 3.7
-  Programming Language :: Python :: 3.8
-  Programming Language :: Python :: 3.9
-  Programming Language :: Python :: 3.10
-  Programming Language :: Python :: 3.11
-  Programming Language :: Python :: 3 :: Only
-  Framework :: Jupyter
-
-[options]
-python_requires = >=3.7
-zip_safe=False
-include_package_data = True
-packages = find:
-
-[options.package_data]
-widgetsnbextension =
-  widgetsnbextension/static/extension.js