---
title: "Renderer port"
description: "The Renderer, RenderTargetInfo and RenderInput types, the render routes and events, and the createRenderer and markdownTarget adapter."
canonical_url: "https://skaile-ai.github.io/forge-editor/reference/renderer-port"
---
# Renderer port

> The Renderer, RenderTargetInfo and RenderInput types, the render routes and events, and the createRenderer and markdownTarget adapter.

The server types come from `packages/editor/src/server/ports.ts` (`@skaile/forge-editor/server`), the wire types from `packages/editor/src/core/backend-types.ts` (`@skaile/forge-editor/core`), the adapter from `@skaile/forge-editor/adapters/render`. For how to add a target and what the editor shows, see [Render](https://skaile-ai.github.io/forge-editor/guides/render).

## `Renderer`

`EditorPorts.render` (capability `render`). The result is stored through `EditorPorts.assets`; without it `POST /api/editor/render` answers `501`.

<table>
<thead>
  <tr>
    <th>
      Member
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Meaning
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        targets
      </code>
    </td>
    
    <td>
      <code>
        (user: object) => Promise<RenderTargetInfo[]>
      </code>
    </td>
    
    <td>
      The targets this user may use.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        render
      </code>
    </td>
    
    <td>
      <code>
        (target, input, user, progress, signal) => Promise<{ data: Uint8Array, mime: string, fileName: string }>
      </code>
    </td>
    
    <td>
      Renders <code>
        input
      </code>
      
       to <code>
        target
      </code>
      
      . <code>
        progress
      </code>
      
       is a <code>
        RenderProgressReporter
      </code>
      
       (<code>
        (p: RenderProgress) => void
      </code>
      
      ); <code>
        signal
      </code>
      
       aborts when the client goes away. Throw to fail the render: the message reaches the client.
    </td>
  </tr>
</tbody>
</table>

## `RenderTargetInfo`

<table>
<thead>
  <tr>
    <th>
      Field
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Meaning
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        id
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Unique among the targets of one renderer.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        label
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Already in the user's language.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        accepts
      </code>
    </td>
    
    <td>
      <code>
        readonly string[]
      </code>
    </td>
    
    <td>
      Block type ids, or <code>
        'document'
      </code>
      
       for a whole Document.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        mime
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      MIME type of the result.
    </td>
  </tr>
</tbody>
</table>

## `RenderInput`

<table>
<thead>
  <tr>
    <th>
      Field
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Meaning
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        documentId
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      The Document the result is stored under.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        blockId
      </code>
    </td>
    
    <td>
      <code>
        string?
      </code>
    </td>
    
    <td>
      Set for a Block; absent for the whole Document.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        content
      </code>
    </td>
    
    <td>
      <code>
        JSONContent
      </code>
    </td>
    
    <td>
      The Block's TipTap JSON, or the whole Document without <code>
        blockId
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        options
      </code>
    </td>
    
    <td>
      <code>
        Record<string, unknown>?
      </code>
    </td>
    
    <td>
      Target specific options.
    </td>
  </tr>
</tbody>
</table>

## Routes

<table>
<thead>
  <tr>
    <th>
      Route (<code>
        API
      </code>
      
       key)
    </th>
    
    <th>
      Request
    </th>
    
    <th>
      Answer
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        GET /api/editor/render/targets
      </code>
      
       (<code>
        renderTargets
      </code>
      
      )
    </td>
    
    <td>
      none
    </td>
    
    <td>
      <code>
        RenderTargetInfo[]
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        POST /api/editor/render
      </code>
      
       (<code>
        renderPost
      </code>
      
      )
    </td>
    
    <td>
      <code>
        { target: string, input: RenderInput }
      </code>
    </td>
    
    <td>
      SSE: <code>
        progress
      </code>
      
       <code>
        { phase: string, percent?: number }
      </code>
      
      , then <code>
        done
      </code>
      
       <code>
        { asset: string, fileName: string, mime: string }
      </code>
      
       or <code>
        error
      </code>
      
       <code>
        { message: string }
      </code>
    </td>
  </tr>
</tbody>
</table>

Both routes are served only when `ports.render` is present. Refusals before the stream starts: `400`, `401`, `403`, `404` (unknown target), `422` (the target does not accept the Block type), `501` (no `assets` port).

## `EditorBackend['render']`

<table>
<thead>
  <tr>
    <th>
      Member
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Meaning
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        targets
      </code>
    </td>
    
    <td>
      <code>
        (signal?) => Promise<RenderTargetInfo[]>
      </code>
    </td>
    
    <td>
      The targets of the user.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        render
      </code>
    </td>
    
    <td>
      <code>
        (target, input, { onProgress?, signal? }?) => Promise<RenderResult>
      </code>
    </td>
    
    <td>
      Streams one render. <code>
        RenderResult
      </code>
      
       is <code>
        RenderDone
      </code>
      
       (<code>
        asset
      </code>
      
      , <code>
        fileName
      </code>
      
      , <code>
        mime
      </code>
      
      ) plus <code>
        url
      </code>
      
       of the stored asset. Rejects with the server's message when the render fails.
    </td>
  </tr>
</tbody>
</table>

## `@skaile/forge-editor/adapters/render`

<table>
<thead>
  <tr>
    <th>
      Export
    </th>
    
    <th>
      Meaning
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        createRenderer(targets)
      </code>
    </td>
    
    <td>
      A <code>
        Renderer
      </code>
      
       over a list of <code>
        RenderTarget
      </code>
      
      s. A repeated <code>
        id
      </code>
      
       keeps the first; <code>
        render
      </code>
      
       rejects with <code>
        404
      </code>
      
       for an unknown id.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        RenderTarget
      </code>
    </td>
    
    <td>
      <code>
        RenderTargetInfo
      </code>
      
       plus <code>
        run(input, progress, signal)
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        markdownTarget(options?)
      </code>
    </td>
    
    <td>
      The built-in target <code>
        markdown
      </code>
      
       (<code>
        text/markdown
      </code>
      
      ); options <code>
        schema
      </code>
      
      , <code>
        blockTypes
      </code>
      
      , <code>
        label
      </code>
      
      .
    </td>
  </tr>
</tbody>
</table>


## Sitemap

See the full [sitemap](https://skaile-ai.github.io/forge-editor/sitemap.md) for all pages.
