diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5d0087c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+examples/keygen-hello-world/dist/*
+examples/keygen-hello-world/keygen_hello_world.egg-info/*
diff --git a/README.md b/README.md
index c26fc87..fa1deb1 100644
--- a/README.md
+++ b/README.md
@@ -9,14 +9,16 @@ using Keygen's distribution API.
 First up, configure a few environment variables:
 
 ```bash
-# Your Keygen product token. You can generate a product token via the API
-# or your admin dashboard.
+# Your Keygen product token
+# You can generate a product token via, 
+# - your admin dashboard here: https://app.keygen.sh/tokens
+# - the API: https://keygen.sh/docs/api/tokens/#tokens-create
 export KEYGEN_PRODUCT_TOKEN="A_KEYGEN_PRODUCT_TOKEN"
 
-# Your Keygen account ID. Find yours at https://app.keygen.sh/settings.
+# Your Keygen account ID. Find yours at https://app.keygen.sh/settings
 export KEYGEN_ACCOUNT_ID="YOUR_KEYGEN_ACCOUNT_ID"
 
-# Your Keygen product ID.
+# Your Keygen product ID
 export KEYGEN_PRODUCT_ID="YOUR_KEYGEN_ACCOUNT_ID"
 ```
 
@@ -26,23 +28,54 @@ file and then run `source ~/.bashrc` after saving the file.
 
 Next, install dependencies with [`pip`](https://packaging.python.org/):
 
-```
+```bash
 pip install -r requirements.txt
 ```
 
-To create and upload a new release, run the program:
+```bash
+# build the package you will upload in the example
+cd examples/keygen-hello-world
 
+# build a wheel and source distribution
+python setup.py bdist_wheel sdist
 ```
+
+To create and upload a new release, run the program:
+```bash
 python main.py
 ```
 
 The script will create a new `1.0.0` release and then upload 2 artifacts:
 
-- `examples/hello-world.txt`
-- `examples/hello-mars.txt`
+- `keygen_hello_world-1.0.0-py3-none-any.whl`
+- `keygen-hello-world-1.0.0.tar.gz`
 
 After uploading the artifacts, the release will be published.
 
+You can now pip install the uploaded python package release:
+
+Export your license token and account slug:
+```bash
+# A license token, https://app.keygen.sh/licenses
+export KEYGEN_LICENSE_TOKEN="YOUR_KEYGEN_LICENSE_TOKEN"
+
+# Your Keygen account slug, https://app.keygen.sh/settings
+export KEYGEN_ACCOUNT_SLUG="YOUR_KEYGEN_ACCOUNT_SLUG"
+```
+
+Then install the package:
+```bash
+# TODO - this does not work for me - what am I doing wrong?
+pip install --index-url https://license:$KEYGEN_LICENSE_TOKEN@pypi.pkg.keygen.sh/$KEYGEN_ACCOUNT_SLUG/simple keygen-hello-world 
+```
+
+Or put this in your `requirements.txt` file:
+```txt
+# TODO - this does not work for me - what am I doing wrong?
+--index-url https://license:${KEYGEN_LICENSE_TOKEN}@pypi.pkg.keygen.sh/${KEYGEN_ACCOUNT_SLUG}/simple 
+keygen-hello-world
+```
+
 ## Questions?
 
 Reach out at [support@keygen.sh](mailto:support@keygen.sh) if you have any
diff --git a/examples/hello-mars.txt b/examples/hello-mars.txt
deleted file mode 100644
index 93675b0..0000000
--- a/examples/hello-mars.txt
+++ /dev/null
@@ -1 +0,0 @@
-Hello, mars!
diff --git a/examples/hello-world.txt b/examples/hello-world.txt
deleted file mode 100644
index af5626b..0000000
--- a/examples/hello-world.txt
+++ /dev/null
@@ -1 +0,0 @@
-Hello, world!
diff --git a/examples/keygen-hello-world/README.md b/examples/keygen-hello-world/README.md
new file mode 100644
index 0000000..6b1f781
--- /dev/null
+++ b/examples/keygen-hello-world/README.md
@@ -0,0 +1,12 @@
+# keygen-hello-world
+
+A simple Python package demonstrating Keygen's release and artifact functionality.
+
+## Usage
+
+```python
+from keygen_hello_world import hello_world, hello_mars
+
+print(hello_world())  # Output: Hello, World!
+print(hello_mars())   # Output: Hello, Mars!
+``` 
\ No newline at end of file
diff --git a/examples/keygen-hello-world/build/lib/keygen_hello_world/__init__.py b/examples/keygen-hello-world/build/lib/keygen_hello_world/__init__.py
new file mode 100644
index 0000000..8b36ce1
--- /dev/null
+++ b/examples/keygen-hello-world/build/lib/keygen_hello_world/__init__.py
@@ -0,0 +1,5 @@
+def hello_world():
+    return "Hello, World!"
+
+def hello_mars():
+    return "Hello, Mars!" 
\ No newline at end of file
diff --git a/examples/keygen-hello-world/keygen_hello_world/__init__.py b/examples/keygen-hello-world/keygen_hello_world/__init__.py
new file mode 100644
index 0000000..8b36ce1
--- /dev/null
+++ b/examples/keygen-hello-world/keygen_hello_world/__init__.py
@@ -0,0 +1,5 @@
+def hello_world():
+    return "Hello, World!"
+
+def hello_mars():
+    return "Hello, Mars!" 
\ No newline at end of file
diff --git a/examples/keygen-hello-world/setup.py b/examples/keygen-hello-world/setup.py
new file mode 100644
index 0000000..50d2221
--- /dev/null
+++ b/examples/keygen-hello-world/setup.py
@@ -0,0 +1,11 @@
+from setuptools import setup, find_packages
+
+setup(
+    name="keygen-hello-world",
+    version="1.0.0",
+    packages=find_packages(),
+    description="A simple hello world package for Keygen example",
+    author="Keygen",
+    author_email="support@keygen.sh",
+    url="https://keygen.sh",
+) 
\ No newline at end of file
diff --git a/main.py b/main.py
index faafdab..85972d5 100644
--- a/main.py
+++ b/main.py
@@ -1,8 +1,10 @@
-import requests
-import platform
 import json
-import sys
+from loguru import logger
 import os
+from pathlib import Path
+import platform
+import requests
+import sys
 
 def to_error_message(errs):
   """
@@ -47,13 +49,11 @@ def create_release(version, channel, name=None, tag=None):
   if 'errors' in release:
     errs = release['errors']
 
-    print(f'[error] Release failed: errors={to_error_message(errs)}',
-          file=sys.stderr)
+    logger.error(f'[error] Release failed: errors={to_error_message(errs)}')
 
     sys.exit(1)
   else:
-    print(f"[info] Created: release={release['data']['id']} link={release['data']['links']['self']}",
-          file=sys.stdout)
+    logger.info(f"[info] Created: release={release['data']['id']} link={release['data']['links']['self']}")
 
   return release['data']
 
@@ -76,13 +76,11 @@ def publish_release(release):
   if 'errors' in release:
     errs = release['errors']
 
-    print(f'[error] Publish failed: errors={to_error_message(errs)}',
-          file=sys.stderr)
+    logger.error(f'[error] Publish failed: errors={to_error_message(errs)}')
 
     sys.exit(1)
   else:
-    print(f"[info] Published: release={release['data']['id']} link={release['data']['links']['self']}",
-          file=sys.stdout)
+    logger.info(f"[info] Published: release={release['data']['id']} link={release['data']['links']['self']}")
 
   return release['data']
 
@@ -124,13 +122,11 @@ def upload_artifact_for_release(release, filename, filetype, filesize, platform,
   if 'errors' in artifact:
     errs = artifact['errors']
 
-    print(f'[error] Upload failed: errors={to_error_message(errs)}',
-          file=sys.stderr)
+    logger.error(f'[error] Upload failed: errors={to_error_message(errs)}')
 
     sys.exit(1)
   else:
-    print(f"[info] Uploaded: artifact={artifact['data']['id']} link={artifact['data']['links']['self']}",
-          file=sys.stdout)
+    logger.info(f"[info] Uploaded: artifact={artifact['data']['id']} link={artifact['data']['links']['self']}")
 
   # Follow redirect and upload file to storage provider
   upload_url = res.headers['location']
@@ -143,36 +139,40 @@ def upload_artifact_for_release(release, filename, filetype, filesize, platform,
 
   return artifact['data']
 
-release = create_release(
-  name='Python Release v1',
-  version='1.0.0',
-  channel='stable'
-)
-
-with open('examples/hello-world.txt', mode='r') as f:
-  stat = os.stat(f.name)
-
-  artifact = upload_artifact_for_release(
-    filename=f.name,
-    filesize=stat.st_size,
-    filetype='txt',
-    platform=f"{platform.system()} {platform.release()}",
-    arch=platform.processor(),
-    release=release,
-    data=f
-  )
 
-with open('examples/hello-mars.txt', mode='r') as f:
-  stat = os.stat(f.name)
-
-  artifact = upload_artifact_for_release(
-    filename=f.name,
-    filesize=stat.st_size,
-    filetype='txt',
-    platform=f"{platform.system()} {platform.release()}",
-    arch=platform.processor(),
-    release=release,
-    data=f
+if __name__ == '__main__':
+  release = create_release(
+    name='keygen-hello-world',
+    version='1.0.0',
+    channel='stable'
   )
 
-publish_release(release)
\ No newline at end of file
+  with open('examples/keygen-hello-world/dist/keygen_hello_world-1.0.0-py3-none-any.whl', mode='rb') as f:
+    filename = Path(f.name).name
+    stat = os.stat(f.name)
+
+    artifact = upload_artifact_for_release(
+      filename=filename,
+      filesize=stat.st_size,
+      filetype='whl',
+      platform=f"{platform.system()} {platform.release()}",
+      arch=platform.processor(),
+      release=release,
+      data=f
+    )
+
+  with open('examples/keygen-hello-world/dist/keygen-hello-world-1.0.0.tar.gz', mode='rb') as f:
+    filename = Path(f.name).name
+    stat = os.stat(f.name)
+
+    artifact = upload_artifact_for_release(
+      filename=filename,
+      filesize=stat.st_size,
+      filetype='tar.gz',
+      platform=f"{platform.system()} {platform.release()}",
+      arch=platform.processor(),
+      release=release,
+      data=f
+    )
+
+  publish_release(release)
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index a8ed785..0bc2e17 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1,3 @@
 requests==2.26.0
+loguru
+wheel
\ No newline at end of file