diff --git a/.gitea/workflows/python-package.yml b/.gitea/workflows/python-package.yml
new file mode 100644
index 0000000..2ee342a
--- /dev/null
+++ b/.gitea/workflows/python-package.yml
@@ -0,0 +1,16 @@
+name: Package Python
+on:
+  push:
+    tags:
+      - 'v[0-9]+.[0-9]+.[0-9]+'
+    paths-ignore: ['README.md', '.gitignore', 'LICENSE', 'CONVENTIONS.md', 'ruff.toml']
+
+jobs:
+  Package:
+    uses: jmaa/workflows/.gitea/workflows/python-package.yaml@v6.21
+    with:
+      REGISTRY_DOMAIN: gitfub.space
+      REGISTRY_ORGANIZATION: jmaa
+    secrets:
+      PIPY_REPO_USER: ${{ secrets.PIPY_REPO_USER }}
+      PIPY_REPO_PASS: ${{ secrets.PIPY_REPO_PASS }}
diff --git a/.gitea/workflows/python-test.yml b/.gitea/workflows/python-test.yml
new file mode 100644
index 0000000..4767f84
--- /dev/null
+++ b/.gitea/workflows/python-test.yml
@@ -0,0 +1,31 @@
+name: Run Python tests (through Pytest)
+
+on:
+  push:
+    paths-ignore: ['README.md', '.gitignore', 'LICENSE', 'CONVENTIONS.md', 'ruff.toml']
+
+jobs:
+  Test:
+    runs-on: ubuntu-latest
+    container:
+      image: node:21-bookworm
+    steps:
+      - name: Setting up Python ${{ env.PYTHON_VERSION }} for ${{runner.arch}} ${{runner.os}}
+        run: |
+           apt-get update
+           apt-get install -y python3 python3-pip
+      - name: Check out repository code
+        if: success()
+        uses: actions/checkout@v3
+      - name: Installing Python Dependencies
+        if: success()
+        run: python3 -m pip install --upgrade pip setuptools wheel build twine pytest pytest-cov --break-system-packages
+      - name: Installing Python Test Dependencies
+        if: success() && hashFiles('requirements_test.txt') != ''
+        run: python3 -m pip install --upgrade -r requirements_test.txt --break-system-packages
+      - name: Installing package
+        if: success()
+        run: python3 -m pip install .[test]  --break-system-packages
+      - name: Test Python Code
+        if: success()
+        run: python3 -m pytest test --cov=pbc_client --cov-report html:htmlcov --cov-fail-under=0
diff --git a/.gitea/workflows/python-version-check.yml b/.gitea/workflows/python-version-check.yml
new file mode 100644
index 0000000..70991b7
--- /dev/null
+++ b/.gitea/workflows/python-version-check.yml
@@ -0,0 +1,28 @@
+name: Verify Python project can be installed, loaded and have version checked
+
+on:
+  push:
+    paths-ignore: ['README.md', '.gitignore', 'LICENSE', 'CONVENTIONS.md', 'ruff.toml']
+
+jobs:
+  Test:
+    runs-on: ubuntu-latest
+    container:
+      image: node:21-bookworm
+    steps:
+      - name: Setting up Python ${{ env.PYTHON_VERSION }} for ${{runner.arch}} ${{runner.os}}
+        run: |
+           apt-get update
+           apt-get install -y python3 python3-pip
+      - name: Check out repository code
+        if: success()
+        uses: actions/checkout@v3
+      - name: Installing Python Dependencies
+        if: success()
+        run: python3 -m pip install --upgrade pip setuptools wheel build twine --break-system-packages
+      - name: Installing package
+        if: success()
+        run: python3 -m pip install .  --break-system-packages
+      - name: Check version field
+        if: success()
+        run: python3 -c "import pbc_client; assert pbc_client.__version__ is not None"
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..41180b8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,20 @@
+# Program specific
+/output/
+/deps/
+/secrets
+/private_deps/
+/data/
+/config/
+
+# Python
+__pycache__/
+/build/
+/dist/
+*.egg-info/
+.mypy_cache/
+
+# Python, Testing
+/test/secrets.py
+/.coverage
+/.hypothesis/
+/htmlcov/
diff --git a/CONVENTIONS.md b/CONVENTIONS.md
new file mode 100644
index 0000000..a8401c1
--- /dev/null
+++ b/CONVENTIONS.md
@@ -0,0 +1,15 @@
+When contributing code to this project, you MUST follow these principles:
+
+- Code should be easy to read and understand.
+- Keep the code as simple as possible. Avoid unnecessary complexity.
+- Use meaningful names for variables, functions, etc. Names should reveal intent.
+- Functions should be small and do one thing well. They should not exceed a few lines.
+- Function names should describe the action being performed.
+- Only use comments when necessary, as they can become outdated. Instead, strive to make the code self-explanatory.
+- When comments are used, they should add useful information that is not readily apparent from the code itself.
+- Properly handle errors and exceptions to ensure the software's robustness.
+- Use exceptions rather than error codes for handling errors.
+- Consider security implications of the code. Implement security best practices to protect against vulnerabilities and attacks.
+- Documentation should document semantics, not syntax.
+- Prefer importing modules, not individual items from modules.
+- Do not use f-strings in logging statements.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..4b4bb1b
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 Jon Michael Aanes
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index e69de29..91fff20 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,67 @@
+<!---                   WARNING                    --->
+<!---        THIS IS AN AUTO-GENERATED FILE        --->
+<!---  MANUAL CHANGES CAN AND WILL BE OVERWRITTEN  --->
+
+
+
+# 
+
+![Test program/library](https://gitfub.space/Jmaa/pbc-client/actions/workflows/python-test.yml/badge.svg)
+
+
+
+
+
+## Dependencies
+
+This project requires [Python](https://www.python.org/) 3.8 or newer.
+
+This project does not have any library requirements 😎
+
+## Contributing
+
+Feel free to submit pull requests. Please follow the [Code Conventions](CONVENTIONS.md) when doing so.
+
+
+### Testing
+
+Testing requires the [pytest](https://docs.pytest.org/en/stable/) library.
+
+Run tests with the following command:
+
+```sh
+pytest test
+```
+
+Test coverage can be run using the [`pytest-cov`](https://pypi.org/project/pytest-cov/) extension:
+
+```sh
+pytest --cov=pbc_client test
+```
+
+
+## License
+
+```
+MIT License
+
+Copyright (c) 2025 Jon Michael Aanes
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+```
diff --git a/pbc_client/_version.py b/pbc_client/_version.py
new file mode 100644
index 0000000..b794fd4
--- /dev/null
+++ b/pbc_client/_version.py
@@ -0,0 +1 @@
+__version__ = '0.1.0'
diff --git a/ruff.toml b/ruff.toml
new file mode 100644
index 0000000..c397e12
--- /dev/null
+++ b/ruff.toml
@@ -0,0 +1,80 @@
+#[tool.ruff]
+lint.select = [ 'ALL' ]
+lint.ignore = [
+    'ANN', # Type annotations (lots of work.)
+    'FBT', # Boolean trap is bullshit.
+    'C90', 'PLR0911',  'PLR0915', 'PLR0913', # Code complexity measures are bullshit.
+    'Q003', 'D205', # Format conflict
+
+    'TCH', # Microoptimization at the cost of readability
+    'TID252', # I like relative imports
+
+    'D407', 'D413', # Weird documentation stuff
+
+    'D100', 'D101', 'D102', 'D103', 'D104', 'D105', 'D106', 'D107', 'D300', 'D401', # Missing docstrings (lots of work)
+    'TD002', 'TD003', 'TD004', 'FIX', # Who cares about TODO standards?
+    "E501", 'PLR0912', 'PTH123', 'F405', 'E402', 'PLW0603',
+
+    'SIM102',
+
+    'TRY002', 'TRY003',
+]
+
+# Autofix
+lint.fixable = [
+    'SIM', 'C', 'Q',
+    'UP035', 'UP004', 'UP032', 'UP006', 'UP007', 'I001',
+    'F401', 'COM812', 'B011', 'PLR1722', 'PLR0402', 'S101',
+]
+lint.unfixable = ['SIM102', 'SIM114']
+
+# Exclude a variety of commonly ignored directories.
+exclude = [
+    ".bzr",
+    ".direnv",
+    ".eggs",
+    ".git",
+    ".hg",
+    ".mypy_cache",
+    ".nox",
+    ".pants.d",
+    ".pytype",
+    ".ruff_cache",
+    ".svn",
+    ".tox",
+    ".venv",
+    "__pypackages__",
+    "_build",
+    "buck-out",
+    "build",
+    "dist",
+    "node_modules",
+    "venv",
+]
+
+# Same as Black.
+line-length = 88
+
+# Allow unused variables when underscore-prefixed.
+lint.dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
+
+# Assume Python 3.10.
+target-version = "py310"
+
+[lint.flake8-quotes]
+inline-quotes = "single"
+multiline-quotes = "double"
+docstring-quotes = "double"
+
+[format]
+quote-style = "single"
+indent-style = "space"
+docstring-code-format = true
+
+[lint.per-file-ignores]
+"test/*" = [
+    "S101",    # Test Asserts
+    "T201",    # Debug prints
+    "PLR2004", # magic-value-comparison
+    'SLF001',  # Allow access to private members
+]
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..2ff1279
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,51 @@
+# WARNING
+#
+# THIS IS AN AUTOGENERATED FILE.
+#
+# MANUAL CHANGES CAN AND WILL BE OVERWRITTEN.
+
+import re
+
+from setuptools import setup
+
+PACKAGE_NAME = 'pbc_client'
+
+PACKAGE_DESCRIPTION = """
+""".strip()
+
+PACKAGE_DESCRIPTION_SHORT = """
+""".strip()
+
+
+def parse_version_file(text: str) -> str:
+    match = re.match(r'^__version__\s*=\s*(["\'])([\d\.]+)\1$', text)
+    if match is None:
+        msg = 'Malformed _version.py file!'
+        raise Exception(msg)
+    return match.group(2)
+
+
+with open(PACKAGE_NAME + '/_version.py') as f:
+    version = parse_version_file(f.read())
+
+
+REQUIREMENTS_MAIN = []
+REQUIREMENTS_TEST = []
+
+
+setup(
+    name=PACKAGE_NAME,
+    version=version,
+    description=PACKAGE_DESCRIPTION_SHORT,
+    long_description=PACKAGE_DESCRIPTION,
+    long_description_content_type='text/markdown',
+    author='Jon Michael Aanes',
+    author_email='jonjmaa@gmail.com',
+    url='https://gitfub.space/Jmaa/' + PACKAGE_NAME,
+    packages=[PACKAGE_NAME],
+    install_requires=REQUIREMENTS_MAIN,
+    extras_require={
+        'test': REQUIREMENTS_TEST,
+    },
+    python_requires='>=3.9',
+)