> For the complete documentation index, see [llms.txt](https://docs.taptap3d.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.taptap3d.com/integration-guides/data-guide.md).

# Render listing data

Framework-independent server-side rendering example for approved Taptap3D listing data, with safe text and canonical URL handling.

Status: proposed integration. The JSON route is not released. The local mock lets you exercise the renderer without a live API.

## Prerequisites

Use Node.js 22 or later. A live integration needs the issued API/embed origins and an approved publication ID from the [connection playbook](/get-started/connection-playbook.md). This example runs on your server, not in a browser bundle.

## Server-side renderer

Use this framework-independent Node.js function for a storefront that wants its own presentation. It escapes text and verifies the canonical origin before emitting HTML. It does not render images, generate offer data or connect checkout.

```js
// Framework-independent, server-side renderer for the proposed contract.
const escape = value => String(value).replace(/[&<>"']/g, char => ({
  '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;'
})[char]);

export async function renderListing({ apiOrigin, embedOrigin, publicationId }) {
  const api = new URL(apiOrigin);
  const embed = new URL(embedOrigin);
  for (const origin of [api, embed]) {
    const loopback = origin.protocol === 'http:' && origin.hostname === '127.0.0.1';
    if ((origin.protocol !== 'https:' && !loopback) || origin.username || origin.password ||
        origin.pathname !== '/' || origin.search || origin.hash) throw new Error('Use an approved HTTPS origin.');
  }
  const endpoint = new URL(`/v1/publications/${encodeURIComponent(publicationId)}`, api);
  const response = await fetch(endpoint, {
    headers: { Accept: 'application/json' }, cache: 'no-store', signal: AbortSignal.timeout(5000)
  });
  if (!response.ok) throw new Error(`Publication unavailable: HTTP ${response.status}`);
  const listing = await response.json();
  if (listing.schemaVersion !== '1' || listing.publicationId !== publicationId ||
      typeof listing.title !== 'string' || typeof listing.description !== 'string' ||
      typeof listing.revision !== 'string' || !listing.revision ||
      !['en', 'zh-Hant'].includes(listing.language) || typeof listing.canonicalUrl !== 'string') {
    throw new Error('Unexpected listing response.');
  }
  const canonical = new URL(listing.canonicalUrl);
  if (canonical.origin !== embed.origin || canonical.username || canonical.password) {
    throw new Error('Untrusted canonical URL.');
  }
  return `<article lang="${escape(listing.language)}">
  <h1>${escape(listing.title)}</h1>
  <p>${escape(listing.description)}</p>
  <a href="${escape(canonical.href)}">Open the listing</a>
</article>`;
}
```

Call it from your server route or build pipeline:

```js
import { renderListing } from './render-listing.mjs';

try {
  const html = await renderListing({
    apiOrigin: process.env.TAPTAP3D_API_ORIGIN,
    embedOrigin: process.env.TAPTAP3D_EMBED_ORIGIN,
    publicationId: 'pub_demo_vessel'
  });
  // Send html through your storefront's server-rendered page response.
  // Preserve the storefront's normal security headers.
  console.log(html);
} catch {
  // Replace previously rendered listing content; do not serve a stale offer.
  console.log('<p>Item details are unavailable. Please contact the seller.</p>');
}
```

Keep the origins in server configuration. The function permits HTTP only for `127.0.0.1` to run the local mock; live integrations require HTTPS. Server-side requests do not require browser CORS. A browser implementation needs explicit origin registration and must use DOM text rendering instead of inserting untrusted HTML.

Do not turn this into a build-time snapshot without a withdrawal refresh strategy. For the proposed initial contract, render on request and disable listing-response caches. The iframe message protocol does not notify a separately rendered JSON page of changes.

## Check the result

A successful response produces an article containing the approved title, description and canonical link. Text is escaped and a canonical URL from an unexpected origin is rejected. Non-success HTTP responses produce an unavailable state in the caller.

Validate against the [listing contract](/proposed-reference/listing-contract.md). For HTTP errors, see [Troubleshooting](/testing-and-support/troubleshooting.md). Complete the [release acceptance checks](/testing-and-support/acceptance.md) before publishing live content.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.taptap3d.com/integration-guides/data-guide.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `build a script that syncs our docs to a CMS` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
