diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 80cc1d5..7851323 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -36,9 +36,9 @@ jobs:
         TOXENV: ${{ matrix.toxenv }}
       run: tox
 
-    - name: Run coverage
-      if: matrix.python-version == '3.8' && matrix.toxenv == 'django32'
-      uses: codecov/codecov-action@v3
-      with:
-        flags: unittests
-        fail_ci_if_error: true
+    #- name: Run coverage
+    #  if: matrix.python-version == '3.8' && matrix.toxenv == 'django32'
+    #  uses: codecov/codecov-action@v3
+    #  with:
+    #    flags: unittests
+    #    fail_ci_if_error: true
diff --git a/Makefile b/Makefile
index 1292a76..e66c48d 100644
--- a/Makefile
+++ b/Makefile
@@ -7,6 +7,10 @@
 # For opening files in a browser. Use like: $(BROWSER)relative/path/to/file.html
 BROWSER := python -m webbrowser file://$(CURDIR)/
 
+PACKAGE=platform_plugin_turnitin
+SOURCES=./setup.py ./$(PACKAGE)
+BLACK_OPTS = --exclude templates ${SOURCES}
+
 help: ## display this help message
 	@echo "Please use \`make <target>' where <target> is one of"
 	@awk -F ':.*?## ' '/^[a-zA-Z]/ && NF==2 {printf "\033[36m  %-25s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort
@@ -66,6 +70,10 @@ requirements: piptools ## install development environment requirements
 test: clean ## run tests in the current virtualenv
 	pytest
 
+format: ## Format code automatically
+	isort $(SOURCES)
+	black $(BLACK_OPTS)
+
 diff_cover: test ## find diff lines that need test coverage
 	diff-cover coverage.xml
 
diff --git a/manage.py b/manage.py
index 4afa5aa..c4c1f40 100644
--- a/manage.py
+++ b/manage.py
@@ -18,7 +18,7 @@
         # issue is really that Django is missing to avoid masking other
         # exceptions on Python 2.
         try:
