diff --git a/src/views/InviteOneView.vue b/src/views/InviteOneView.vue
index 563bec4b..f1cbfa36 100644
--- a/src/views/InviteOneView.vue
+++ b/src/views/InviteOneView.vue
@@ -73,17 +73,15 @@
                   invite.expiresAt > new Date().toISOString()
                 "
                 class="text-center text-blue-500 cursor-pointer"
-                :title="inviteLink(invite.jwt)"
-                @click="
-                  copyInviteAndNotify(invite.inviteIdentifier, invite.jwt)
-                "
+                title="Click to copy invite link"
+                @click="copyInviteAndNotify(invite)"
               >
                 {{ getTruncatedInviteId(invite.inviteIdentifier) }}
               </span>
               <span
                 v-else
                 class="text-center text-slate-500 cursor-pointer"
-                :title="inviteLink(invite.jwt)"
+                title="Click to see invite details"
                 @click="
                   showInvite(
                     invite.inviteIdentifier,
@@ -120,6 +118,8 @@
                 @click="deleteInvite(invite.inviteIdentifier, invite.notes)"
               />
             </td>
+            <td class="hidden" :data-testId="invite.jwt" aria-hidden="true">
+            </td>
           </tr>
         </tbody>
       </table>
@@ -146,7 +146,7 @@ import { logger } from "../utils/logger";
 interface Invite {
   inviteIdentifier: string;
   expiresAt: string;
-  jwt: string;
+  jwt?: string; // only used to store a JWT for testing, after the link is clicked
   notes: string;
   redeemedAt: string | null;
   redeemedBy: string | null;
@@ -220,18 +220,27 @@ export default class InviteOneView extends Vue {
     return `${redeemedBy.slice(0, 13)}...${redeemedBy.slice(-3)}`;
   }
 
-  inviteLink(jwt: string): string {
+  inviteLink(jwt: string | undefined): string {
+    if (!jwt) return "Click to set JWT link";
     return APP_SERVER + "/invite-one-accept/" + jwt;
   }
 
-  copyInviteAndNotify(inviteId: string, jwt: string) {
-    useClipboard().copy(this.inviteLink(jwt));
+  async copyInviteAndNotify(invite: Invite) {
+    const expiresIn = (new Date(invite.expiresAt).getTime() - Date.now()) / 1000;
+    const inviteJwt = await createInviteJwt(
+      this.activeDid,
+      undefined,
+      invite.inviteIdentifier,
+      expiresIn,
+    );
+    invite.jwt = inviteJwt; // set for testing
+    useClipboard().copy(this.inviteLink(inviteJwt));
     this.$notify(
       {
         group: "alert",
         type: "success",
         title: "Copied",
-        text: "Your clipboard now contains the link for invite " + inviteId,
+        text: "Your clipboard now contains the link for invite " + invite.inviteIdentifier,
       },
       5000,
     );
@@ -295,22 +304,14 @@ export default class InviteOneView extends Vue {
               },
             };
           }
-          const expiresIn = (new Date(expiresAt).getTime() - Date.now()) / 1000;
-          const inviteJwt = await createInviteJwt(
-            this.activeDid,
-            undefined,
-            inviteIdentifier,
-            expiresIn,
-          );
           await axios.post(
             this.apiServer + "/api/userUtil/invite",
-            { inviteJwt: inviteJwt, notes: notes },
+            { inviteIdentifier: inviteIdentifier, notes: notes, expiresAt: expiresAt },
             { headers },
           );
           const newInvite = {
             inviteIdentifier: inviteIdentifier,
             expiresAt: expiresAt,
-            jwt: inviteJwt,
             notes: notes,
             redeemedAt: null,
             redeemedBy: null,
diff --git a/test-playwright/05-invite.spec.ts b/test-playwright/05-invite.spec.ts
index 821f7c39..c0c34668 100644
--- a/test-playwright/05-invite.spec.ts
+++ b/test-playwright/05-invite.spec.ts
@@ -44,6 +44,11 @@ test('Check User 0 can invite someone', async ({ page }) => {
   await expect(page.locator('div[role="alert"] button:has-text("Yes")')).toBeHidden();
 
   // check that the invite is in the list
+  const newInviteRow = page.locator(`tr:has(td:has-text("Neighbor ${neighborNum}"))`);
+  await expect(newInviteRow).toBeVisible();
+  // click on the link in the first column, which generates the JWT in the other column
+  await newInviteRow.locator('td:first-child').click();
+
   const newInviteLine = page.locator(`td:has-text("Neighbor ${neighborNum}")`);
   await expect(newInviteLine).toBeVisible();
   // retrieve the link from the title