Getting started with the React UI
This guide walks you through integrating the ARender viewer into your own application — step by step, from setting up registry access to displaying your first document in the browser.
The ARender viewer is distributed as the arender-ui npm package. It registers an <arender-element> Web Component that integrates into any framework — React, Angular, Vue, Svelte, or plain HTML. The viewer communicates with the ARender rendition backend over REST.
Don't have a project yet? You can create a fresh React application to follow along:
npm create vite@latest my-app -- --template react-ts
cd my-app
Then continue with the steps below.
Prerequisites
- Access to the ARender npm registry on Cloudsmith (credentials provided by Uxopian)
- Node.js 20+ and a package manager (npm or yarn)
Step 1 — Configure access to the ARender registry
ARender packages are hosted on a private Cloudsmith registry. Create a .npmrc file at the root of your project with your token:
//npm.cloudsmith.io/uxopian/release/:_authToken=your_token_here
Replace your_token_here with the token provided by Uxopian.
Then add .npmrc to your .gitignore to avoid committing the token:
.npmrc
Step 2 — Install the ARender package
Open a terminal at the root of your project and install the arender-ui package:
npm install arender-ui --registry https://npm.cloudsmith.io/uxopian/release/
Step 3 — Configure the dev server proxy
The viewer needs to reach the rendition backend. In development, your dev server's built-in proxy handles this — no external reverse proxy needed.
Uxopian provides a shared demo rendition backend at https://rendition.arender.2026.uxopian.com — available to all, no credentials or installation required. This lets you test the viewer right away. Deploying your own backend is covered in the Installation section.
- Vite (React / Vue / Svelte)
- Angular
Add the following proxy configuration to vite.config.ts:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
server: {
proxy: {
'/documents': {
target: 'https://rendition.arender.2026.uxopian.com',
changeOrigin: true,
},
'/registry/documents': {
target: 'https://rendition.arender.2026.uxopian.com',
changeOrigin: true,
},
'/annotation': {
target: 'https://rendition.arender.2026.uxopian.com',
changeOrigin: true,
},
},
},
})
Create a proxy.conf.json file at the root of your project:
{
"/documents": { "target": "https://rendition.arender.2026.uxopian.com", "changeOrigin": true },
"/registry/documents": { "target": "https://rendition.arender.2026.uxopian.com", "changeOrigin": true },
"/annotation": { "target": "https://rendition.arender.2026.uxopian.com", "changeOrigin": true }
}
Then reference it in angular.json under serve.options:
"serve": {
"options": {
"proxyConfig": "proxy.conf.json"
},
...
}
Restart ng serve — the proxy is active immediately.
To connect to your own backend instead of the demo, change each target to your backend URL (e.g. http://localhost:8761 for Docker Compose). In production, replace the dev proxy with a reverse proxy (Nginx, Ingress) or a BFF. See Docker Compose for deployment guides.
For other frameworks (Next.js, Nuxt, CRA, webpack…), configure your dev server proxy to forward /documents, /registry/documents, and /annotation to the rendition backend. Refer to your framework's documentation.
Step 4 — Embed the viewer
The <arender-element> is a Web Component — a standard HTML element you can drop into any template or JSX just like a <video> or <input>. It encapsulates the entire ARender viewer: no JavaScript instantiation required to display it. You configure it through HTML attributes.
Web Component attributes
The table below lists the attributes you can set directly on the element:
| Attribute | Required | Description |
|---|---|---|
rendition | Yes | URL of the ARender rendition backend. Use / when proxied with Vite, or http://localhost:4200/ with Angular (see Step 3). |
url | No | URL of the document to open on startup. |
uuid | No | ID of the document to open on startup (alternative to url). |
Set url or uuid directly as HTML attributes to open a document on startup — no JavaScript needed.
To load a different document at runtime, use the JavaScript API.
- React
- Vue
- Svelte
- Angular
- HTML
Copy the following into your src/App.tsx file, replacing its entire contents:
import { useEffect } from 'react'
import type { ARenderHTMLElement } from 'arender-ui'
// Move these declarations to a global.d.ts in a real project
declare module 'react' {
namespace JSX {
interface IntrinsicElements {
'arender-element': React.HTMLAttributes<HTMLElement> & {
rendition?: string
url?: string
uuid?: string
}
}
}
}
declare global {
interface Window { ARender: ARenderHTMLElement }
}
function App() {
useEffect(() => { import('arender-ui') }, [])
return (
<div style={{ width: '100%', height: '100vh' }}>
<arender-element
rendition="/"
url="https://www.uxopian.com/hubfs/PDFReference15_v5.pdf"
/>
</div>
)
}
export default App
Copy the following into your src/App.vue file, replacing its entire contents:
<script setup lang="ts">
import { onMounted } from 'vue'
onMounted(() => { import('arender-ui') })
</script>
<template>
<div style="width: 100%; height: 100vh">
<arender-element
rendition="/"
url="https://www.uxopian.com/hubfs/PDFReference15_v5.pdf"
/>
</div>
</template>
To suppress the Vue compiler warning for unknown elements, add isCustomElement to your Vite config:
vue({ template: { compilerOptions: { isCustomElement: (tag) => tag === 'arender-element' } } })
Copy the following into your src/App.svelte file, replacing its entire contents:
<script lang="ts">
import { onMount } from 'svelte'
onMount(() => { import('arender-ui') })
</script>
<div style="width: 100%; height: 100vh">
<arender-element
rendition="/"
url="https://www.uxopian.com/hubfs/PDFReference15_v5.pdf"
></arender-element>
</div>
Copy the following into your src/app/app.component.ts file, replacing its entire contents:
import { Component, AfterViewInit, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
@Component({
selector: 'app-root',
standalone: true,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<arender-element
rendition="http://localhost:4200/"
url="https://www.uxopian.com/hubfs/PDFReference15_v5.pdf"
style="display: block; width: 100%; height: 100vh"
></arender-element>
`,
})
export class AppComponent implements AfterViewInit {
ngAfterViewInit() {
import('arender-ui')
}
}
Angular requires an absolute URL for rendition — a relative / is not resolved correctly by the dev server. In production, replace http://localhost:4200/ with your actual backend URL.
Add the following to your index.html file, just before the closing </body> tag:
<arender-element
rendition="/"
url="https://www.uxopian.com/hubfs/PDFReference15_v5.pdf"
style="display: block; width: 100%; height: 100vh"
></arender-element>
<script type="module">
import('arender-ui')
</script>
The examples below use a dynamic import() inside a lifecycle hook (useEffect, onMounted, etc.) rather than a static import at the top of the file. This is intentional for SSR compatibility: arender-ui registers a Web Component using browser APIs (window, document, customElements) that do not exist in Node.js. A static import would crash the build in SSR frameworks like Next.js, Nuxt, or SvelteKit.
If your application is purely client-side (no SSR), a static import at the top of the file works just as well:
import 'arender-ui'
Step 5 — Start the dev server
With the viewer embedded, start your development server and open it in your browser.
If you created a fresh Vite project (as shown in the introduction), run:
npm run dev
Vite will print a local URL — usually http://localhost:5173. Open it in your browser and you should see the ARender viewer loading the sample PDF.
If you use a different package manager, the equivalent command is:
| Package manager | Command |
|---|---|
| yarn | yarn dev |
| pnpm | pnpm dev |
| bun | bun dev |
For other frameworks, use your usual start command (e.g. npm start for CRA).
If the viewer loads but no document appears, double-check the proxy configuration in Step 3 — the /documents, /registry/documents, and /annotation paths must all be proxied to the rendition backend.
Step 6 — Load a document dynamically
To change the displayed document at runtime, use window.ARender. Calls made before the viewer finishes mounting are queued automatically — no need to wait for any event.
- React
- Vue
- Svelte
- Angular
- HTML
Replace your src/App.tsx with the following complete file:
import { useEffect } from 'react'
import type { ARenderHTMLElement } from 'arender-ui'
declare module 'react' {
namespace JSX {
interface IntrinsicElements {
'arender-element': React.HTMLAttributes<HTMLElement> & {
rendition?: string
url?: string
uuid?: string
}
}
}
}
declare global {
interface Window { ARender: ARenderHTMLElement }
}
function App() {
useEffect(() => { import('arender-ui') }, [])
return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100vh' }}>
<div>
<button onClick={() => window.ARender.openDocumentByUrl('https://www.uxopian.com/hubfs/ARender-Mail_viewer_use_case.msg')}>
Change document
</button>
</div>
<arender-element
rendition="/"
url="https://www.uxopian.com/hubfs/PDFReference15_v5.pdf"
style={{ flex: 1 }}
/>
</div>
)
}
export default App
Replace your src/App.vue with the following complete file:
<script setup lang="ts">
import { onMounted } from 'vue'
onMounted(() => { import('arender-ui') })
function changeDocument() {
window.ARender.openDocumentByUrl('https://www.uxopian.com/hubfs/ARender-Mail_viewer_use_case.msg')
}
</script>
<template>
<div style="display: flex; flex-direction: column; height: 100vh">
<div>
<button @click="changeDocument">Change document</button>
</div>
<arender-element
rendition="/"
url="https://www.uxopian.com/hubfs/PDFReference15_v5.pdf"
style="flex: 1"
/>
</div>
</template>
Replace your src/App.svelte with the following complete file:
<script lang="ts">
import { onMount } from 'svelte'
onMount(() => { import('arender-ui') })
function changeDocument() {
window.ARender.openDocumentByUrl('https://www.uxopian.com/hubfs/ARender-Mail_viewer_use_case.msg')
}
</script>
<div style="display: flex; flex-direction: column; height: 100vh">
<div>
<button on:click={changeDocument}>Change document</button>
</div>
<arender-element
rendition="/"
url="https://www.uxopian.com/hubfs/PDFReference15_v5.pdf"
style="flex: 1; display: block"
></arender-element>
</div>
Replace your src/app/app.component.ts with the following complete file:
import { Component, AfterViewInit, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
@Component({
selector: 'app-root',
standalone: true,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<div style="display: flex; flex-direction: column; height: 100vh">
<div>
<button (click)="changeDocument()">Change document</button>
</div>
<arender-element
rendition="http://localhost:4200/"
url="https://www.uxopian.com/hubfs/PDFReference15_v5.pdf"
style="display: block; flex: 1"
></arender-element>
</div>
`,
})
export class AppComponent implements AfterViewInit {
ngAfterViewInit() {
import('arender-ui')
}
changeDocument() {
window.ARender.openDocumentByUrl('https://www.uxopian.com/hubfs/ARender-Mail_viewer_use_case.msg')
}
}
Add the following to your index.html, just before the closing </body> tag:
<div style="display: flex; flex-direction: column; height: 100vh">
<div>
<button id="change-btn">Change document</button>
</div>
<arender-element
rendition="/"
url="https://www.uxopian.com/hubfs/PDFReference15_v5.pdf"
style="display: block; flex: 1"
></arender-element>
</div>
<script type="module">
import('arender-ui')
document.getElementById('change-btn').addEventListener('click', () => {
window.ARender.openDocumentByUrl('https://www.uxopian.com/hubfs/ARender-Mail_viewer_use_case.msg')
})
</script>
Sample documents
These public URLs can be used for testing (the demo rendition already authorizes https://www.uxopian.com/):
- PDF:
https://www.uxopian.com/hubfs/PDFReference15_v5.pdf - Image:
https://www.uxopian.com/hubfs/example_image_comparison_unmodified.jpg - Email:
https://www.uxopian.com/hubfs/ARender-Mail_viewer_use_case.msg
Next steps
- Docker Compose — deploy the rendition backend on your own infrastructure
- Configuration — reverse proxy, authentication, and BFF
- Feature availability — what's available now and what's coming
- Web Component — HTML attributes, JavaScript API, styling
- Providers — load documents from Alfresco, FileNet, or custom repositories