API

Preview API

Generate lightweight HTML previews for the report designer with first-page-only rendering.

Endpoint

POST /api/preview

The preview endpoint renders only the first page of a report as HTML. It is optimized for speed and designed for use in live designer tools where fast feedback is essential.

When to use preview

Use the preview endpoint when:

  • Building a live report designer that needs instant visual feedback
  • Rendering thumbnails of report templates
  • Validating layout before committing to a full render

For full multi-page rendering, use the Render API instead.

Request

The request format is the same as the render endpoint, but always returns HTML for the first page only:

{
  "template": {
    "version": "1.0",
    "type": "report",
    "page": { "size": "A4", "orientation": "portrait" },
    "bands": [
      {
        "type": "header",
        "height": 60,
        "components": [
          {
            "type": "text",
            "position": { "x": 0, "y": 20, "width": 300, "height": 30 },
            "content": "{{title}}",
            "fontSize": 20,
            "fontWeight": "bold"
          }
        ]
      },
      {
        "type": "detail",
        "height": 28,
        "dataBinding": "items",
        "components": [
          {
            "type": "text",
            "position": { "x": 0, "y": 4, "width": 200, "height": 20 },
            "content": "{{item.name}}",
            "fontSize": 12
          }
        ]
      }
    ]
  },
  "data": {
    "title": "Preview Report",
    "items": [{ "name": "Item 1" }, { "name": "Item 2" }, { "name": "Item 3" }]
  }
}

Response

The response is always JSON with the first page rendered as HTML:

{
  "output": "<div class=\"report page-1\">...</div>",
  "metadata": {
    "pageCount": 1,
    "totalPages": 3,
    "renderTimeMs": 12,
    "format": "html",
    "preview": true
  }
}

Note the metadata includes totalPages (how many pages the full report would have) and preview: true to distinguish from a full render.

Performance

The preview endpoint is typically 3-5x faster than a full render because it:

  1. Stops band expansion after the first page fills
  2. Skips PDF conversion entirely
  3. Returns minimal HTML without pagination markup

Typical response times:

Report complexityPreviewFull render
Simple (1 page)~5ms~15ms
Medium (5 pages)~8ms~40ms
Large (50 pages)~10ms~200ms

Example with curl

curl -X POST http://localhost:3000/api/preview \
  -H "Content-Type: application/json" \
  -d '{
    "template": {
      "version": "1.0",
      "type": "report",
      "page": { "size": "A4", "orientation": "portrait" },
      "bands": [
        {
          "type": "header",
          "height": 40,
          "components": [
            {
              "type": "text",
              "position": { "x": 0, "y": 10, "width": 200, "height": 20 },
              "content": "Preview Test",
              "fontSize": 16
            }
          ]
        }
      ]
    },
    "data": {}
  }'

Integration with the designer

The preview endpoint pairs naturally with the ReportViewer component. As users edit the schema in a designer UI, debounce changes and call the preview endpoint for real-time visual feedback:

// Debounce schema changes, then preview
const previewReport = debounce(async (schema, data) => {
  const res = await fetch('/api/preview', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ template: schema, data }),
  })
  const { output } = await res.json()
  setPreviewHtml(output)
}, 300)

Next steps