diff --git a/.forgejo/workflows/pull_request.yaml b/.forgejo/workflows/pull_request.yaml
index 8ca9d2b..bba274a 100644
--- a/.forgejo/workflows/pull_request.yaml
+++ b/.forgejo/workflows/pull_request.yaml
@@ -34,12 +34,21 @@ jobs:
               export GS_RELEASE_TYPE="minor"
           elif [[ "$latest_commit_message" == *"(patch)"* ]]; then
               export GS_RELEASE_TYPE="patch"
+          elif [[ "$latest_commit_message" == *"(docs)"* ]]; then
+              export GS_RELEASE_TYPE="norelease"
+          elif [[ "$latest_commit_message" == *"(norelease)"* ]]; then
+              export GS_RELEASE_TYPE="norelease"
           else
-              export GS_RELEASE_TYPE="patch"
+              export GS_RELEASE_TYPE="norelease"
           fi
+          echo "GS_RELEASE_TYPE=$GS_RELEASE_TYPE" >> $GITHUB_ENV
           echo "Previous Git Tag: $latest_git_tag"
           echo "Latest Commit: $latest_commit_message ($GS_RELEASE_TYPE) (SNAPSHOT)"
-          sbtn -Dsnapshot=true -Drelease="$GS_RELEASE_TYPE" semVerInfo
+          if [ "$GS_RELEASE_TYPE" = "norelease" ]; then
+            sbtn -Dsnapshot=true -Drelease="patch" semVerInfo
+          else
+            sbtn -Dsnapshot=true -Drelease="$GS_RELEASE_TYPE" semVerInfo
+          fi
       - name: 'Unit Tests and Code Coverage'
         run: |
           sbtn clean
@@ -48,5 +57,10 @@ jobs:
           sbtn coverageReport
       - name: 'Publish Snapshot'
         run: |
-          sbtn clean
-          sbtn publish
+          echo "Testing env var propagation = ${{ env.GS_RELEASE_TYPE }}"
+          if [ "${{ env.GS_RELEASE_TYPE }}" = "norelease" ]; then
+            echo "Skipping publish due to GS_RELEASE_TYPE=norelease"
+          else
+            sbtn clean
+            sbtn publish
+          fi
diff --git a/.forgejo/workflows/release.yaml b/.forgejo/workflows/release.yaml
index ecbd203..8351605 100644
--- a/.forgejo/workflows/release.yaml
+++ b/.forgejo/workflows/release.yaml
@@ -35,26 +35,49 @@ jobs:
               export GS_RELEASE_TYPE="minor"
           elif [[ "$latest_commit_message" == *"(patch)"* ]]; then
               export GS_RELEASE_TYPE="patch"
+          elif [[ "$latest_commit_message" == *"(docs)"* ]]; then
+              export GS_RELEASE_TYPE="norelease"
+          elif [[ "$latest_commit_message" == *"(norelease)"* ]]; then
+              export GS_RELEASE_TYPE="norelease"
           else
-              export GS_RELEASE_TYPE="patch"
+              export GS_RELEASE_TYPE="norelease"
           fi
+
+          echo "GS_RELEASE_TYPE=$GS_RELEASE_TYPE" >> $GITHUB_ENV
           echo "Previous Git Tag: $latest_git_tag"
           echo "Latest Commit: $latest_commit_message"
           echo "Selected Release Type: '$GS_RELEASE_TYPE'"
-          sbtn -Drelease="$GS_RELEASE_TYPE" semVerInfo
+
+          if [ "$GS_RELEASE_TYPE" = "norelease" ]; then
+            echo "Skipping all versioning for 'norelease' commit."
+          else
+            sbtn -Drelease="$GS_RELEASE_TYPE" semVerInfo
+          fi
       - name: 'Unit Tests and Code Coverage'
         run: |
-          sbtn clean
-          sbtn coverage
-          sbtn test
-          sbtn coverageReport
+          if [ "${{ env.GS_RELEASE_TYPE }}" = "norelease" ]; then
+            echo "Skipping build/test for 'norelease' commit."
+          else
+            sbtn clean
+            sbtn coverage
+            sbtn test
+            sbtn coverageReport
+          fi
       - name: 'Publish Release'
         run: |
-          sbtn clean
-          sbtn semVerWriteVersionToFile
-          sbtn publish
+          if [ "${{ env.GS_RELEASE_TYPE }}" = "norelease" ]; then
+            echo "Skipping publish for 'norelease' commit."
+          else
+            sbtn clean
+            sbtn semVerWriteVersionToFile
+            sbtn publish
+          fi
       - name: 'Create Git Tag'
         run: |
-          selected_version="$(cat .version)"
-          git tag "$selected_version"
-          git push origin "$selected_version"
+          if [ "${{ env.GS_RELEASE_TYPE }}" = "norelease" ]; then
+            echo "Skipping Git tag for 'norelease' commit."
+          else
+            selected_version="$(cat .version)"
+            git tag "$selected_version"
+            git push origin "$selected_version"
+          fi
diff --git a/README.md b/README.md
index bcbbf8e..43c52ea 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,20 @@
 # gs-hex
 
-[License (Apache 2.0)](./LICENSE)
+[GS Open Source](https://garrity.co/oss.html) |
+[License (MIT)](./LICENSE)
 
 Hexadecimal conversions for Scala 3. Provides support for standard types.
 
 - [Usage](#usage)
+    - [Dependency](#dependency)
+    - [Byte Array Conversion](#byte-array-conversion)
+    - [Type Classes](#type-classes)
+- [Donate](#donate)
 
 ## Usage
 
+### Dependency
+
 This artifact is available in the Garrity Software Maven repository.
 
 ```scala
@@ -15,5 +22,52 @@ externalResolvers +=
   "Garrity Software Releases" at "https://maven.garrity.co/releases"
 
 val GsHex: ModuleID =
-  "gs" %% "gs-hex-v0" % "0.1.0"
+  "gs" %% "gs-hex-v0" % "$VERSION"
 ```
+
+### Byte Array Conversion
+
+This library is based on two functions: `Hex.toHexString(Array[Byte])` and
+`Hex.fromHexString(String)`.
+
+```scala
+import gs.hex.v0.Hex
+
+val data: Array[Byte] = ???
+val encoded: String = Hex.toHexString(data)
+val decoded: Option[Array[Byte]] = Hex.fromHexString(encoded)
+```
+
+### Type Classes
+
+This library provides `HexEncode[A]` and `HexDecode[A]` for encoding and
+decoding arbitrary types as Hexadecimal strings. The types `Array[Byte]`,
+`String`, `Boolean`, `Int` and `Long` are supported by default.
+
+#### Example Type Class Implementations
+
+```scala
+given HexEncode[Array[Byte]] = new HexEncode[Array[Byte]] {
+  def toHexString(data: Array[Byte]): String = Hex.toHexString(data)
+}
+
+given HexDecode[Array[Byte]] = new HexDecode[Array[Byte]] {
+  def fromHexString(data: String): Option[Array[Byte]] =
+    Hex.fromHexString(data)
+}
+```
+
+#### Example Type Class Usage
+
+```scala
+def encode[A](data: A)(using HexEncode[A]): String =
+  data.toHex()
+
+def decode[A](data: String)(using HexDecode[A]): Option[A] =
+  data.fromHex()
+```
+
+## Donate
+
+Enjoy this project or want to help me achieve my [goals](https://garrity.co)?
+Consider [Donating to Pat on Ko-fi](https://ko-fi.com/gspfm).