Defining Components
You can create custom React components in Embeddable using any JS libraries you like.
Key capabilities include:
- Define Inputs: Make re-usable components by defining inputs your team can customize in the builder.
- Load Data: Dynamically fetch data from your database via Embeddable's
loadData
function. - Pass Events: Capture user actions (e.g. button clicks) and send them back to Embeddable for interactive features like filtering.
How It Works
Build Your React Component (.tsx
)
Write a standard React component - handling your UI, props, and business logic.
For example, this simple text component displays a title and body:
// src/components/TextComponent/index.tsx
import React from 'react';
type Props = {
title: string;
body: string;
};
export default ({ title, body }: Props) => {
return (
<div>
<h1>{title}</h1>
<p>{body}</p>
</div>
);
};
There's nothing Embeddable-specific about this code - it's just standard React.
Configure in .emb.ts
In a companion .emb.ts
file, define inputs and other configuration, including how to load data. This file tells Embeddable how to expose the component in the no-code builder so it can be configured by your team without code:
// src/components/TextComponent/TextComponent.emb.ts
import { EmbeddedComponentMeta, defineComponent } from '@embeddable.com/react';
import Component from './index';
import { Inputs } from '@embeddable.com/react';
export const meta = {
name: 'TextComponent', // a unique identifier that must match the file name (i.e. TextComponent.emb.ts)
label: 'Text component', // user-facing name in the builder
inputs: [
{
name: 'title', // unique identifier for this input
type: 'string', // determines the UI control to render (i.e. a text field in this case)
label: 'Title', // the label shown in the builder
},
{
name: 'body', // unique identifier for this input
type: 'string', // renders a second text field.
label: 'Body', // the label shown in the builder
}
]
} as const satisfies EmbeddedComponentMeta;
//The function that tells the SDK to include this component in the no-code builder.
export default defineComponent(Component, meta, {
props: (inputs: Inputs<typeof meta>) => {
return {
// the inputs are passed through to the React component as props
title: inputs.title,
body: inputs.body
};
}
});
Two things to notice:
inputs
tells Embeddable which input fields to show in the UI when using this component. In this case, two text input fields.props
is a function that takes thoseinputs
and maps them onto theprops
that should be passed into the React component when rendering.
Push to Embeddable
Run npm run embeddable:dev
to test out your component, and when you’re happy with it, push your component code to Embeddable. Your teammates can now drag, drop, and configure it in their dashboards - no extra coding required.


Example: a simple data component
Below is a simple KPI chart component that loads data from your database:
// src/components/KPIChart/index.tsx
import React from 'react';
import { DataResponse, Measure } from '@embeddable.com/core';
import Loading from '../util/Loading'
import Error from '../util/Error'
type Props = {
title?: string;
metric?: Measure; // { name, title }
results: DataResponse; // { isLoading, error, data: [{ <name>: <value>, ... }]
};
export default ({ title, metric, results }: Props) => {
const { isLoading, data, error } = results;
if(isLoading) {
return <Loading />
}
if(error) {
return <Error msg={error}/>;
}
const value = results.data?.[0]?.[metric.name] ?? 'No data';
return (
<div>
{title && <h1>{title}</h1>}
<p>{value}</p>
</div>
);
};
And its .emb
file, defining the inputs and configuration:
// src/components/KPIChart/KPIChart.emb.ts
import { EmbeddedComponentMeta, defineComponent, Inputs } from '@embeddable.com/react';
import { loadData } from '@embeddable.com/core';
import Component from './index';
export const meta = {
name: 'KPIChart', // an identifier - must match KPIChart.emb.ts
label: 'KPI Chart', // user-facing name in the builder
inputs: [
{
name: 'title',
type: 'string',
label: 'Title text',
},
{
name: 'ds',
type: 'dataset', // shows a dropdown of available datasets. These are created directly in the Builder.
label: 'Dataset',
},
{
name: 'metric',
type: 'measure', // shows a dropdown of measures (defined in your data models)
label: 'KPI',
array: false, // specifies that users can select a single measure
config: {
dataset: 'ds', // restricts measure options to the selected dataset
}
},
]
} as const satisfies EmbeddedComponentMeta;
//The function that tells the SDK to include this component in the no-code builder.
export default defineComponent(Component, meta, {
props: (inputs: Inputs<typeof meta>) => {
return {
...inputs, // the inputs are passed through to the component as props
results: loadData({ // fetches data from your database and passes it to your component
from: inputs.ds,
measures: [inputs.metric],
})
};
}
});
The defineComponent
and loadData
functions used above are two of the most powerful parts of the Embeddable SDK. You can learn more about them here: defineComponent and loadData.
Extending Vanilla Components
You can also extend existing components like the Bar Chart or Pivot Table to add custom functionality. This allows you to leverage the existing UI while adding your own logic or data handling. There are two ways to do this:
Copy the Component and Make It Your own
This is the way we recommend, as it will allow you to have both your customized component and the original Vanilla component available in the builder. There are two simple steps:
Copy the Component Code
Visit our repo (opens in a new tab) and copy the component code from the Vanilla component you want to extend. For example, if you want to extend the Bar Chart, copy the code from src/components/BarChart/index.tsx
and src/components/BarChart/BarChart.emb.ts
.
Create Your Own Component
Create a new folder in src/components/
with your component name, and paste the copied code into it. Then, update the component name in the .emb.ts
file to match your new component name. Make sure your component's .emb.ts
file name matches the component name, e.g. if your component is named MyBarChart
, the file should be MyBarChart.emb.ts
.
From here, you'll have a fully functional component that you can customize further. You can add your own logic, inputs, and data handling as needed. When you're ready to test, just fire up the development server with npm run embeddable:dev
and you'll be able to see your new component in the menu.
Some components are more complex than others, and a few of them call on various helper/utility files to handle specific functionality. If you find that your component is missing some of these dependencies, you can copy them over from the Vanilla component's folder as well. You can change the folder structure as needed, but make sure to update the import paths in your component code accordingly.
Override the Vanilla Component Entirely
Important: if you follow this route, you will no longer receive updates to the original component. They'll still come through when you update the package, but because this involves disabling a particular chart, you won't see them.
If you want to completely override a Vanilla component, you can do so by disabling it in the embeddable.config.ts
file. This will remove it from the builder and allow you to use your own version instead. The process for creating your own component is the same as above (you still need to copy the code), but you won't need to rename the component - you can use the same folder and component name as the original Vanilla component.
To disable the Vanilla component, open the embeddable.config.ts
file in your project root and add the following code:
componentLibraries: [{
name: '@embeddable.com/vanilla-components',
exclude: ['BarChart'],
}],
... where BarChart
is the name of the component you want to disable. You can add multiple components to the exclude
array if needed. This will remove the Vanilla component from the builder, allowing you to use your own version instead.
Once you've done this, you can run npm run embeddable:dev
to test your new component in the builder. It will now appear in the menu, and you can use it in your dashboard just like any other component. Keep in mind that until you make some changes, the component will look and behave exactly like the original Vanilla component, so you'll need to customize it further to make it your own.