From 16d2ee496e3bcfbf8773cf021b5d49be4915cc64 Mon Sep 17 00:00:00 2001 From: Nate Otto Date: Thu, 18 Dec 2025 09:26:35 -0800 Subject: [PATCH 1/4] Example json-card render method template method for consideration --- index.html | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) diff --git a/index.html b/index.html index a8bd844..7ffe508 100644 --- a/index.html +++ b/index.html @@ -600,6 +600,193 @@

The `pdf-mustache` Render Suite

+
+

The `json-card` Render Suite

+

+The `json-card` render suite uses the JSONata templating language to +transform a [=verifiable credential=] into a standardized JSON card format. +This format enables wallets to display credentials in a responsive card layout +with key data highlighted and configurable additional fields. Wallets that +implement this method can render the standardized JSON output into their own +card UI designs, allowing credentials to be displayed even when a wallet +doesn't natively support a specific credential type. +

+ +

+The template is expressed as a JSONata expression string. When the template +is evaluated against the [=verifiable credential=] data, it MUST produce +output that conforms to the json-card JSON schema defined below. +

+ +
+

JSON Card Schema

+

+The output of a `json-card` template MUST be a JSON object that conforms to +the following structure: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
name[=string=] +A REQUIRED display name for the credential card. +
description[=string=] +A REQUIRED description text for the credential card. +
icon[=string=] +An OPTIONAL URL or data URI for an icon or image to display on the card. +
theme[=ordered map|map=] +An OPTIONAL color theme object with the following properties: +
    +
  • primaryColor ([=string=]): Primary color for backgrounds and highlights
  • +
  • accentColor ([=string=]): Accent color for highlights and emphasis
  • +
+
fields[=list=] +A REQUIRED ordered list of custom data fields. Each field is an object with: +
    +
  • label ([=string=]): The field label
  • +
  • value ([=string=]): The field value
  • +
+
issueDate[=string=] +An OPTIONAL ISO 8601 date string indicating when the credential was issued. +
expirationDate[=string=] +An OPTIONAL ISO 8601 date string indicating when the credential expires. +
+ +

+The following example shows a valid json-card output: +

+ +
+{
+  "name": "Bachelor of Science and Arts",
+  "description": "University Degree Credential",
+  "icon": "https://example.edu/icons/degree.svg",
+  "theme": {
+    "primaryColor": "#1a5490",
+    "accentColor": "#4a90e2"
+  },
+  "fields": [
+    {
+      "label": "Institution",
+      "value": "Example University"
+    },
+    {
+      "label": "Degree Type",
+      "value": "BachelorDegree"
+    },
+    {
+      "label": "Graduation Date",
+      "value": "2010-05-15"
+    }
+  ],
+  "issueDate": "2010-01-01T19:23:24Z",
+  "expirationDate": null
+}
+            
+ +
+ +

+In the example below, a fully embedded JSONata template is used as the rendering +template. +

+ +
+{
+  ...
+  "renderMethod": {
+    "type": "TemplateRenderMethod",
+    "renderSuite": "json-card",
+    "template": "data:text/plain;base64,eyJuYW1lIjogY3JlZGVudGlhbFN1YmplY3QuZGVncmVlLm5hbWUsICJkZXNjcmlwdGlvbiI6ICJVbml2ZXJzaXR5IERlZ3JlZSBDcmVkZW50aWFsIiwgImZpZWxkcyI6IFt7ImxhYmVsIjogIkluc3RpdHV0aW9uIiwgInZhbHVlIjogaXNzdWVyfV19"
+  }
+}
+          
+ +

+The next example links to the JSONata template on the Web and secures it against +modification by using the `digestMultibase` property. +