-            import django  # pylint: disable=unused-import, wrong-import-position
+            import django  # pylint: disable=unused-import
         except ImportError as import_error:
             raise ImportError(
                 "Couldn't import Django. Are you sure it's installed and "
diff --git a/platform_plugin_turnitin/__init__.py b/platform_plugin_turnitin/__init__.py
index b41d428..ceaf225 100644
--- a/platform_plugin_turnitin/__init__.py
+++ b/platform_plugin_turnitin/__init__.py
@@ -2,4 +2,4 @@
 Open edX Django plugin for Turnitin integrations using Open edX Filters.
 """
 
-__version__ = '0.1.0'
+__version__ = "0.1.0"
diff --git a/platform_plugin_turnitin/apps.py b/platform_plugin_turnitin/apps.py
index b34e3b1..aeb61ac 100644
--- a/platform_plugin_turnitin/apps.py
+++ b/platform_plugin_turnitin/apps.py
@@ -10,4 +10,19 @@ class PlatformPluginTurnitinConfig(AppConfig):
     Configuration for the platform_plugin_turnitin Django application.
     """
 
-    name = 'platform_plugin_turnitin'
+    name = "platform_plugin_turnitin"
+
+    plugin_app = {
+        "settings_config": {
+            "lms.djangoapp": {
+                "common": {"relative_path": "settings.common"},
+                "test": {"relative_path": "settings.test"},
+                "production": {"relative_path": "settings.production"},
+            },
+            "cms.djangoapp": {
+                "common": {"relative_path": "settings.common"},
+                "test": {"relative_path": "settings.test"},
+                "production": {"relative_path": "settings.production"},
+            },
+        },
+    }
diff --git a/platform_plugin_turnitin/settings/__init__.py b/platform_plugin_turnitin/settings/__init__.py
new file mode 100644
index 0000000..ceaf225
--- /dev/null
+++ b/platform_plugin_turnitin/settings/__init__.py
@@ -0,0 +1,5 @@
+"""
+Open edX Django plugin for Turnitin integrations using Open edX Filters.
+"""
+
+__version__ = "0.1.0"
diff --git a/platform_plugin_turnitin/settings/common.py b/platform_plugin_turnitin/settings/common.py
new file mode 100644
index 0000000..5c9f08c
--- /dev/null
+++ b/platform_plugin_turnitin/settings/common.py
@@ -0,0 +1,37 @@
+"""
+Common Django settings for the platform_plugin_turnitin project.
+For more information on this file, see
+https://docs.djangoproject.com/en/2.22/topics/settings/
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/2.22/ref/settings/
+"""
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/2.22/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = "secret-key"
+
+
+# Application definition
+
+INSTALLED_APPS = [
+    "platform_plugin_turnitin",
+]
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/2.22/topics/i18n/
+
+LANGUAGE_CODE = "en-us"
+
+TIME_ZONE = "UTC"
+
+USE_TZ = True
+
+
+def plugin_settings(settings):  # pylint: disable=unused-argument
+    """
+    Set of plugin settings used by the Open Edx platform.
+    More info: https://github.com/edx/edx-platform/blob/master/openedx/core/djangoapps/plugins/README.rst
+    """
diff --git a/platform_plugin_turnitin/settings/production.py b/platform_plugin_turnitin/settings/production.py
new file mode 100644
index 0000000..f029aa9
--- /dev/null
+++ b/platform_plugin_turnitin/settings/production.py
@@ -0,0 +1,10 @@
+"""
+Production Django settings for platform_plugin_turnitin project.
+"""
+
+
+def plugin_settings(settings):  # pylint: disable=unused-argument
+    """
+    Set of plugin settings used by the Open Edx platform.
+    More info: https://github.com/edx/edx-platform/blob/master/openedx/core/djangoapps/plugins/README.rst
+    """
diff --git a/requirements/base.txt b/requirements/base.txt
new file mode 100644
index 0000000..81ee185
--- /dev/null
+++ b/requirements/base.txt
@@ -0,0 +1,18 @@
+#
+# This file is autogenerated by pip-compile with Python 3.8
+# by the following command:
+#
+#    make upgrade
+#
+asgiref==3.7.2
+    # via django
+django==3.2.22
+    # via
+    #   -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt
+    #   -r requirements/base.in
+pytz==2023.3.post1
+    # via django
+sqlparse==0.4.4
+    # via django
+typing-extensions==4.8.0
+    # via asgiref
diff --git a/requirements/ci.txt b/requirements/ci.txt
new file mode 100644
index 0000000..8115a7d
--- /dev/null
+++ b/requirements/ci.txt
@@ -0,0 +1,33 @@
+#
+# This file is autogenerated by pip-compile with Python 3.8
+# by the following command:
+#
+#    make upgrade
+#
+distlib==0.3.7
+    # via virtualenv
+filelock==3.12.4
+    # via
+    #   tox
+    #   virtualenv
+packaging==23.2
+    # via tox
+platformdirs==3.11.0
+    # via virtualenv
+pluggy==1.3.0
+    # via tox
+py==1.11.0
+    # via tox
+six==1.16.0
+    # via tox
+tomli==2.0.1
+    # via tox
+tox==3.28.0
+    # via
+    #   -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt
+    #   -r requirements/ci.in
+    #   tox-battery
+tox-battery==0.6.2
+    # via -r requirements/ci.in
+virtualenv==20.24.5
+    # via tox
diff --git a/requirements/dev.in b/requirements/dev.in
index eb8c92c..bc211db 100644
--- a/requirements/dev.in
+++ b/requirements/dev.in
@@ -7,3 +7,4 @@
 
 diff-cover                # Changeset diff test coverage
 edx-i18n-tools            # For i18n_tool dummy
+black
diff --git a/requirements/dev.txt b/requirements/dev.txt
new file mode 100644
index 0000000..55e9f02
--- /dev/null
+++ b/requirements/dev.txt
@@ -0,0 +1,267 @@
+#
+# This file is autogenerated by pip-compile with Python 3.8
+# by the following command:
+#
+#    make upgrade
+#
+asgiref==3.7.2
+    # via
+    #   -r requirements/quality.txt
+    #   django
+astroid==2.15.8
+    # via
+    #   -r requirements/quality.txt
+    #   pylint
+    #   pylint-celery
+black==23.9.1
+    # via -r requirements/dev.in
+build==1.0.3
+    # via
+    #   -r requirements/pip-tools.txt
+    #   pip-tools
+chardet==5.2.0
+    # via diff-cover
+click==8.1.7
+    # via
+    #   -r requirements/pip-tools.txt
+    #   -r requirements/quality.txt
+    #   black
+    #   click-log
+    #   code-annotations
+    #   edx-lint
+    #   pip-tools
+click-log==0.4.0
+    # via
+    #   -r requirements/quality.txt
+    #   edx-lint
+code-annotations==1.5.0
+    # via
+    #   -r requirements/quality.txt
+    #   edx-lint
+coverage[toml]==7.3.2
+    # via
+    #   -r requirements/quality.txt
+    #   pytest-cov
+diff-cover==7.7.0
+    # via -r requirements/dev.in
+dill==0.3.7
+    # via
+    #   -r requirements/quality.txt
+    #   pylint
+distlib==0.3.7
+    # via
+    #   -r requirements/ci.txt
+    #   virtualenv
+django==3.2.22
+    # via
+    #   -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt
+    #   -r requirements/quality.txt
+    #   edx-i18n-tools
+edx-i18n-tools==1.2.0
+    # via -r requirements/dev.in
+edx-lint==5.3.4
+    # via -r requirements/quality.txt
+exceptiongroup==1.1.3
+    # via
+    #   -r requirements/quality.txt
+    #   pytest
+filelock==3.12.4
+    # via
+    #   -r requirements/ci.txt
+    #   tox
+    #   virtualenv
+importlib-metadata==6.8.0
+    # via
+    #   -r requirements/pip-tools.txt
+    #   build
+iniconfig==2.0.0
+    # via
+    #   -r requirements/quality.txt
+    #   pytest
+isort==5.12.0
+    # via
+    #   -r requirements/quality.txt
+    #   pylint
+jinja2==3.1.2
+    # via
+    #   -r requirements/quality.txt
+    #   code-annotations
+    #   diff-cover
+lazy-object-proxy==1.9.0
+    # via
+    #   -r requirements/quality.txt
+    #   astroid
+markupsafe==2.1.3
+    # via
+    #   -r requirements/quality.txt
+    #   jinja2
+mccabe==0.7.0
+    # via
+    #   -r requirements/quality.txt
+    #   pylint
+mypy-extensions==1.0.0
+    # via black
+packaging==23.2
+    # via
+    #   -r requirements/ci.txt
+    #   -r requirements/pip-tools.txt
+    #   -r requirements/quality.txt
+    #   black
+    #   build
+    #   pytest
+    #   tox
+path==16.7.1
+    # via edx-i18n-tools
+pathspec==0.11.2
+    # via black
+pbr==5.11.1
+    # via
+    #   -r requirements/quality.txt
+    #   stevedore
+pip-tools==7.3.0
+    # via -r requirements/pip-tools.txt
+platformdirs==3.11.0
+    # via
+    #   -r requirements/ci.txt
+    #   -r requirements/quality.txt
+    #   black
+    #   pylint
+    #   virtualenv
+pluggy==1.3.0
+    # via
+    #   -r requirements/ci.txt
+    #   -r requirements/quality.txt
+    #   diff-cover
+    #   pytest
+    #   tox
+polib==1.2.0
+    # via edx-i18n-tools
+py==1.11.0
+    # via
+    #   -r requirements/ci.txt
+    #   tox
+pycodestyle==2.11.0
+    # via -r requirements/quality.txt
+pydocstyle==6.3.0
+    # via -r requirements/quality.txt
+pygments==2.16.1
+    # via diff-cover
+pylint==2.17.7
+    # via
+    #   -r requirements/quality.txt
+    #   edx-lint
+    #   pylint-celery
+    #   pylint-django
+    #   pylint-plugin-utils
+pylint-celery==0.3
+    # via
+    #   -r requirements/quality.txt
+    #   edx-lint
+pylint-django==2.5.3
+    # via
+    #   -r requirements/quality.txt
+    #   edx-lint
+pylint-plugin-utils==0.8.2
+    # via
+    #   -r requirements/quality.txt
+    #   pylint-celery
+    #   pylint-django
+pyproject-hooks==1.0.0
+    # via
+    #   -r requirements/pip-tools.txt
+    #   build
+pytest==7.4.2
+    # via
+    #   -r requirements/quality.txt
+    #   pytest-cov
+    #   pytest-django
+pytest-cov==4.1.0
+    # via -r requirements/quality.txt
+pytest-django==4.5.2
+    # via -r requirements/quality.txt
+python-slugify==8.0.1
+    # via
+    #   -r requirements/quality.txt
+    #   code-annotations
+pytz==2023.3.post1
+    # via
+    #   -r requirements/quality.txt
+    #   django
+pyyaml==6.0.1
+    # via
+    #   -r requirements/quality.txt
+    #   code-annotations
+    #   edx-i18n-tools
+six==1.16.0
+    # via
+    #   -r requirements/ci.txt
+    #   -r requirements/quality.txt
+    #   edx-lint
+    #   tox
+snowballstemmer==2.2.0
+    # via
+    #   -r requirements/quality.txt
+    #   pydocstyle
+sqlparse==0.4.4
+    # via
+    #   -r requirements/quality.txt
+    #   django
+stevedore==5.1.0
+    # via
+    #   -r requirements/quality.txt
+    #   code-annotations
+text-unidecode==1.3
+    # via
+    #   -r requirements/quality.txt
+    #   python-slugify
+tomli==2.0.1
+    # via
+    #   -r requirements/ci.txt
+    #   -r requirements/pip-tools.txt
+    #   -r requirements/quality.txt
+    #   black
+    #   build
+    #   coverage
+    #   pip-tools
+    #   pylint
+    #   pyproject-hooks
+    #   pytest
+    #   tox
+tomlkit==0.12.1
+    # via
+    #   -r requirements/quality.txt
+    #   pylint
+tox==3.28.0
+    # via
+    #   -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt
+    #   -r requirements/ci.txt
+    #   tox-battery
+tox-battery==0.6.2
+    # via -r requirements/ci.txt
+typing-extensions==4.8.0
+    # via
+    #   -r requirements/quality.txt
+    #   asgiref
+    #   astroid
+    #   black
+    #   pylint
+virtualenv==20.24.5
+    # via
+    #   -r requirements/ci.txt
+    #   tox
+wheel==0.41.2
+    # via
+    #   -r requirements/pip-tools.txt
+    #   pip-tools
+wrapt==1.15.0
+    # via
+    #   -r requirements/quality.txt
+    #   astroid
+zipp==3.17.0
+    # via
+    #   -r requirements/pip-tools.txt
+    #   importlib-metadata
+
+# The following packages are considered to be unsafe in a requirements file:
+# pip
+# setuptools
diff --git a/requirements/doc.txt b/requirements/doc.txt
new file mode 100644
index 0000000..7f770d4
--- /dev/null
+++ b/requirements/doc.txt
@@ -0,0 +1,228 @@
+#
+# This file is autogenerated by pip-compile with Python 3.8
+# by the following command:
+#
+#    make upgrade
+#
+accessible-pygments==0.0.4
+    # via pydata-sphinx-theme
+alabaster==0.7.13
+    # via sphinx
+asgiref==3.7.2
+    # via
+    #   -r requirements/test.txt
+    #   django
+babel==2.13.0
+    # via
+    #   pydata-sphinx-theme
+    #   sphinx
+beautifulsoup4==4.12.2
+    # via pydata-sphinx-theme
+build==1.0.3
+    # via -r requirements/doc.in
+certifi==2023.7.22
+    # via requests
+cffi==1.16.0
+    # via cryptography
+charset-normalizer==3.3.0
+    # via requests
+click==8.1.7
+    # via
+    #   -r requirements/test.txt
+    #   code-annotations
+code-annotations==1.5.0
+    # via -r requirements/test.txt
+coverage[toml]==7.3.2
+    # via
+    #   -r requirements/test.txt
+    #   pytest-cov
+cryptography==41.0.4
+    # via secretstorage
+django==3.2.22
+    # via
+    #   -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt
+    #   -r requirements/test.txt
+doc8==1.1.1
+    # via -r requirements/doc.in
+docutils==0.19
+    # via
+    #   doc8
+    #   pydata-sphinx-theme
+    #   readme-renderer
+    #   restructuredtext-lint
+    #   sphinx
+exceptiongroup==1.1.3
+    # via
+    #   -r requirements/test.txt
+    #   pytest
+idna==3.4
+    # via requests
+imagesize==1.4.1
+    # via sphinx
+importlib-metadata==6.8.0
+    # via
+    #   build
+    #   keyring
+    #   sphinx
+    #   twine
+importlib-resources==6.1.0
+    # via keyring
+iniconfig==2.0.0
+    # via
+    #   -r requirements/test.txt
+    #   pytest
+jaraco-classes==3.3.0
+    # via keyring
+jeepney==0.8.0
+    # via
+    #   keyring
+    #   secretstorage
+jinja2==3.1.2
+    # via
+    #   -r requirements/test.txt
+    #   code-annotations
+    #   sphinx
+keyring==24.2.0
+    # via twine
+markdown-it-py==3.0.0
+    # via rich
+markupsafe==2.1.3
+    # via
+    #   -r requirements/test.txt
+    #   jinja2
+mdurl==0.1.2
+    # via markdown-it-py
+more-itertools==10.1.0
+    # via jaraco-classes
+nh3==0.2.14
+    # via readme-renderer
+packaging==23.2
+    # via
+    #   -r requirements/test.txt
+    #   build
+    #   pydata-sphinx-theme
+    #   pytest
+    #   sphinx
+pbr==5.11.1
+    # via
+    #   -r requirements/test.txt
+    #   stevedore
+pkginfo==1.9.6
+    # via twine
+pluggy==1.3.0
+    # via
+    #   -r requirements/test.txt
+    #   pytest
+pycparser==2.21
+    # via cffi
+pydata-sphinx-theme==0.14.1
+    # via sphinx-book-theme
+pygments==2.16.1
+    # via
+    #   accessible-pygments
+    #   doc8
+    #   pydata-sphinx-theme
+    #   readme-renderer
+    #   rich
+    #   sphinx
+pyproject-hooks==1.0.0
+    # via build
+pytest==7.4.2
+    # via
+    #   -r requirements/test.txt
+    #   pytest-cov
+    #   pytest-django
+pytest-cov==4.1.0
+    # via -r requirements/test.txt
+pytest-django==4.5.2
+    # via -r requirements/test.txt
+python-slugify==8.0.1
+    # via
+    #   -r requirements/test.txt
+    #   code-annotations
+pytz==2023.3.post1
+    # via
+    #   -r requirements/test.txt
+    #   babel
+    #   django
+pyyaml==6.0.1
+    # via
+    #   -r requirements/test.txt
+    #   code-annotations
+readme-renderer==42.0
+    # via twine
+requests==2.31.0
+    # via
+    #   requests-toolbelt
+    #   sphinx
+    #   twine
+requests-toolbelt==1.0.0
+    # via twine
+restructuredtext-lint==1.4.0
+    # via doc8
+rfc3986==2.0.0
+    # via twine
+rich==13.6.0
+    # via twine
+secretstorage==3.3.3
+    # via keyring
+snowballstemmer==2.2.0
+    # via sphinx
+soupsieve==2.5
+    # via beautifulsoup4
+sphinx==6.2.1
+    # via
+    #   -r requirements/doc.in
+    #   pydata-sphinx-theme
+    #   sphinx-book-theme
+sphinx-book-theme==1.0.1
+    # via -r requirements/doc.in
+sphinxcontrib-applehelp==1.0.4
+    # via sphinx
+sphinxcontrib-devhelp==1.0.2
+    # via sphinx
+sphinxcontrib-htmlhelp==2.0.1
+    # via sphinx
+sphinxcontrib-jsmath==1.0.1
+    # via sphinx
+sphinxcontrib-qthelp==1.0.3
+    # via sphinx
+sphinxcontrib-serializinghtml==1.1.5
+    # via sphinx
+sqlparse==0.4.4
+    # via
+    #   -r requirements/test.txt
+    #   django
+stevedore==5.1.0
+    # via
+    #   -r requirements/test.txt
+    #   code-annotations
+    #   doc8
+text-unidecode==1.3
+    # via
+    #   -r requirements/test.txt
+    #   python-slugify
+tomli==2.0.1
+    # via
+    #   -r requirements/test.txt
+    #   build
+    #   coverage
+    #   doc8
+    #   pyproject-hooks
+    #   pytest
+twine==4.0.2
+    # via -r requirements/doc.in
+typing-extensions==4.8.0
+    # via
+    #   -r requirements/test.txt
+    #   asgiref
+    #   pydata-sphinx-theme
+    #   rich
+urllib3==2.0.6
+    # via
+    #   requests
+    #   twine
+zipp==3.17.0
+    # via
+    #   importlib-metadata
+    #   importlib-resources
diff --git a/requirements/pip-tools.txt b/requirements/pip-tools.txt
index 7dc0677..50d35f2 100644
--- a/requirements/pip-tools.txt
+++ b/requirements/pip-tools.txt
@@ -4,22 +4,27 @@
 #
 #    make upgrade
 #
-build==0.10.0
+build==1.0.3
     # via pip-tools
-click==8.1.4
+click==8.1.7
     # via pip-tools
-packaging==23.1
+importlib-metadata==6.8.0
     # via build
-pip-tools==6.14.0
-    # via -r python-template/placeholder_repo_name_0/requirements/pip-tools.in
+packaging==23.2
+    # via build
+pip-tools==7.3.0
+    # via -r requirements/pip-tools.in
 pyproject-hooks==1.0.0
     # via build
 tomli==2.0.1
     # via
     #   build
     #   pip-tools
-wheel==0.40.0
+    #   pyproject-hooks
+wheel==0.41.2
     # via pip-tools
+zipp==3.17.0
+    # via importlib-metadata
 
 # The following packages are considered to be unsafe in a requirements file:
 # pip
diff --git a/requirements/pip.txt b/requirements/pip.txt
index 956782e..3e7d8f4 100644
--- a/requirements/pip.txt
+++ b/requirements/pip.txt
@@ -4,11 +4,11 @@
 #
 #    make upgrade
 #
-wheel==0.40.0
-    # via -r python-template/placeholder_repo_name_0/requirements/pip.in
+wheel==0.41.2
+    # via -r requirements/pip.in
 
 # The following packages are considered to be unsafe in a requirements file:
-pip==23.1.2
-    # via -r python-template/placeholder_repo_name_0/requirements/pip.in
-setuptools==68.0.0
-    # via -r python-template/placeholder_repo_name_0/requirements/pip.in
+pip==23.2.1
+    # via -r requirements/pip.in
+setuptools==68.2.2
+    # via -r requirements/pip.in
diff --git a/requirements/quality.txt b/requirements/quality.txt
new file mode 100644
index 0000000..c27dfd7
--- /dev/null
+++ b/requirements/quality.txt
@@ -0,0 +1,147 @@
+#
+# This file is autogenerated by pip-compile with Python 3.8
+# by the following command:
+#
+#    make upgrade
+#
+asgiref==3.7.2
+    # via
+    #   -r requirements/test.txt
+    #   django
+astroid==2.15.8
+    # via
+    #   pylint
+    #   pylint-celery
+click==8.1.7
+    # via
+    #   -r requirements/test.txt
+    #   click-log
+    #   code-annotations
+    #   edx-lint
+click-log==0.4.0
+    # via edx-lint
+code-annotations==1.5.0
+    # via
+    #   -r requirements/test.txt
+    #   edx-lint
+coverage[toml]==7.3.2
+    # via
+    #   -r requirements/test.txt
+    #   pytest-cov
+dill==0.3.7
+    # via pylint
+django==3.2.22
+    # via
+    #   -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt
+    #   -r requirements/test.txt
+edx-lint==5.3.4
+    # via -r requirements/quality.in
+exceptiongroup==1.1.3
+    # via
+    #   -r requirements/test.txt
+    #   pytest
+iniconfig==2.0.0
+    # via
+    #   -r requirements/test.txt
+    #   pytest
+isort==5.12.0
+    # via
+    #   -r requirements/quality.in
+    #   pylint
+jinja2==3.1.2
+    # via
+    #   -r requirements/test.txt
+    #   code-annotations
+lazy-object-proxy==1.9.0
+    # via astroid
+markupsafe==2.1.3
+    # via
+    #   -r requirements/test.txt
+    #   jinja2
+mccabe==0.7.0
+    # via pylint
+packaging==23.2
+    # via
+    #   -r requirements/test.txt
+    #   pytest
+pbr==5.11.1
+    # via
+    #   -r requirements/test.txt
+    #   stevedore
+platformdirs==3.11.0
+    # via pylint
+pluggy==1.3.0
+    # via
+    #   -r requirements/test.txt
+    #   pytest
+pycodestyle==2.11.0
+    # via -r requirements/quality.in
+pydocstyle==6.3.0
+    # via -r requirements/quality.in
+pylint==2.17.7
+    # via
+    #   edx-lint
+    #   pylint-celery
+    #   pylint-django
+    #   pylint-plugin-utils
+pylint-celery==0.3
+    # via edx-lint
+pylint-django==2.5.3
+    # via edx-lint
+pylint-plugin-utils==0.8.2
+    # via
+    #   pylint-celery
+    #   pylint-django
+pytest==7.4.2
+    # via
+    #   -r requirements/test.txt
+    #   pytest-cov
+    #   pytest-django
+pytest-cov==4.1.0
+    # via -r requirements/test.txt
+pytest-django==4.5.2
+    # via -r requirements/test.txt
+python-slugify==8.0.1
+    # via
+    #   -r requirements/test.txt
+    #   code-annotations
+pytz==2023.3.post1
+    # via
+    #   -r requirements/test.txt
+    #   django
+pyyaml==6.0.1
+    # via
+    #   -r requirements/test.txt
+    #   code-annotations
+six==1.16.0
+    # via edx-lint
+snowballstemmer==2.2.0
+    # via pydocstyle
+sqlparse==0.4.4
+    # via
+    #   -r requirements/test.txt
+    #   django
+stevedore==5.1.0
+    # via
+    #   -r requirements/test.txt
+    #   code-annotations
+text-unidecode==1.3
+    # via
+    #   -r requirements/test.txt
+    #   python-slugify
+tomli==2.0.1
+    # via
+    #   -r requirements/test.txt
+    #   coverage
+    #   pylint
+    #   pytest
+tomlkit==0.12.1
+    # via pylint
+typing-extensions==4.8.0
+    # via
+    #   -r requirements/test.txt
+    #   asgiref
+    #   astroid
+    #   pylint
+wrapt==1.15.0
+    # via astroid
diff --git a/requirements/test.txt b/requirements/test.txt
new file mode 100644
index 0000000..878494c
--- /dev/null
+++ b/requirements/test.txt
@@ -0,0 +1,65 @@
+#
+# This file is autogenerated by pip-compile with Python 3.8
+# by the following command:
+#
+#    make upgrade
+#
+asgiref==3.7.2
+    # via
+    #   -r requirements/base.txt
+    #   django
+click==8.1.7
+    # via code-annotations
+code-annotations==1.5.0
+    # via -r requirements/test.in
+coverage[toml]==7.3.2
+    # via pytest-cov
+    # via
+    #   -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt
+    #   -r requirements/base.txt
+exceptiongroup==1.1.3
+    # via pytest
+iniconfig==2.0.0
+    # via pytest
+jinja2==3.1.2
+    # via code-annotations
+markupsafe==2.1.3
+    # via jinja2
+packaging==23.2
+    # via pytest
+pbr==5.11.1
+    # via stevedore
+pluggy==1.3.0
+    # via pytest
+pytest==7.4.2
+    # via
+    #   pytest-cov
+    #   pytest-django
+pytest-cov==4.1.0
+    # via -r requirements/test.in
+pytest-django==4.5.2
+    # via -r requirements/test.in
+python-slugify==8.0.1
+    # via code-annotations
+pytz==2023.3.post1
+    # via
+    #   -r requirements/base.txt
+    #   django
+pyyaml==6.0.1
+    # via code-annotations
+sqlparse==0.4.4
+    # via
+    #   -r requirements/base.txt
+    #   django
+stevedore==5.1.0
+    # via code-annotations
+text-unidecode==1.3
+    # via python-slugify
+tomli==2.0.1
+    # via
+    #   coverage
+    #   pytest
+typing-extensions==4.8.0
+    # via
+    #   -r requirements/base.txt
+    #   asgiref
diff --git a/setup.cfg b/setup.cfg
index d782599..f171ddf 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -3,6 +3,7 @@ include_trailing_comma = True
 indent = '    '
 line_length = 120
 multi_line_output = 3
+profile = black
 skip=
     migrations
 
diff --git a/setup.py b/setup.py
index 777c57d..a954885 100755
--- a/setup.py
+++ b/setup.py
@@ -19,11 +19,10 @@ def get_version(*file_paths):
     """
     filename = os.path.join(os.path.dirname(__file__), *file_paths)
     version_file = open(filename, encoding="utf8").read()
-    version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
-                              version_file, re.M)
+    version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M)
     if version_match:
         return version_match.group(1)
-    raise RuntimeError('Unable to find version string.')
+    raise RuntimeError("Unable to find version string.")
 
 
 def load_requirements(*requirements_paths):
@@ -40,7 +39,9 @@ def load_requirements(*requirements_paths):
     # groups "pkg<=x.y.z,..." into ("pkg", "<=x.y.z,...")
     requirement_line_regex = re.compile(r"([a-zA-Z0-9-_.]+)([<>=][^#\s]+)?")
 
-    def add_version_constraint_or_raise(current_line, current_requirements, add_if_not_present):
+    def add_version_constraint_or_raise(
+        current_line, current_requirements, add_if_not_present
+    ):
         regex_match = requirement_line_regex.match(current_line)
         if regex_match:
             package = regex_match.group(1)
@@ -48,11 +49,16 @@ def add_version_constraint_or_raise(current_line, current_requirements, add_if_n
             existing_version_constraints = current_requirements.get(package, None)
             # fine to add constraints to an unconstrained package,
             # raise an error if there are already constraints in place
-            if existing_version_constraints and existing_version_constraints != version_constraints:
-                raise BaseException(f'Multiple constraint definitions found for {package}:'
-                                    f' "{existing_version_constraints}" and "{version_constraints}".'
-                                    f'Combine constraints into one location with {package}'
-                                    f'{existing_version_constraints},{version_constraints}.')
+            if (
+                existing_version_constraints
+                and existing_version_constraints != version_constraints
+            ):
+                raise BaseException(
+                    f"Multiple constraint definitions found for {package}:"
+                    f' "{existing_version_constraints}" and "{version_constraints}".'
+                    f"Combine constraints into one location with {package}"
+                    f"{existing_version_constraints},{version_constraints}."
+                )
             if add_if_not_present or package in current_requirements:
                 current_requirements[package] = version_constraints
 
@@ -63,8 +69,12 @@ def add_version_constraint_or_raise(current_line, current_requirements, add_if_n
             for line in reqs:
                 if is_requirement(line):
                     add_version_constraint_or_raise(line, requirements, True)
-                if line and line.startswith('-c') and not line.startswith('-c http'):
-                    constraint_files.add(os.path.dirname(path) + '/' + line.split('#')[0].replace('-c', '').strip())
+                if line and line.startswith("-c") and not line.startswith("-c http"):
+                    constraint_files.add(
+                        os.path.dirname(path)
+                        + "/"
+                        + line.split("#")[0].replace("-c", "").strip()
+                    )
 
     # process constraint files: add constraints to existing requirements
     for constraint_file in constraint_files:
@@ -74,7 +84,9 @@ def add_version_constraint_or_raise(current_line, current_requirements, add_if_n
                     add_version_constraint_or_raise(line, requirements, False)
 
     # process back into list of pkg><=constraints strings
-    constrained_requirements = [f'{pkg}{version or ""}' for (pkg, version) in sorted(requirements.items())]
+    constrained_requirements = [
+        f'{pkg}{version or ""}' for (pkg, version) in sorted(requirements.items())
+    ]
     return constrained_requirements
 
 
@@ -86,47 +98,57 @@ def is_requirement(line):
         bool: True if the line is not blank, a comment,
         a URL, or an included file
     """
-    return line and line.strip() and not line.startswith(("-r", "#", "-e", "git+", "-c"))
+    return (
+        line and line.strip() and not line.startswith(("-r", "#", "-e", "git+", "-c"))
+    )
 
 
-VERSION = get_version('platform_plugin_turnitin', '__init__.py')
+VERSION = get_version("platform_plugin_turnitin", "__init__.py")
 
-if sys.argv[-1] == 'tag':
+if sys.argv[-1] == "tag":
     print("Tagging the version on github:")
     os.system("git tag -a %s -m 'version %s'" % (VERSION, VERSION))
     os.system("git push --tags")
     sys.exit()
 
-README = open(os.path.join(os.path.dirname(__file__), 'README.rst'), encoding="utf8").read()
-CHANGELOG = open(os.path.join(os.path.dirname(__file__), 'CHANGELOG.rst'), encoding="utf8").read()
+README = open(
+    os.path.join(os.path.dirname(__file__), "README.rst"), encoding="utf8"
+).read()
+CHANGELOG = open(
+    os.path.join(os.path.dirname(__file__), "CHANGELOG.rst"), encoding="utf8"
+).read()
 
 setup(
-    name='platform-plugin-turnitin',
+    name="platform-plugin-turnitin",
     version=VERSION,
     description="""Open edX Django plugin for Turnitin integrations using Open edX Filters.""",
-    long_description=README + '\n\n' + CHANGELOG,
-    author='eduNEXT',
-    author_email='technical@edunext.co',
-    url='https://github.com/eduNEXT/platform-plugin-turnitin',
+    long_description=README + "\n\n" + CHANGELOG,
+    author="eduNEXT",
+    author_email="technical@edunext.co",
+    url="https://github.com/eduNEXT/platform-plugin-turnitin",
     packages=find_packages(
-        include=['platform_plugin_turnitin', 'platform_plugin_turnitin.*'],
+        include=["platform_plugin_turnitin", "platform_plugin_turnitin.*"],
         exclude=["*tests"],
     ),
-
     include_package_data=True,
-    install_requires=load_requirements('requirements/base.in'),
+    install_requires=load_requirements("requirements/base.in"),
     python_requires=">=3.8",
     license="AGPL 3.0",
     zip_safe=False,
-    keywords='Python edx',
+    keywords="Python edx",
     classifiers=[
-        'Development Status :: 3 - Alpha',
-        'Framework :: Django',
-        'Framework :: Django :: 3.2',
-        'Intended Audience :: Developers',
-        'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
-        'Natural Language :: English',
-        'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.8',
+        "Development Status :: 3 - Alpha",
+        "Framework :: Django",
+        "Framework :: Django :: 3.2",
+        "Intended Audience :: Developers",
+        "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
+        "Natural Language :: English",
+        "Programming Language :: Python :: 3",
+        "Programming Language :: Python :: 3.8",
     ],
+    entry_points={
+        "lms.djangoapp": [
+            "platform_plugin_turnitin = platform_plugin_turnitin.apps:PlatformPluginTurnitinConfig"
+        ],
+    },
 )