docs/static/v0.9/project/contributing/contributing-ui-widgets/index.html
Prerequisite Reading
Meshery’s dashboard is a composable and extensible interface made up of individual widgets. These widgets allow contributors to surface specific Meshery data or capabilities within a modular layout system.
This guide walks through the process of creating and integrating a custom widget into the Meshery dashboard. You’ll learn about layout configuration, design best practices, and how to register new widgets.
Widgets are React components located here:
/ui/components/DashboardComponent/widgets/
Each widget is rendered inside a card component (<PlainCard />, <DesignCard />, etc.), which is sourced from the Sistent design system.
Widgets can:
Create a new file inside widgets/, e.g.:
/ui/components/DashboardComponent/widgets/LatestBlogs.js
Use design system components from @sistent/sistent:
import { useTheme, PlainCard, BellIcon } from "@sistent/sistent";
const LatestBlogs = (props) => {
const theme = useTheme();
const { data: blogs } = useFetchBlogsQuery(); // fetch data from rtk query
return (
<PlainCard
title="LATEST BLOGS"
icon={<BellIcon {...props.iconsProps} />}
resources={resources}
/>
);
};
export default LatestBlogs;
Use useTheme() for consistent color tokens across themes.
Thumbnails are image previews of widgets. Place them here:
/ui/components/DashboardComponent/widgets/Thumbnails/
Recommended format: .png or .svg
Example:
import LatestBlogsThumbnail from "./Thumbnails/LatestBlogs.png";
To verify your thumbnail appears correctly, click on the “Edit” button on the Dashboard. A visual card with your thumbnail and widget title will be listed there, allowing users to add it to their layout.
Register your widget inside getWidgets.js:
export const getWidgets = () => ({
LATEST_BLOGS: {
title: "Latest Blogs",
isEnabled: alwaysShown,
component: <LatestBlogs />,
defaultSizing: { w: 3, h: 2 },
thumbnail: LatestBlogsThumbnail?.src,
},
});
title: Display namecomponent: JSX elementisEnabled: Visibility flagdefaultSizing: Default dimensionsthumbnail: Path to preview imageTo include your widget in the default dashboard layout:
/ui/components/DashboardComponent/defaultLayout.js
Layouts are defined per screen size breakpoint (e.g., sm, xs, xxs) to ensure responsiveness. Each layout item is an object with grid-based properties defined by the react-grid-layout library.
sm: tablets and desktops
xs: large phones
xxs: small phones
{
h: 2, // Height in grid units
i: 'LATEST_BLOGS', // Widget identifier (unique string)
moved: false, // Internal flag (do not change manually)
static: false, // If true, the widget cannot be dragged or resized
w: 3, // Width in grid units
x: 0, // Horizontal grid position (column index)
y: 0, // Vertical grid position (row index)
}
id used elsewhere in your code.y value appear in the same row.true, the widget is locked in place — it can’t be moved or resized.false.Here layout is based on a 12-column CSS grid. Each widget’s position is defined in terms of this virtual grid, which helps in building a responsive and flexible dashboard layout.
Define the widget’s position (x, y) and size (w, h) in each breakpoint for responsive behavior. The code for it can be found here.
Note: Layouts for Remote Providers are dynamically generated based on user configuration and stored remotely. Local providers use a predefined layout (LOCAL_PROVIDER_LAYOUT). Widgets must be added to both if you want consistent behavior across environments.
Meshery stores user layout preferences either in local storage or via the provider’s backend, depending on login state.
This is how your default widget would appear in the dashboard:
MY_DESIGNS) for clarityCatalogIcon, DesignIcon)useTheme() to access tokenssm, xs, xxs)| Widget | File | Data Source | UI Component |
|---|---|---|---|
| Latest Blogs | LatestBlogs.js | RSS Feed | PlainCard |
| Help Center | HelpCenterWidget.js | Static Links | PlainCard |
| My Designs | MyDesignsWidget.js | REST Api | DesignCard |
Note: MyDesignsWidget demonstrates integration with RTK Query hooks like useGetLoggedInUserQuery() and useGetUserDesignsQuery().
Have a look at existing Widgets here.
Once your widget is working:
[ Previous
UI End-to-End Tests ](/v0.9/project/contributing/contributing-ui-tests)[ Next
Schema-Driven UI in Meshery ](/v0.9/project/contributing/contributing-ui-schemas)