+ +
+{
+...
+"renderMethod": {
+  "type": "TemplateRenderMethod",
+  "renderSuite": "json-card",
+  "template": {
+    "id": "https://degree.example/credential-templates/bachelors.jsonata",
+    "mediaType": "text/plain",
+    "digestMultibase": "zQmerWC85Wg6wFl9znFCwYxApG270iEu5h6JqWAPdhyxz2dR"
+  }
+}
+          
+ +

+The next example links to the rendering template on the Web and secures it +using the `digestMultibase` property: +

+ +
+{
+...
+"renderMethod": {
+  // this render method is fetched from the Web
+  "id": "https://degrees.example/bachelors-json-card.jsonld",
+  "mediaType": "application/ld+json",
+  "type": "TemplateRenderMethod",
+  "renderSuite": "json-card",
+  "digestMultibase": "zQmG270iEu5h6JqWAPdhyxz2dRerWC85Wg6wFl9znFCwYxAp"
+}
+          
+ +
+

The `nfc` Render Suite

From 0b9b6806fe9b08945dcfea266f902cd6062d68ab Mon Sep 17 00:00:00 2001 From: Nate Otto Date: Thu, 18 Dec 2025 09:56:39 -0800 Subject: [PATCH 2/4] Switch to JSON pointer --- index.html | 287 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 269 insertions(+), 18 deletions(-) diff --git a/index.html b/index.html index 7ffe508..0617ffa 100644 --- a/index.html +++ b/index.html @@ -603,23 +603,221 @@

The `pdf-mustache` Render Suite

The `json-card` Render Suite

-The `json-card` render suite uses the JSONata templating language to -transform a [=verifiable credential=] into a standardized JSON card format. -This format enables wallets to display credentials in a responsive card layout -with key data highlighted and configurable additional fields. Wallets that -implement this method can render the standardized JSON output into their own -card UI designs, allowing credentials to be displayed even when a wallet -doesn't natively support a specific credential type. +The `json-card` render suite uses JSON templates to transform a +[=verifiable credential=] into a standardized JSON card format. This format +enables wallets to display credentials in a responsive card layout with key +data highlighted and configurable additional fields. Wallets that implement +this method can render the standardized JSON output into their own card UI +designs, allowing credentials to be displayed even when a wallet doesn't +natively support a specific credential type.

-The template is expressed as a JSONata expression string. When the template -is evaluated against the [=verifiable credential=] data, it MUST produce -output that conforms to the json-card JSON schema defined below. +The template is a JSON object that matches the json-card output structure. +String values in the template can be JSON pointer strings (as specified in +[[[RFC6901]]]) that reference fields in the [=verifiable credential=]. When +processing the template, JSON pointer strings are evaluated against the +credential data and replaced with the resolved values. The template MUST +conform to the JSON template schema defined below, and the resulting output +MUST conform to the json-card output schema. Compound data across multiple +fields is not supported; each field references a single JSON pointer.

-

JSON Card Schema

+

JSON Template Schema

+

+The template for a `json-card` render suite MUST be a JSON object that +conforms to the following structure. The template structure matches the +output structure, but string values can be either literal strings or JSON +pointer strings (starting with `/`) that reference fields in the +[=verifiable credential=]. The template SHOULD be validated against this +schema before processing. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
name[=string=] +A REQUIRED string that is either a literal display name or a JSON pointer +string (e.g., "/credentialSubject/degree/name") that references +the credential data. +
description[=string=] +A REQUIRED string that is either a literal description or a JSON pointer +string that references the credential data. +
icon[=string=] +An OPTIONAL string that is either a literal URL/data URI or a JSON pointer +string that references the credential data. +
theme[=ordered map|map=] +An OPTIONAL color theme object with the following properties: +
    +
  • primaryColor ([=string=]): Primary color as a literal string or JSON pointer
  • +
  • accentColor ([=string=]): Accent color as a literal string or JSON pointer
  • +
+
fields[=list=] +A REQUIRED ordered list of custom data fields. Each field is an object with: +
    +
  • label ([=string=]): The field label (MUST be a literal string, not a JSON pointer)
  • +
  • value ([=string=]): The field value as a JSON pointer string (e.g., "/issuer")
  • +
+
issueDate[=string=] +An OPTIONAL string that is either a literal ISO 8601 date or a JSON pointer +string that references the credential data. +
expirationDate[=string=] +An OPTIONAL string that is either a literal ISO 8601 date or a JSON pointer +string that references the credential data. +
+ +

+The following JSON Schema implements the template structure rules defined +above: +

+ +
+{
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
+  "type": "object",
+  "required": ["name", "description", "fields"],
+  "properties": {
+    "name": {
+      "type": "string",
+      "description": "Display name as a literal string or JSON pointer (e.g., \"/credentialSubject/degree/name\")"
+    },
+    "description": {
+      "type": "string",
+      "description": "Description as a literal string or JSON pointer"
+    },
+    "icon": {
+      "type": "string",
+      "description": "Icon URL/data URI as a literal string or JSON pointer"
+    },
+    "theme": {
+      "type": "object",
+      "properties": {
+        "primaryColor": {
+          "type": "string",
+          "description": "Primary color as a literal string or JSON pointer"
+        },
+        "accentColor": {
+          "type": "string",
+          "description": "Accent color as a literal string or JSON pointer"
+        }
+      },
+      "additionalProperties": false
+    },
+    "fields": {
+      "type": "array",
+      "minItems": 1,
+      "items": {
+        "type": "object",
+        "required": ["label", "value"],
+        "properties": {
+          "label": {
+            "type": "string",
+            "description": "Field label (MUST be a literal string, not a JSON pointer)"
+          },
+          "value": {
+            "type": "string",
+            "pattern": "^/",
+            "description": "Field value as a JSON pointer string (MUST start with \"/\")"
+          }
+        },
+        "additionalProperties": false
+      }
+    },
+    "issueDate": {
+      "type": "string",
+      "description": "Issue date as a literal ISO 8601 date string or JSON pointer"
+    },
+    "expirationDate": {
+      "type": "string",
+      "description": "Expiration date as a literal ISO 8601 date string or JSON pointer"
+    }
+  },
+  "additionalProperties": false
+}
+            
+ +

+The following example shows a valid json-card template with JSON pointer +strings: +

+ +
+{
+  "name": "/credentialSubject/degree/name",
+  "description": "University Degree Credential",
+  "icon": "/credentialSubject/icon",
+  "theme": {
+    "primaryColor": "#1a5490",
+    "accentColor": "/credentialSubject/theme/accentColor"
+  },
+  "fields": [
+    {
+      "label": "Institution",
+      "value": "/issuer"
+    },
+    {
+      "label": "Degree Type",
+      "value": "/credentialSubject/degree/type"
+    },
+    {
+      "label": "Issue Date",
+      "value": "/validFrom"
+    }
+  ],
+  "issueDate": "/validFrom",
+  "expirationDate": "/validUntil"
+}
+            
+ +
+ +
+

JSON Card Output Schema

The output of a `json-card` template MUST be a JSON object that conforms to the following structure: @@ -729,9 +927,60 @@

JSON Card Schema

+
+

Template Processing

+

+When processing a `json-card` template, the following steps MUST be +performed: +

+ +
    +
  1. +Validate the template JSON object against the JSON template schema defined +above. If validation fails, processing MUST stop and an error MUST be +returned. +
  2. +
  3. +For each string value in the template object: +
      +
    1. +If the string value starts with `/` (indicating it is a JSON pointer), +evaluate it using the JSON Pointer algorithm [[[RFC6901]]] against the +[=verifiable credential=] as the target document. +
    2. +
    3. +If the JSON pointer evaluation succeeds, replace the JSON pointer string with +the resolved value. If the resolved value is not a string, convert it to a +string representation. +
    4. +
    5. +If the JSON pointer evaluation fails or returns `null`, the behavior is +implementation-specific. Implementations MAY use an empty string, leave the +value as `null`, or signal an error. +
    6. +
    7. +If the string value does not start with `/`, treat it as a literal string +and leave it unchanged. +
    8. +
    +
  4. +
  5. +Validate the resulting JSON object against the json-card output schema. If +validation fails, processing MUST stop and an error MUST be returned. +
  6. +
+ +

+Note that compound data across multiple fields is not supported. Each field +in the template references a single JSON pointer that resolves to a single +value from the credential. +

+ +
+

-In the example below, a fully embedded JSONata template is used as the rendering -template. +In the example below, a fully embedded JSON template is used as the rendering +template. The template uses JSON pointer strings to reference credential data.

JSON Card Schema
   "renderMethod": {
     "type": "TemplateRenderMethod",
     "renderSuite": "json-card",
-    "template": "data:text/plain;base64,eyJuYW1lIjogY3JlZGVudGlhbFN1YmplY3QuZGVncmVlLm5hbWUsICJkZXNjcmlwdGlvbiI6ICJVbml2ZXJzaXR5IERlZ3JlZSBDcmVkZW50aWFsIiwgImZpZWxkcyI6IFt7ImxhYmVsIjogIkluc3RpdHV0aW9uIiwgInZhbHVlIjogaXNzdWVyfV19"
+    // the JSON template is embedded in the VC
+    "template": "data:application/json;base64,eyJuYW1lIjogIi9jcmVkZW50aWFsU3ViamVjdC9kZWdyZWUvbmFtZSIsICJkZXNjcmlwdGlvbiI6ICJVbml2ZXJzaXR5IERlZ3JlZSBDcmVkZW50aWFsIiwgImZpZWxkcyI6IFt7ImxhYmVsIjogIkluc3RpdHV0aW9uIiwgInZhbHVlIjogIi9pc3N1ZXIifV19"
   }
 }
           

-The next example links to the JSONata template on the Web and secures it against +The next example links to the JSON template on the Web and secures it against modification by using the `digestMultibase` property.

+              title="A remotely hosted JSON template for a json-card render template">
 {
 ...
 "renderMethod": {
   "type": "TemplateRenderMethod",
   "renderSuite": "json-card",
   "template": {
-    "id": "https://degree.example/credential-templates/bachelors.jsonata",
-    "mediaType": "text/plain",
+    // this JSON template is fetched from the Web
+    "id": "https://degree.example/credential-templates/bachelors.json",
+    "mediaType": "application/json",
     "digestMultibase": "zQmerWC85Wg6wFl9znFCwYxApG270iEu5h6JqWAPdhyxz2dR"
   }
 }

From 15fd0ab641f70b27e053d5a42442ba2b829abde8 Mon Sep 17 00:00:00 2001
From: Nate Otto 
Date: Tue, 17 Mar 2026 18:47:43 -0700
Subject: [PATCH 3/4] feat(json-card): Text formatting updates

Co-authored-by: @TallTed 

Co-authored-by: Ted Thibodeau Jr 
---
 index.html | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/index.html b/index.html
index 0617ffa..c4eb59a 100644
--- a/index.html
+++ b/index.html
@@ -607,19 +607,19 @@ 

The `json-card` Render Suite

[=verifiable credential=] into a standardized JSON card format. This format enables wallets to display credentials in a responsive card layout with key data highlighted and configurable additional fields. Wallets that implement -this method can render the standardized JSON output into their own card UI +this method can render the standardized JSON output in their own card UI designs, allowing credentials to be displayed even when a wallet doesn't natively support a specific credential type.

-The template is a JSON object that matches the json-card output structure. +The template is a JSON object that matches the `json-card` output structure. String values in the template can be JSON pointer strings (as specified in [[[RFC6901]]]) that reference fields in the [=verifiable credential=]. When processing the template, JSON pointer strings are evaluated against the credential data and replaced with the resolved values. The template MUST conform to the JSON template schema defined below, and the resulting output -MUST conform to the json-card output schema. Compound data across multiple +MUST conform to the `json-card` output schema. Compound data across multiple fields is not supported; each field references a single JSON pointer.

@@ -781,7 +781,7 @@

JSON Template Schema

-The following example shows a valid json-card template with JSON pointer +The following example shows a valid `json-card` template with JSON pointer strings:

@@ -893,7 +893,7 @@

JSON Card Output Schema

-The following example shows a valid json-card output: +The following example shows a valid `json-card` output:

Template Processing
                 
               
               
  • -Validate the resulting JSON object against the json-card output schema. If +Validate the resulting JSON object against the `json-card` output schema. If validation fails, processing MUST stop and an error MUST be returned.
  • From d26a211fead8c35f05737228c33b40be5c459029 Mon Sep 17 00:00:00 2001 From: Nate Otto Date: Tue, 17 Mar 2026 19:02:28 -0700 Subject: [PATCH 4/4] feat(json-card): Add language tag for custom fields (including labels). - users are expected to translate core field labels themselves --- index.html | 55 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/index.html b/index.html index c4eb59a..cc7344d 100644 --- a/index.html +++ b/index.html @@ -118,6 +118,11 @@ alternateFormats: [ {uri: "diff-20111214.html", label: "diff to previous version"} ], */ localBiblio: { + BCP47: { + title: "Tags for Identifying Languages", + href: "https://www.rfc-editor.org/info/bcp47", + publisher: "IETF", + }, ENTRY: { title: "Example Title", href: "https://website.example/document", @@ -607,19 +612,19 @@

    The `json-card` Render Suite

    [=verifiable credential=] into a standardized JSON card format. This format enables wallets to display credentials in a responsive card layout with key data highlighted and configurable additional fields. Wallets that implement -this method can render the standardized JSON output in their own card UI +this method can render the standardized JSON output in their own card UI designs, allowing credentials to be displayed even when a wallet doesn't natively support a specific credential type.

    -The template is a JSON object that matches the `json-card` output structure. +The template is a JSON object that matches the `json-card` output structure. String values in the template can be JSON pointer strings (as specified in [[[RFC6901]]]) that reference fields in the [=verifiable credential=]. When processing the template, JSON pointer strings are evaluated against the credential data and replaced with the resolved values. The template MUST conform to the JSON template schema defined below, and the resulting output -MUST conform to the `json-card` output schema. Compound data across multiple +MUST conform to the `json-card` output schema. Compound data across multiple fields is not supported; each field references a single JSON pointer.

    @@ -687,23 +692,24 @@

    JSON Template Schema

    • label ([=string=]): The field label (MUST be a literal string, not a JSON pointer)
    • value ([=string=]): The field value as a JSON pointer string (e.g., "/issuer")
    • +
    • language ([=string=]): An OPTIONAL language tag (as specified in [[[BCP47]]]) indicating the language of the field's label and/or value
    - issueDate + validFrom [=string=] An OPTIONAL string that is either a literal ISO 8601 date or a JSON pointer -string that references the credential data. +string that references the credential data (validity start date). - expirationDate + validUntil [=string=] An OPTIONAL string that is either a literal ISO 8601 date or a JSON pointer -string that references the credential data. +string that references the credential data (validity end date). @@ -762,18 +768,22 @@

    JSON Template Schema

    "type": "string", "pattern": "^/", "description": "Field value as a JSON pointer string (MUST start with \"/\")" + }, + "language": { + "type": "string", + "description": "Optional BCP 47 language tag for the field" } }, "additionalProperties": false } }, - "issueDate": { + "validFrom": { "type": "string", - "description": "Issue date as a literal ISO 8601 date string or JSON pointer" + "description": "Validity start date as a literal ISO 8601 date string or JSON pointer" }, - "expirationDate": { + "validUntil": { "type": "string", - "description": "Expiration date as a literal ISO 8601 date string or JSON pointer" + "description": "Validity end date as a literal ISO 8601 date string or JSON pointer" } }, "additionalProperties": false @@ -781,7 +791,7 @@

    JSON Template Schema

    -The following example shows a valid `json-card` template with JSON pointer +The following example shows a valid `json-card` template with JSON pointer strings:

    @@ -809,8 +819,8 @@

    JSON Template Schema

    "value": "/validFrom" } ], - "issueDate": "/validFrom", - "expirationDate": "/validUntil" + "validFrom": "/validFrom", + "validUntil": "/validUntil" } @@ -872,28 +882,29 @@

    JSON Card Output Schema

    • label ([=string=]): The field label
    • value ([=string=]): The field value
    • +
    • language ([=string=]): An OPTIONAL language tag (as specified in [[[BCP47]]]) indicating the language of the field
    - issueDate + validFrom [=string=] -An OPTIONAL ISO 8601 date string indicating when the credential was issued. +An OPTIONAL ISO 8601 date string indicating when the credential becomes valid. - expirationDate + validUntil [=string=] -An OPTIONAL ISO 8601 date string indicating when the credential expires. +An OPTIONAL ISO 8601 date string indicating when the credential ceases to be valid.

    -The following example shows a valid `json-card` output: +The following example shows a valid `json-card` output:

    JSON Card Output Schema
           "value": "2010-05-15"
         }
       ],
    -  "issueDate": "2010-01-01T19:23:24Z",
    -  "expirationDate": null
    +  "validFrom": "2010-01-01T19:23:24Z",
    +  "validUntil": null
     }
                 
    @@ -965,7 +976,7 @@

    Template Processing

  • -Validate the resulting JSON object against the `json-card` output schema. If +Validate the resulting JSON object against the `json-card` output schema. If validation fails, processing MUST stop and an error MUST be returned.