Embedding
Studio Web Component
Embed the Carbone Studio in your application
Overview
From Carbone v5, the studio or "Designer Assistant" is an HTML-native Web component which can be integrated into any web application π.
From the user's perspective:
- Enjoy a seamless experience by editing reports directly within your application.
- Automatically open the studio with user data as a sample.
From the software editor's perspective:
- Leverage your own access rights management to control which templates users can view, list, or edit.
- Make all reports in your app customizable.
- Increase revenue potential by upselling access to this feature or offering personalized reports.
From the developer's perspective:
- The studio is a customizable, lightweight HTML5 web component compatible with all front-end frameworks like Vue.js, React.js, Angular, and Riot.
- The studio is simple to integrate.
Quickstart
Want to try Carbone Studio instantly? π
See the quick example to get started in 2 minutes (no license needed)!
Or, follow these 3 minimal steps below to embed Carbone Studio in your application and explore all available options.
Embed in your app
Add the Carbone Studio web component to your application.Start and configure
Instantiate the component and set your configuration.
Ideally, decide which embedded mode you want to use before integrating the studio.Open an existing template
Load an existing template into the studio for editing.
API Reference
Quick overview of all functions available in the studio
| Function | Description |
|---|---|
| setConfig() | Configure studio mode, theme, ... |
| setRenderOptions() | Set the render/sample data and (optionally) trigger preview refresh. |
| getRenderOptions() | Get the current render/sample options for the studio. |
| openTemplateId() | Open a template by its 64-bit template ID and automatically load all versions. |
| openTemplateVersionId() | Open a template by version ID (SHA-256 hash). In embedded-versioning mode, this will generate a unique 64-bit template ID. |
| openTemplateURL() | Open a template from an external URL, optionally providing a sample data URL. |
| openTemplateDataURI() | Open a template from a base64 Data URI (e.g. output of FileReader). |
| openTemplate() | Deprecated: Open a template by providing a minimal template object. For compatibility only. |
| reset() | Reset the studio state, clearing opened template, options, and preview. |
Quick overview of all listenable events available in the studio
| Event | Description |
|---|---|
| connected | Fired when the component is added to the page |
| disconnected | Fired when the component is removed from the page |
| options:updated | Fired when preview options change |
| template:updated | Fired when the template file changes |
| template:saved | Fired when clicking the "save" button |
| template:deployed | Fired when clicking the "deploy" button |
Embed in your app
To get started, you need to include the Carbone Studio web component in your application. There are two primary ways to do this:
Use our public CDN: Replace
latestwith a valid Carbone release (for example,5.1.1):https://bin.carbone.io/studio/latest/carbone-studio.min.jsUse your local Carbone On-Premise instance: Start your Carbone instance with the
-soption to enable the studio. Once itβs running, download the script at:http://localhost:4000/carbone-studio.js
Include the JavaScript file in your HTML and add basic CSS styling to ensure the studio fills its container.
<script src="PATH-TO/carbone-studio.js"></script>
<style>
carbone-studio {
width: 100%;
height: 100%;
}
</style>
Start and configure
Once you have included the studio component in your script, you can easily add it to the DOM.
// Instantiate the Web component
const studio = document.createElement('carbone-studio');
// [Optional] Disable the studio when appending it to the DOM (silent initialization).
// The studio will be activated with the correct mode after calling setConfig() below.
studio.setAttribute('carbone-mode', 'off');
window.addEventListener('DOMContentLoaded', function() {
// Add the studio component to the DOM
// or insert `<carbone-studio></carbone-studio>` directly into the DOM.
document.body.appendChild(studio);
// This method can be called multiple times, updating only the attributes you wish to change each time.
studio.setConfig({
// Mode options:
// - 'off' : Can be used to delay initialization and prevent flickering
// - 'embedded' (default) : Only designer page, no version management.
// - 'embedded-versioning' : Only designer page, with template version management.
mode : 'embedded',
// [Optional] Overwrite theme (see Theme and Appearance paragraph)
theme : 'main { --primary: #1348b3; }',
// [Optional] Origin of all requests. Defaults to `window.location.origin`
// Accepts URLs with or without a trailing slash
origin : 'https://api.carbone.io/',
// [Optional] Add authorization HTTP header "Bearer <token>"
token : '',
// [Optional] Add carbone-version HTTP header
version : '5',
// [Optional] Update the list of available Carbone version in preview window
enabledVersions : ['5', '4', '3', 'staging']
// [Optional] If any API endpoint returns HTTP STATUS 401 (Unauthorized), the studio can redirects to this URL
loginRedirectUrl : 'https://login.to',
// [Optional] Override all studio requests to add your custom logic or proxy the request through your app
fetchOverride : (url, options) => {
// original browser fetch function
return fetch(url, options);
}
});
Alternatively, three common attributes can be set directly in the DOM when declaring the component:
carbone-mode: set the operation mode (off,embedded, orembedded-versioning)carbone-theme: customize the theme with CSS overridescarbone-login-redirect-url: specify a redirect URL for 401 (Unauthorized) responses
Example:
<carbone-studio
carbone-mode="embedded-versioning"
carbone-theme="main { --primary: #1348b3; }"
carbone-login-redirect-url="https://login.to">
</carbone-studio>
Open a Template
The Carbone Studio Web Component supports five different ways to open a template, offering flexibility to match your workflow, backend, or storage method.
For quick testing, you can easily open a sample template and data from our website as shown below:
studio.openTemplateURL(
'https://carbone.io/examples/awards-simple/template.docx',
'https://carbone.io/examples/awards-simple/data.json'
);
openTemplateId()
/**
* Open a template and all its versions by its constant 64 bit ID.
*
* Only available in 'embedded-versioning' mode with Carbone backend in stateful mode.
*
* - Automatically gets all versions via GET /templates?id={id}&includeVersions=true,
* including all template fields (name, type, createdAt, size, comment, tags, origin, ...).
* - Automatically finds the deployed template and the previous deployed template.
* - Gets sample data automatically from GET /template/{versionId}_sample.json
* - Automatically updates sample data in the studio.
* - Sorts versions by createdAt descending and sets the most recent one as the active template.
*
* @param {String} id 64 bit ID of the template
*/
function openTemplateId(id)
openTemplateVersionId()
/**
* Open a template using its versionId and type (low-level method).
*
* Behavior depends on studio mode:
* - In "embedded" mode, only `comment` and `createdAt` in `defaultTemplateAttributes`
* are visible in the template panel UI.
* - In "embedded-versioning" mode, the system automatically:
* - Generates and assigns a new "id" (unique 64-bit ID: timestamp + random number)
* to start template version management,
* - Sets "deployedAt" (Unix timestamp) to the current date,
* - Immediately updates the template to store the new "id" and "deployedAt"
* (with PATCH /template/{versionId}).
*
* @param {String} versionId Template versionId
* @param {String} type Template type (docx, xlsx, odt, ods, etc.), used
* by the UI for type and conversion options
* @param {Object} [defaultTemplateAttributes] Optional default template attributes
* {
* name : String,
* comment : String, Visible in UI ('Template file' by default)
* createdAt : Number (Unix timestamp), Visible in UI (default: now)
* tags : Array of strings,
* category : String,
* origin : Number (0: API, 1: studio)
* }
*/
function openTemplateVersionId(versionId, type = '', defaultTemplateAttributes = { comment: 'Template file' })
openTemplateURL()
/**
* Open a template from a template URL and a sample data URL.
*
* Useful for opening examples from the Carbone.io website or from any other source.
*
* @param {String} templateURL External template URL
* @param {String} [sampleDataURL] Optional sample data URL (ignored if null).
* Must be a JSON file with this structure
* [{
* data: object|array,
* complement: object|array,
* enum: object,
* translations: object
* }]
* @param {Object} [defaultTemplateAttributes] Optional default template attributes
* {
* name : String,
* comment : String, Visible in UI ('Template file' by default)
* createdAt : Number (Unix timestamp), Visible in UI (default: now)
* tags : Array of strings,
* category : String,
* origin : Number (0: API, 1: studio)
* }
*/
function openTemplateURL(templateURL, sampleDataURL, defaultTemplateAttributes = { comment: 'Template file' })
openTemplateDataURI()
/**
* Open a template from a Data URI string (e.g., from `FileReader.readAsDataURL()`).
*
* @param {String} templateDataURI Template Data URI (example: "data:application/xml;base64,...")
* Can be generated using FileReader.readAsDataURL().
* @param {Object} [defaultTemplateAttributes] Optional default template attributes
* {
* name : String,
* comment : String, Visible in UI ('Template file' by default)
* createdAt : Number (Unix timestamp), Visible in UI (default: now)
* tags : Array of strings,
* category : String,
* origin : Number (0: API, 1: studio)
* }
*/
function openTemplateDataURI(templateDataURI, defaultTemplateAttributes = { comment: 'Template file' })
openTemplate()
Deprecated, replaced by openTemplateVersionId() or openTemplateId() for new projects
/**
* Open a template from a template object (LEGACY WAY).
*
* Only available in `"embedded"` mode.
*
* @param {Object} templateObj Minimal template object with versionId and type:
* {
* templateId : Template versionId (SHA-256 hash)
* extension : String (docx, xlsx, etc.)
* comment : String (template comment), Visible in UI ('Template file' by default)
* }
* @param {Object} options Render options
*/
function openTemplate(templateObj, options)
Manage State and Data
Update all the state of the studio, including all data panels, language, timezone, and related options.
setRenderOptions()
All attributes match with the objects sent to the generation API. See the POST /render API documentation for more details on each attribute.
/**
* Set the render options.
*
* @param {Object} options The render options, including:
* {
* data : Object or Array,
* complement : Object or Array,
* enum : Object,
* translations : Object,
* converter : String ('L', 'O', or 'C'),
* lang : String (BCP 47 code, e.g. "en-US"), defaults to the user's browser language,
* timezone : String (e.g., "Europe/Paris"), defaults to the user's browser timezone,
* reportName : String (e.g., "Invoice"),
* currencySource : String (e.g., "EUR"), defaults to EUR,
* currencyTarget : String (e.g., "EUR")
* }
* @param {boolean} forceRefreshPreview [optional] If true, forces the preview to refresh immediately.
* If false, shows the refresh button in the preview panel.
* Default is false.
*/
function setRenderOptions(options, forceRefreshPreview = false)
getRenderOptions()
Returns the current render options (same object as provided to setRenderOptions).
/**
* Get the current render options.
*
* @return {Object} The current render options.
*/
function getRenderOptions()
reset()
Reset the entire Studio, clearing all opened templates, state, and options
/**
* Reset the studio.
*
* - Stop watching the file
* - Reset the template
* - Reset the render options
* - Reset the render result
*/
function reset()
Listen Events
Your application can listen to multiple events emitted by the studio component.
connected
Triggered when the component is added to the page.
studio.addEventListener('connected', () => {});
disconnected
Triggered when the component is removed from the page.
studio.addEventListener('disconnected', () => {});
options:updated
Triggered when preview/sample options are updated. The event's detail contains only the modified data.
studio.addEventListener('options:updated', (e) => {
console.log(e.detail);
// {
// data : Object|Array,
// complement : Object|Array,
// enum : Object,
// translations : Object,
// lang : String,
// timezone : String,
// converter : String,
// currencySource : String,
// }
});
template:updated
Triggered each time the template is modified by the user.
studio.addEventListener('template:updated', (e) => {
console.log(e.detail);
// {
// createdAt : 1767108187 (timestamp unix)
// type : "html",
// dataURI : "data:text/html;base64,PCFET0NU..."
// }
});
template:saved
This event is triggered when the user clicks the "Save" button.
The detail property contains a direct reference to the internal template object.
Make sure to clone this object before modifying it, as changes will affect the original!
For descriptions of each property, see the template API documentation.
There may be additional undocumented fields starting with "_". These are internal and might change or be removed in future versions.
studio.addEventListener('template:saved', (e) => {
console.log(e.detail);
// {
// versionId : "a53593973e6ec37c2b79fb9128cc602c830afbb44de4bd0db719b0b71e34fc77",
// id : "1317319105326582256",
// createdAt : 1767109431,
// expireAt : 0,
// deployedAt : -1,
// size : 66,
// type : "html",
// name : "",
// comment : "",
// tags : [],
// origin : 1,
// sample : [
// {
// "data": {},
// "complement": {},
// "enum": {},
// "translations": {}
// }
// ]
// }
});
template:deployed
This event is triggered when the user clicks the "Deploy" button.
The detail property contains a direct reference to the internal template object.
Make sure to clone this object before modifying it, as changes will affect the original!
For descriptions of each property, see the template API documentation.
There may be additional undocumented fields starting with "_". These are internal and might change or be removed in future versions.
studio.addEventListener('template:deployed', (e) => {
console.log('template:deployed', e.detail);
// {
// versionId : "a53593973e6ec37c2b79fb9128cc602c830afbb44de4bd0db719b0b71e34fc77",
// id : "1317319105326582256",
// createdAt : 1767109431,
// expireAt : 0,
// deployedAt : -1,
// size : 66,
// type : "html",
// name : "",
// comment : "",
// tags : [],
// origin : 1,
// sample : [
// {
// "data": {},
// "complement": {},
// "enum": {},
// "translations": {}
// }
// ]
// }
});
Theme and Appearance
Customize the look and feel of the Carbone Studio Web Component by overriding its default CSS variables.
Option 1: Set Directly via JavaScript
// using JavaScript allows you to update the CSS after initialization
// via setConfig
studio.setConfig({ theme: 'main { --primary: #1348b3; }' });
// or via HTML attribute
studio.setAttribute('carbone-theme', 'main { --primary: #1348b3; }');
Option 2: Set in HTML
Assign your custom CSS variables directly in the HTML definition:
<carbone-studio carbone-theme="main { --primary: #1348b3; }"></carbone-studio>
Available CSS Variables
Below is a reference of all the main CSS variables you can override to change the Studio's colors. These variables are based on Material Design principles BeerCSS and cover every part of the studio:
/* https://github.com/beercss/beercss/blob/main/docs/SETTINGS.md */
/* Primary UI colors */
--primary: #a544c5;
--on-primary: #ffffff;
--primary-container: #eecafc;
--on-primary-container: #350040;
--secondary: #6b586b;
--on-secondary: #ffffff;
--secondary-container: #cac5ca;
--on-secondary-container: #251626;
--tertiary: #9e9e9e;
--on-tertiary: #ffffff;
--tertiary-container: #ffdad2;
--on-tertiary-container: #32110c;
/* Error & background colors */
--error: #ba1b1b;
--error-container: #ffdad4;
--on-error: #ffffff;
--on-error-container: #410001;
--background: #fcfcfc;
--on-background: #1e1a1d;
/* Surface colors */
--surface: #f5f5f5;
--on-surface: #1e1a1d;
--surface-variant: #e8e5e9;
--on-surface-variant: #1e1a1d;
--outline: #a7a7a7;
--inverse-surface: #323639;
--inverse-on-surface: #f7eef3;
--inverse-primary: #fbaaff;
--inverse-on-primary: #371E73;
--outline-variant: var(--outline);
--surface-dim: #f4f4f4;
--surface-bright: #fdf8fd;
--surface-container-lowest: #ffffff;
--surface-container-low: #f7f2f7;
--surface-container: #fff;
--surface-container-high: #ece7eb;
--surface-container-highest: #e6e1e6;
/* Interactive states */
--active: rgba(0,0,0,.1);
--overlay: rgba(0,0,0,.5);
/* Studio-specific: Tabs */
--tab-preview-border-color: #999;
--tab-border-color: #c0aabf;
--tab-text-color: #999;
/* Studio-specific: JSON Editor */
--json-editor-active-line: rgb(235 204 255 / 27%);
--json-editor-active-bracket: rgb(193 96 255 / 27%);
--json-editor-search-match-selected: rgb(237 178 255 / 51%);
--json-editor-search-match: rgb(255 211 0 / 35%);
Authentication
The Studio Web Component is user-agnostic. Authentication and tenant separation depend on your architecture.
With a On-Premise backend
The recommended way to handle authentication with the Studio Web Component is to route all Carbone requests through your own backend.
This approach is simple and secure:
- No backend tokens are exposed to the browser.
- No CORS (cross-origin) issues.
- Your appβs authentication and rights management are reused.
- You can log all requests.
The Studio Web Component running in the browser will send requests to your own domain (e.g., your-domain.com).
Your backend (or load balancer/reverse proxy) then forwards (proxies) these requests to the Carbone backend, so your application stays in full control of authentication and authorization.
The list of endpoints to proxy is detailed in the Embedded Mode section.
All fetch requests made by the component can be overridden using the fetchOverride option in the setConfig API.
ββββββββββββββββββββββββ
β User's Browser β
ββββββββββββββββββββββββ
β
(Carbone Studio web component
makes AJAX/fetch requests)
β
βΌ
ββββββββββββββββββββββββββββββββ
β your-domain.com β
β (Your load balancer and β β β βββ
β reverse proxy) β β
ββββββββββββββββββββββββββββββββ β
β β
β (direct proxy to
β Carbone)
β β
βΌ βΌ
βββββββββββββββββββββ (or indirect βββββββββββββββββ
β Your App Backend β proxy) β Carbone β
β (Handles auth, β β β β β βββββΆ β On-Premise β
β session, etc.) β β β
βββββββββββββββββββββ βββββββββββββββββ
With a Carbone Cloud backend
When using Carbone Cloud as your backend, there are two ways to enable authentication:
- You can proxy all requests from your application's backend to a single Carbone account, just like the On-Premise setup described above.
- Alternatively, if you want your users to connect their own Carbone accounts to your app, please contact us so we can help you set up the integration. We provide an OAuth provider for partner integrations such as our integrations in Salesforce, Odoo, or HubSpot.
Backend Compatibility
The Studio Web Component is a standalone JavaScript component that communicates with the Carbone backend exclusively via the public HTTP API. This means it is generally compatible with both older and newer Carbone backend versions.
For example, Studio v5.1.0 works seamlessly with Carbone v5.0.0 and v5.2.0.
Version Alignment
Each Carbone backend release is accompanied by a matching Studio Web Component version.
Sometimes, this corresponding Studio version contains no internal changes and is simply a version alignment to keep releases in sync.
Recommendation
It is recommended to use a Studio Web Component version that is equal to or greater than your Carbone backend version. This ensures optimal compatibility, but it is not strictly required.
Minimum Backend Compatibility
The Studio Web Component requires the following minimum Carbone backend versions for document generation and preview features: >= v3.8.0, >= v4.26.0, >= v5.0.0.
Advanced Features Requiring Carbone API v5
Certain features, such as those enabled by embedded-versioning mode (including template management, version history, and deployment), require the Carbone v5 API.
When Studio uses these advanced features, it automatically includes the HTTP header carbone-version: 5 in its requests.
Embedded mode
The Studio Web Component provides two integration modes for your application:
embedded: Use this mode if your application is responsible for handling template files or if youβre using the Carbone backend without a database (no template versioning). The studio does not create new versions of templates. Your application is responsible for listening to studio save events and uploading/saving the template as needed.embedded-versioning: Use this mode if you want Carbone to manage template saving, versioning, and deployment for you. This requires the Carbone backend with a database enabled or Carbone Cloud.
The following table summarizes how these two modes differ:
| Mode | embedded | embedded-versioning |
|---|---|---|
| Carbone backend compatibility | ||
| On-Premise (no database, only report generator) | ||
| On-Premise (with database, stateful) | ||
| Carbone Cloud (with reverse proxy) | ||
| Template user interactions | ||
| Download/Upload template | ||
| Live reload on template change | ||
| View/Save/Delete multiple versions of a template | ||
| Select which template version to deploy | ||
| Modify comment of each version | ||
| Studio Web Component APIs | ||
openTemplate [deprecated since 5.1.1, replaced by openTemplateVersionId] |
||
openTemplateId open template by id (automatic sample/version fetch) |
||
openTemplateVersionId open template by its SHA256 file hash / versionId (low level) |
||
openTemplateURL open template from URL |
||
openTemplateDataURI open template from Data URI |
||
| Custom Events | ||
connected when the component is added to the page |
||
disconnected when the component is removed from the page |
||
options:updated when preview options change |
||
template:updated when the template file changes |
||
template:saved when clicking the "save" button |
||
template:deployed when clicking the "deploy" button |
||
| API endpoints called (can be overridden) | ||
GET /template/:versionId fetches the template on first download by user |
||
POST /render/template generates a preview |
||
GET /render/:renderId fetches the rendered preview |
||
GET /templates?id=<id>&includeVersions=true retrieves all versions of template |
||
GET /template/:templateId_sample.json fetches sample data if not provided when opening |
||
POST /template on "save" button click |
||
PATCH /template on "deploy", "delete", or comment changes |
For your information, Carbone also provides two other modes. These modes are generally not recommended for integration:
light: The default studio interface without database support.full: The default studio interface with database enabled (used by Carbone Cloud).
Typical "embedded" mode flow
In the embedded mode, the Studio Web Component only calls endpoints for previewing rendered documents. Your application is responsible for reacting to these events (such as saving or uploading the new template). Listen for events like template:updated and implement your persistence logic accordingly.
ββββββββββββ βββββββββββββββββ
β Your β β Carbone β
β App β β embedded mode β
βββ¬βββββββββ βββ¬ββββββββββββββ
β β
β Open the studio β
ββββββββββββββββββββββββΊβ
β β
β β
β β
β Listen to events ββββΊβββββΊ POST /render/template
β βββββββββββββββββββ€ β For each preview update
β βββββ€ on template changes
β β
POST /template βββββ€ β
Save the template β β
β Close the studio β
ββββββββββββββββββββββββΊβ Typical "embedded-versioning" mode flow
In the embedded-versioning mode, the Studio Web Component handles template version management. Users can create, delete, and deploy template versions directly within the Studio interface.
As a developer, you can intercept and override API requests triggered by user actions, allowing you to implement custom backend logic or workflows as needed.
ββββββββββββ ββββββββββββββββββββββββββββ
β Your β β Carbone β
β App β β embedded-versioning mode β
βββ¬βββββββββ βββ¬βββββββββββββββββββββββββ
β β
β Open the studio β
ββββββββββββββββββββββββΊβ
β β
β β
β Listen to events ββββΊβββββΊ POST /render/template
β βββββββββββββββββββ€ β For each preview update
β βββββ€ on template changes
β β
β β
β Listen to events ββββΊβββββΊ GET /templates
β βββββββββββββββββββ€ β POST /template
β βββββ PATCH /template
β β Manage template versions
β Close the studio β
βββββββββββββββββββββββββ€ Technical Stack
- CSS: BeerCSS, fully customizable with variables and CSS overrides
- JavaScript: Implemented as a near-native web component, utilizing an optimized version of Lego.js
- PDF Viewer: Uses the native browser viewer, and an optimized version of PDF.js
- HTML Editor: Powered by Squire
- JSON/Code Editor: Powered by CodeMirror
Full Example
Start Carbone On-Premise
docker run -t -i --rm -p 4000:4000 -e CARBONE_STUDIO=true -e CARBONE_DATABASE_NAME="database.sqlite" carbone/carbone-ee:full-5.1.1By default, the API will listen on http://localhost:4000.
Create a Quick HTML Page
Copy and save the following as
index.htmlanywhere on your computer:<!DOCTYPE html> <html lang="en" style="height:100%;"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Carbone Studio Quick Test</title> <meta name="color-scheme" content="light"> <style> html, body { height:100%; margin:0; } carbone-studio { width:100vw; height:100vh; } </style> </head> <body></body> <script src="https://bin.carbone.io/studio/5.1.1/carbone-studio.min.js"></script> <script> // Create and append the studio component, starting in "off" mode for silent initialization const studio = document.createElement('carbone-studio'); studio.setAttribute('carbone-mode', 'off'); document.body.appendChild(studio); window.addEventListener('DOMContentLoaded', () => { studio.setConfig({ // Point this to your local Carbone On-Premise instance! origin : 'http://localhost:4000/', mode : 'embedded-versioning' // enables versioning features }); // Example: open an online test template with some sample data studio.openTemplateURL('https://carbone.io/examples/awards-simple/template.docx', 'https://carbone.io/examples/awards-simple/data.json'); }); </script> </html>Serve the HTML Page
Open a terminal in the folder where you savedindex.htmland run a simple web server:# On Linux or MacOS python3 -m http.server 8000 # Or on Windows (Command Prompt or PowerShell) py -m http.server 8000Test it!
Open http://localhost:8000 in your browser.
You should see the Studio Web Component loaded and ready to edit a sample template.
That's it! You're ready to embed and test the Carbone Studio Web Component anywhere.