diff --git a/package-lock.json b/package-lock.json
index 0d9584124..f5e9ca80e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -24,6 +24,7 @@
         "@simplewebauthn/browser": "^10.0.0",
         "@simplewebauthn/server": "^10.0.0",
         "@tweenjs/tween.js": "^21.1.1",
+        "@types/qrcode": "^1.5.5",
         "@veramo/core": "^5.6.0",
         "@veramo/credential-w3c": "^5.6.0",
         "@veramo/data-store": "^5.6.0",
@@ -57,6 +58,7 @@
         "pina": "^0.20.2204228",
         "pinia-plugin-persistedstate": "^3.2.1",
         "qr-code-generator-vue3": "^1.4.21",
+        "qrcode": "^1.5.4",
         "ramda": "^0.29.1",
         "readable-stream": "^4.5.2",
         "reflect-metadata": "^0.1.14",
@@ -9766,6 +9768,14 @@
         "@types/node": "*"
       }
     },
+    "node_modules/@types/qrcode": {
+      "version": "1.5.5",
+      "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.5.tgz",
+      "integrity": "sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==",
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
     "node_modules/@types/ramda": {
       "version": "0.29.11",
       "dev": true,
@@ -13040,10 +13050,6 @@
       "version": "8.0.0",
       "license": "MIT"
     },
-    "node_modules/encode-utf8": {
-      "version": "1.0.3",
-      "license": "MIT"
-    },
     "node_modules/encodeurl": {
       "version": "1.0.2",
       "license": "MIT",
@@ -19720,11 +19726,11 @@
       }
     },
     "node_modules/qrcode": {
-      "version": "1.5.3",
-      "license": "MIT",
+      "version": "1.5.4",
+      "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz",
+      "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
       "dependencies": {
         "dijkstrajs": "^1.0.1",
-        "encode-utf8": "^1.0.3",
         "pngjs": "^5.0.0",
         "yargs": "^15.3.1"
       },
diff --git a/package.json b/package.json
index b7183a85f..54421f90d 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
     "@simplewebauthn/browser": "^10.0.0",
     "@simplewebauthn/server": "^10.0.0",
     "@tweenjs/tween.js": "^21.1.1",
+    "@types/qrcode": "^1.5.5",
     "@veramo/core": "^5.6.0",
     "@veramo/credential-w3c": "^5.6.0",
     "@veramo/data-store": "^5.6.0",
@@ -61,6 +62,7 @@
     "pina": "^0.20.2204228",
     "pinia-plugin-persistedstate": "^3.2.1",
     "qr-code-generator-vue3": "^1.4.21",
+    "qrcode": "^1.5.4",
     "ramda": "^0.29.1",
     "readable-stream": "^4.5.2",
     "reflect-metadata": "^0.1.14",
diff --git a/public/img/background/cert-frame-2.jpg b/public/img/background/cert-frame-2.jpg
new file mode 100644
index 000000000..a901aff03
Binary files /dev/null and b/public/img/background/cert-frame-2.jpg differ
diff --git a/src/main.ts b/src/main.ts
index 229497f8d..cd386a3f6 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -43,6 +43,7 @@ import {
   faEraser,
   faEye,
   faEyeSlash,
+  faFileContract,
   faFileLines,
   faFilter,
   faFloppyDisk,
@@ -117,6 +118,7 @@ library.add(
   faEraser,
   faEye,
   faEyeSlash,
+  faFileContract,
   faFileLines,
   faFilter,
   faFloppyDisk,
diff --git a/src/router/index.ts b/src/router/index.ts
index d255be5b6..e526302f4 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -43,6 +43,11 @@ const routes: Array<RouteRecordRaw> = [
     name: "claim-add-raw",
     component: () => import("../views/ClaimAddRawView.vue"),
   },
+  {
+    path: "/claim-cert/:id?",
+    name: "claim-cert",
+    component: () => import("../views/ClaimCertificateView.vue"),
+  },
   {
     path: "/confirm-contact",
     name: "confirm-contact",
diff --git a/src/views/ClaimCertificateView.vue b/src/views/ClaimCertificateView.vue
new file mode 100644
index 000000000..c87c39eac
--- /dev/null
+++ b/src/views/ClaimCertificateView.vue
@@ -0,0 +1,149 @@
+<template>
+  <section id="Content">
+    <div v-if="claimData">
+      <canvas ref="claimCanvas"></canvas>
+    </div>
+  </section>
+</template>
+
+<style scoped>
+canvas {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+}
+</style>
+
+<script lang="ts">
+import { Component, Vue } from "vue-facing-decorator";
+import { nextTick } from "vue";
+import QRCode from "qrcode";
+
+import { NotificationIface } from "@/constants/app";
+import { retrieveSettingsForActiveAccount } from "@/db/index";
+import * as endorserServer from "@/libs/endorserServer";
+
+@Component
+export default class ClaimViewCertificate extends Vue {
+  $notify!: (notification: NotificationIface, timeout?: number) => void;
+
+  activeDid = "";
+  allMyDids: Array<string> = [];
+  apiServer = "";
+  claimId = "";
+  claimData = null;
+
+  endorserServer = endorserServer;
+
+  async created() {
+    const settings = await retrieveSettingsForActiveAccount();
+    this.activeDid = settings.activeDid || "";
+    this.apiServer = settings.apiServer || "";
+    const pathParams = window.location.pathname.substring(
+      "/claim-cert/".length,
+    );
+    this.claimId = pathParams;
+    await this.fetchClaim();
+  }
+
+  async fetchClaim() {
+    try {
+      const response = await fetch(
+        `${this.apiServer}/api/claim/${this.claimId}`,
+      );
+      if (response.ok) {
+        this.claimData = await response.json();
+        await nextTick(); // Wait for the DOM to update
+        this.drawCanvas();
+      } else {
+        throw new Error(`Error fetching claim: ${response.statusText}`);
+      }
+    } catch (error) {
+      console.error("Failed to load claim:", error);
+      this.$notify({
+        group: "alert",
+        type: "danger",
+        title: "Error",
+        text: "There was a problem loading the claim.",
+      });
+    }
+  }
+
+  drawCanvas() {
+    const canvas = this.$refs.claimCanvas as HTMLCanvasElement;
+    if (canvas) {
+      const CANVAS_WIDTH = 1100;
+      const CANVAS_HEIGHT = 850;
+
+      // size to approximate portrait of 8.5"x11"
+      canvas.width = CANVAS_WIDTH;
+      canvas.height = CANVAS_HEIGHT;
+      const ctx = canvas.getContext("2d");
+      if (ctx) {
+        // Load the background image
+        const backgroundImage = new Image();
+        backgroundImage.src = "/img/background/cert-frame-2.jpg";
+        backgroundImage.onload = async () => {
+          // Draw the background image
+          ctx.drawImage(backgroundImage, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
+
+          // Set font and styles
+          ctx.fillStyle = "black";
+
+          // Draw claim type
+          ctx.font = "bold 20px Arial";
+          const claimTypeText =
+            this.endorserServer.capitalizeAndInsertSpacesBeforeCaps(
+              this.claimData.claimType,
+            );
+          const claimTypeWidth = ctx.measureText(claimTypeText).width;
+          ctx.fillText(
+            claimTypeText,
+            (CANVAS_WIDTH - claimTypeWidth) / 2, // Center horizontally
+            CANVAS_HEIGHT * 0.35,
+          );
+
+          const descriptionText =
+            this.claimData.claim.description || this.claimData.claim.name;
+          if (descriptionText) {
+            const descriptionLine =
+              descriptionText.length > 50
+                ? descriptionText.substring(0, 47) + "..."
+                : descriptionText;
+            ctx.font = "14px Arial";
+            const descriptionWidth = ctx.measureText(descriptionLine).width;
+            ctx.fillText(
+              descriptionLine,
+              (CANVAS_WIDTH - descriptionWidth) / 2,
+              CANVAS_HEIGHT * 0.45,
+            );
+          }
+
+          // Draw claim ID
+          ctx.font = "14px Arial";
+          ctx.fillText(this.claimId, CANVAS_WIDTH * 0.3, CANVAS_HEIGHT * 0.62);
+          ctx.fillText(
+            "via EndorserSearch.com",
+            CANVAS_WIDTH * 0.3,
+            CANVAS_HEIGHT * 0.65,
+          );
+
+          // Generate and draw QR code
+          const qrCodeCanvas = document.createElement("canvas");
+          await QRCode.toCanvas(qrCodeCanvas, window.location.href, {
+            width: 150,
+            color: { light: "#0000" /* Transparent background */ },
+          });
+          ctx.drawImage(
+            qrCodeCanvas,
+            CANVAS_WIDTH * 0.57,
+            CANVAS_HEIGHT * 0.55,
+          );
+        };
+      }
+    }
+  }
+}
+</script>
diff --git a/src/views/ClaimView.vue b/src/views/ClaimView.vue
index e58f4aad4..e318d685d 100644
--- a/src/views/ClaimView.vue
+++ b/src/views/ClaimView.vue
@@ -157,6 +157,14 @@
       <fa icon="comment" class="text-slate-400" />
       {{ issuerName }} posted that.
     </div>
+    <!--
+    <div>
+      <router-link :to="'/claim-cert/' + encodeURIComponent(veriClaim.id)">
+        <fa icon="file-contract" class="text-slate-400" />
+        <span class="ml-2 text-blue-500">Printable Certificate</span>
+      </router-link>
+    </div>
+    -->
 
     <div class="mt-8">
       <button
@@ -885,7 +893,6 @@ export default class ClaimView extends Vue {
         this.veriClaim as GenericCredWrapper<OfferVerifiableCredential>,
       ),
     };
-    console.log("giver & dialog", giver, this.$refs.customGiveDialog);
     (this.$refs.customGiveDialog as GiftedDialog).open(
       giver,
       undefined,