Build a Web Face

Create a custom web-based visual representation for your objects using HTML/CSS/JS.

20 minIntermediate

Prerequisites

  • A DUAL account with a template
  • Basic HTML/CSS/JS knowledge

What You'll Build

Faces are the visual layer of DUAL objects. While image faces are simple, web faces let you create fully interactive displays using HTML, CSS, and JavaScript. In this tutorial you'll build a dynamic loyalty card face that reads object properties in real time.

Step 1 — Understand Face Types

DUAL supports several face display types:

Display TypeDescription
ResourceFaceStatic image (PNG, JPG, SVG)
WebFaceInteractive HTML/JS rendered in a webview
NativeFacePlatform-native UI component
GLTFFace3D model rendered with a GL viewer

We'll be creating a WebFace — the most flexible option.

Step 2 — Create Your HTML

A web face is a standard HTML page that receives object data through the DUAL Bridge API. Here's a minimal loyalty card face:

html
<!DOCTYPE html>
<html>
<head>
  <style>
    body {
      margin: 0; padding: 24px;
      font-family: system-ui, sans-serif;
      background: linear-gradient(135deg, #0f172a, #1e293b);
      color: white; min-height: 100vh;
    }
    .card { max-width: 360px; margin: 0 auto; }
    .points { font-size: 48px; font-weight: bold; color: #15b8a7; }
    .tier { text-transform: uppercase; letter-spacing: 2px; opacity: 0.6; }
    .name { margin-top: 16px; font-size: 18px; }
  </style>
</head>
<body>
  <div class="card">
    <div class="tier" id="tier"></div>
    <div class="points" id="points"></div>
    <div class="name" id="name"></div>
  </div>
  <script src="https://cdn.dual.network/bridge.js"></script>
  <script>
    DualBridge.onLoad(function(object) {
      document.getElementById('tier').textContent = object.properties.tier;
      document.getElementById('points').textContent = object.properties.points + ' pts';
      document.getElementById('name').textContent = object.properties.holder_name;
    });
  </script>
</body>
</html>

Step 3 — Host Your Face

Upload your HTML file to any static hosting provider (Vercel, Netlify, S3, etc.) and note the public URL. The face URL must be accessible over HTTPS.

Step 4 — Register the Face

Attach the web face to your template:

bash
curl -X POST https://gateway-48587430648.europe-west6.run.app/faces \
  -H "Authorization: Bearer $DUAL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "face": {
      "template": "my-org::loyalty-card::v1",
      "display_type": "WebFace",
      "meta": {
        "url": "https://your-cdn.com/loyalty-face.html"
      },
      "is_default": true
    }
  }'

Step 5 — Test in the Viewer

Retrieve an object minted from this template and view it. The face will load your HTML, inject the object's properties, and render the interactive card.

bash
curl https://gateway-48587430648.europe-west6.run.app/objects/{objectId} \
  -H "Authorization: Bearer $DUAL_TOKEN" \
  | jq '.properties.faces'
Bridge API Reference: The DualBridge object provides onLoad(), onStateChange(), and performAction() methods for full two-way communication between your face and the DUAL platform.

What's Next?

To receive notifications when objects change state, try Set Up Webhooks.