diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 0000000000000000000000000000000000000000..096ae14ebab27380feedb28bf923c29e112ab4ec
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,4 @@
+[run]
+omit = 
+    *example.py
+    */usr/*
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 75c602c4917dd6e028ce0d13998c170f33a74e3e..5ef0029b6b1aa805d65afec7d6f7a14bb5572e5a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -48,7 +48,7 @@ PEP8:
 Pylint:
   stage: linting
   # allow_failure: true
-  script: find . -type f -name '*.py' | xargs pylint -rn --fail-under=9 # Find all python files and check the code with pylint.
+  script: find src/plotid/ tests/ -type f -name '*.py' | xargs pylint -rn --fail-under=9 # Find all python files and check the code with pylint.
 
 test:
   stage: testing
@@ -56,7 +56,7 @@ test:
     - docker
   script:
 #     - python -m unittest discover -s ./tests/ -p "test*" # deprecated unittest command
-      - python runner_tests.py
+      - python tests/runner_tests.py
 #    - pip install tox flake8  # you can also use tox
 #    - tox -e py36,flake8
 
diff --git a/.pylintrc b/.pylintrc
new file mode 100644
index 0000000000000000000000000000000000000000..0b39a7bbb506aa7953d4a46ba3f69c1f06e98631
--- /dev/null
+++ b/.pylintrc
@@ -0,0 +1,2 @@
+[MASTER]
+init-hook='import sys; sys.path.append("./src/plotid")' 
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000000000000000000000000000000000000..d7e840034ed50460658669893359af8536606f5b
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,3 @@
+[build-system]
+requires = ["setuptools>=42"]
+build-backend = "setuptools.build_meta" 
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..2102a30cf3512d0fbeb877f5802eee1f387197fd
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,24 @@
+[metadata]
+name = example-package-plotid-test
+version = 0.0.1
+author = Example Author
+author_email = author@example.com
+description = A small example package
+long_description = file: README.md
+long_description_content_type = text/markdown
+url = https://github.com/pypa/sampleproject
+project_urls =
+    Bug Tracker = https://github.com/pypa/sampleproject/issues
+classifiers =
+    Programming Language :: Python :: 3
+    License :: OSI Approved :: Apache Software License
+    Operating System :: OS Independent
+
+[options]
+package_dir =
+    = src
+packages = find:
+python_requires = >=3.10
+
+[options.packages.find]
+where = src 
diff --git a/src/plotid/.pylintrc b/src/plotid/.pylintrc
new file mode 100644
index 0000000000000000000000000000000000000000..0b39a7bbb506aa7953d4a46ba3f69c1f06e98631
--- /dev/null
+++ b/src/plotid/.pylintrc
@@ -0,0 +1,2 @@
+[MASTER]
+init-hook='import sys; sys.path.append("./src/plotid")' 
diff --git a/src/plotid/__init__.py b/src/plotid/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/create_id.py b/src/plotid/create_id.py
similarity index 100%
rename from create_id.py
rename to src/plotid/create_id.py
diff --git a/example.py b/src/plotid/example.py
similarity index 87%
rename from example.py
rename to src/plotid/example.py
index b6302f7d7895616b2435d252b0c8a3777d1399e2..f8156f2acf233a057dc16fa6b9fbfefa03d2a1c9 100644
--- a/example.py
+++ b/src/plotid/example.py
@@ -57,5 +57,7 @@ for i, figure in enumerate(figs):
     figure.savefig(name)
 
 # %% Publish
-publish('tests', '/home/chief/Dokumente/fst/plotid_python/data',
+# Arguments: Source directory, destination directory, figure, plot (which is
+# already saved as picture, publish-mode).
+publish('../../tests', '/home/chief/Dokumente/fst/plotid_python/data',
         fig1, 'Bild', 'individual')
diff --git a/filecompare.py b/src/plotid/filecompare.py
similarity index 100%
rename from filecompare.py
rename to src/plotid/filecompare.py
diff --git a/hdf5_external_link.py b/src/plotid/hdf5_external_link.py
similarity index 100%
rename from hdf5_external_link.py
rename to src/plotid/hdf5_external_link.py
diff --git a/plotoptions.py b/src/plotid/plotoptions.py
similarity index 100%
rename from plotoptions.py
rename to src/plotid/plotoptions.py
diff --git a/publish.py b/src/plotid/publish.py
similarity index 100%
rename from publish.py
rename to src/plotid/publish.py
diff --git a/save_plot.py b/src/plotid/save_plot.py
similarity index 100%
rename from save_plot.py
rename to src/plotid/save_plot.py
diff --git a/tagplot.py b/src/plotid/tagplot.py
similarity index 100%
rename from tagplot.py
rename to src/plotid/tagplot.py
diff --git a/tagplot_matplotlib.py b/src/plotid/tagplot_matplotlib.py
similarity index 100%
rename from tagplot_matplotlib.py
rename to src/plotid/tagplot_matplotlib.py
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/runner_tests.py b/tests/runner_tests.py
similarity index 84%
rename from runner_tests.py
rename to tests/runner_tests.py
index cb159c4f6d24d86dddab007a15675160b5bdc835..20beec95206fe1dac53ae04765e9c50c295369d4 100644
--- a/runner_tests.py
+++ b/tests/runner_tests.py
@@ -8,15 +8,19 @@ Includes starting all tests and measuring the code coverage.
 import sys
 import unittest
 import coverage
+import os
+
+path = os.path.abspath('src/plotid')
+sys.path.append(path)
 
 cov = coverage.Coverage()
 cov.start()
 
 loader = unittest.TestLoader()
-tests = loader.discover('tests')
+tests = loader.discover('.')
 testRunner = unittest.runner.TextTestRunner(verbosity=2)
-
 result = testRunner.run(tests)
+
 cov.stop()
 cov.save()
 cov.report(show_missing=True)
diff --git a/tests/test_create_id.py b/tests/test_create_id.py
index d7c4b2e6f6d1f9a21a5fcb7593a4d1b8ead8f648..d4560624afba6a7a5c19141abc241b52f842b6dd 100644
--- a/tests/test_create_id.py
+++ b/tests/test_create_id.py
@@ -5,7 +5,7 @@ Unittests for CreateID
 """
 
 import unittest
-from create_id import create_id
+import src.plotid.create_id as cid
 
 
 class TestCreateID(unittest.TestCase):
@@ -15,20 +15,20 @@ class TestCreateID(unittest.TestCase):
 
     def test_existence(self):
         """Test if create_id returns a string."""
-        self.assertIsInstance(create_id(1), str)
-        self.assertIsInstance(create_id(2), str)
+        self.assertIsInstance(cid.create_id(1), str)
+        self.assertIsInstance(cid.create_id(2), str)
 
     def test_errors(self):
         """ Test if Errors are raised when id_method is wrong. """
         with self.assertRaises(ValueError):
-            create_id(3)
+            cid.create_id(3)
         with self.assertRaises(ValueError):
-            create_id('h')
+            cid.create_id('h')
 
     def test_length(self):
         """ Test if figure_id has the correct length. """
-        self.assertEqual(len(create_id(1)), 10)
-        self.assertEqual(len(create_id(2)), 8)
+        self.assertEqual(len(cid.create_id(1)), 10)
+        self.assertEqual(len(cid.create_id(2)), 8)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_publish.py b/tests/test_publish.py
index 40a6096b1213c8227fc433e0db3ed94929040ac7..86c3192524ff1dbc567ff12b8c0be9ca73c32907 100644
--- a/tests/test_publish.py
+++ b/tests/test_publish.py
@@ -10,7 +10,8 @@ import sys
 import shutil
 from unittest.mock import patch
 import matplotlib.pyplot as plt
-from publish import publish
+from src.plotid.publish import publish
+
 
 SRC_DIR = 'test_src_folder'
 PIC_NAME = 'test_picture'
diff --git a/tests/test_save_plot.py b/tests/test_save_plot.py
index a015223d1a6bfb8b6293675341093263387f31ce..14b8dee05e088d5bc93558f3268931d953a5e163 100644
--- a/tests/test_save_plot.py
+++ b/tests/test_save_plot.py
@@ -7,7 +7,7 @@ Unittests for save_plot
 import os
 import unittest
 import matplotlib.pyplot as plt
-from save_plot import save_plot
+from src.plotid.save_plot import save_plot
 
 FIGURE = plt.figure()
 PLOT_NAME = 'PLOT_NAME'