robobyte-front-builder
v1.0.35-beta.12
Published
RoboByte low-code UI builder, Report builder, and navigation extension system
Maintainers
Readme
robobyte-front-builder
A low-code UI Builder, Report Builder, Print Layout Designer, and Navigation Extension API for Next.js applications.
📚 Documentation
| Document | Audience | What it covers |
|---|---|---|
| README.md (this file) | Everyone | Public surface, provider props, every component's inspector schema, action-scope tables, troubleshooting, changelog. The exhaustive reference. |
| INTEGRATION.md | Host-app developers | next.config.js setup, peer deps, page wrapper pattern, provider bridge, print layout integration steps. |
| docs/ReportViewer.md | Host-app developers | Embedding <ReportViewer> in regular React (cancellation, memo'd filters, viewerActions, master/detail patterns). |
| docs/fetchReportData.md | Host-app developers | Calling fetchReportDataByPageId directly from host code (hooks, KPI counters, XLSX export, paginated cursors). |
| docs/printLayout.md | Host-app developers | Triggering print layouts via PrintDialog ref API, recommended PrintProvider + usePrintLayout() pattern. |
| training/00-index.md | AI sessions / schema authors | Component catalog index — categories and one-page refs for every component the builder ships. |
| training/35-reportViewer.md | AI sessions / schema authors | Full AI manual for the reportViewer component (Calculation scope, action arrays, filter shape, recipes). |
| training/48-fetchReportData.md | AI sessions / schema authors | In-builder Calculation reference for the auto-injected fetchReportData helper. |
| training/49-printLayout.md | AI sessions / schema authors | In-builder Calculation reference for openPrintLayout / closePrintLayout. |
| RoboByteBuilder_User_Manual.docx | End users | Visual user manual for the builder UI. Ships inside the package. |
Pair convention. Most features have two manuals: a
docs/one for host-app React code (consumer of the package) and atraining/one for AI sessions emitting builder schemas / Calculation code. They cross-link each other; pick the audience that matches your task.
Table of Contents
- What's included
- Requirements
- Installation
- Peer dependencies
- next.config.js setup
- Provider setup
- Builder pages
- Navigation Extension API
- Provider props reference
- AG Grid theme
- MUI theme
- fetchReportDataByPageId
- ReportViewer as a component
- Data Grid component
- Dialog component
- Popover component
- Excel Upload component
- Wizard component
- Repeater component
- Menu component
- View Renderer component
- Layout Grid component
- Breadcrumb component
- Print Layout Builder
- Calculation Scope Reference
- KPI Component Actions
- Global Data Store
- Dark / Light theme
- Syncing local changes
- Troubleshooting
- Publishing
- Changelog
What's included
- UI Builder — drag-and-drop canvas for building data-driven views with 50+ components
- Report Builder — design and preview paginated reports with AG Grid
- Print Layout Designer — multi-zone print templates (header / body pages / footer)
- Navigator Builder — configure sidebar navigation
- Viewer — production read-only renderer for saved UI Builder views
- Navigation Extension API — inject nav items from the host app without forking the package
- KPI Components — 12 ready-to-use metric visualisations (gauge, trend, bullet chart, rating, countdown, …)
- Timer Engine — configurable auto-refresh timers per view
- Undo / Redo / Copy / Paste — full clipboard and history support in the builder
- Global Data Store — cross-route reactive state that survives client-side navigations
Requirements
| Dependency | Version | |---|---| | Node.js | ≥ 18 | | React / React DOM | ≥ 18 | | Next.js | ≥ 13 | | @mui/material | ≥ 7 | | AG Grid | ≥ 33 |
Installation
npm install robobyte-front-builderPeer dependencies
Only the libraries that must be shared as a single instance are declared as peerDependencies — React, MUI, Emotion, and AG Grid. Everything else ships inside the package so the host app doesn't need to install them manually.
npm install \
react react-dom next \
@mui/material @mui/icons-material @mui/lab @mui/system \
@mui/x-data-grid @mui/x-date-pickers @mui/x-internals @mui/x-virtualizer \
@emotion/react @emotion/styled \
ag-grid-community ag-grid-enterprise ag-grid-react \
xlsx react-hot-toastWhy only these? React and MUI use context and module registries that break if two copies exist in the same app (hooks errors, theme not applied, AG Grid license warnings).
xlsxis required by the Excel Upload component and is resolved from the host app'snode_modulesbecause the builder source is transpiled in the host's webpack context. Everything else —dayjs,lodash,recharts, etc. — can safely run from the package's ownnode_modulescopy with no side effects.
next.config.js setup
Two things are required: transpile the package and set up the context-aware bare-alias webpack plugin so that bare imports like services/*, context/*, etc. resolve to the correct source tree.
const path = require('path')
const withTM = require('next-transpile-modules')(['robobyte-front-builder'])
const hostSrc = path.resolve(__dirname, 'src')
const builderSrc = path.resolve(__dirname, 'node_modules/robobyte-front-builder/src')
module.exports = withTM({
webpack(config, { isServer }) {
if (isServer) {
config.resolve.conditionNames = ['require', 'node', 'default']
}
const { NormalModuleReplacementPlugin } = require('webpack')
// Package-owned services — always resolved from the package
const packageOwnedServices = [
'services/reportData/fetchReportData',
]
packageOwnedServices.forEach(mod => {
config.plugins.push(
new NormalModuleReplacementPlugin(
new RegExp(`^${mod.replace(/\//g, '\\/')}(\\.js)?$`),
resource => { resource.request = path.join(builderSrc, mod) }
)
)
})
// Context-aware bare alias routing
config.plugins.push(
new NormalModuleReplacementPlugin(
/^(services|views|context|src|pages)(\/|$)/,
resource => {
const isBuilder =
resource.context.includes('robobyte-front-builder') ||
resource.context.includes('RoboByteFrontBuilder')
const root = isBuilder ? builderSrc : hostSrc
resource.request = resource.request.replace(
/^(services|views|context|src|pages)(\/|$)/,
(_, prefix, sep) =>
prefix === 'src'
? root + sep
: path.join(root, prefix) + sep
)
}
)
)
return config
},
})Restart the dev server whenever
next.config.jschanges — hot-reload does not apply to webpack plugin changes.
Provider setup (_app.js)
Wrap the component tree with RoboByteFrontBuilderProvider. Bridge your host auth context into it so the package attaches auth headers to every API call.
import { RoboByteFrontBuilderProvider } from 'robobyte-front-builder'
function RoboByteBridge({ children }) {
const auth = useContext(YourAuthContext)
return (
<RoboByteFrontBuilderProvider
baseURL={process.env.NEXT_PUBLIC_API_BASE_URL}
apiURL={process.env.NEXT_PUBLIC_API_URL}
user={auth.user}
accessToken={auth.accessToken}
agGridLicenseKey={process.env.NEXT_PUBLIC_AG_GRID_LICENSE_KEY}
// Optional: Quartz theme overrides applied to every <AgGridReact>
// in the package. Merged on top of the package defaults — see the
// "AG Grid theme" section for the full list of params and the
// programmatic API. Omit to use the package defaults.
agGridTheme={{ accentColor: '#3b82f6' }}
// Optional: MUI theme overrides applied to every MUI component the
// package renders. Deep-merged on top of DEFAULT_MUI_THEME_OPTIONS.
// See the "MUI theme" section for the full token list. Omit to use
// the package defaults (Inter font, 8px radius, soft shadows, etc.).
muiTheme={{
palette: { primary: { main: '#3b82f6' } },
shape: { borderRadius: 10 },
}}
>
{children}
</RoboByteFrontBuilderProvider>
)
}
export default function App({ Component, pageProps }) {
const getLayout = Component.getLayout ?? (page => page)
return (
<YourAuthProvider>
<RoboByteBridge>
{getLayout(<Component {...pageProps} />)}
</RoboByteBridge>
</YourAuthProvider>
)
}Builder pages
All builder routes live under the /builders/ prefix. Create a thin wrapper page in your host app for each route.
| Route | Package export |
|---|---|
| /builders/ui | UIBuilderPage |
| /builders/ui/views | ViewsList |
| /builders/report | ReportBuilderPage |
| /builders/report/list | ReportsList |
| /builders/report/viewer | ReportViewer |
| /builders/report/reportsPermissions | ReportsCard |
| /builders/navigator | NavigatorBuilderPage |
| /viewer/[id] | ViewerPage |
| /printBuilder | PrintBuilderPage |
| /printBuilder/layouts | PrintLayoutsList |
Page wrapper pattern
Use explicit import + static property assignment. A bare export { X as default } does not reliably carry getLayout, acl, authGuard across package boundaries in Next.js.
// pages/builders/report/viewer/index.jsx
import { ReportViewer } from 'robobyte-front-builder'
import BlankLayout from 'src/@core/layouts/BlankLayout'
import PermissionsSubjects from 'src/configs/Permissions/PermissionsSubjects.json'
ReportViewer.getLayout = page => <BlankLayout>{page}</BlankLayout>
ReportViewer.acl = { action: 'view', subject: PermissionsSubjects.Free }
ReportViewer.authGuard = true
ReportViewer.guestGuard = false
export default ReportViewerViewer page (/viewer/[id])
import { useContext } from 'react'
import { ViewerPage, SystemContext } from 'robobyte-front-builder'
import { YourNavContext } from 'src/context/YourNavContext'
function SystemContextBridge({ children }) {
const { nav } = useContext(YourNavContext)
return (
<SystemContext.Provider value={{ nav }}>
{children}
</SystemContext.Provider>
)
}
export default function ViewerRoute() {
return (
<SystemContextBridge>
<ViewerPage />
</SystemContextBridge>
)
}
ViewerRoute.authGuard = true
ViewerRoute.guestGuard = falseNavigation Extension API
Option A — Static items via the Provider
<RoboByteFrontBuilderProvider
navExtensions={[
{
id: 'host-analytics',
title: 'Analytics',
icon: 'ChartBar',
type: 'static',
path: '/analytics',
insertAt: 'end',
},
]}
>
...
</RoboByteFrontBuilderProvider>Option B — Dynamic items via useNavExtension hook
import { useNavExtension } from 'robobyte-front-builder'
function MyFeaturePlugin() {
useNavExtension(
[{ id: 'my-feature', title: 'My Feature', icon: 'StarOutline', type: 'static', path: '/my-feature', insertAt: 'start' }],
'my-feature-plugin'
)
return null
}Nav item shape
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | yes | Stable unique identifier |
| title | string | yes | Display label |
| icon | string | no | mdi-material-ui icon name |
| type | 'static' | 'dynamic' | 'external' | yes | Route type |
| path | string | for static | Absolute path |
| viewId | number | for dynamic | Registered view ID |
| externalUrl | string | for external | Full URL, opens in new tab |
| insertAt | 'start' | 'end' | number | { afterId } | { beforeId } | no | Placement (default 'end') |
| children | NavItem[] | no | Collapsible group |
| action / subject | string | no | CASL ACL visibility |
Provider props reference
| Prop | Type | Description |
|---|---|---|
| baseURL | string | Root API server URL |
| apiURL | string | /api prefix URL |
| user | object | Current user object from your auth context |
| accessToken | string | Bearer token attached to every service call |
| agGridLicenseKey | string | AG Grid Enterprise license key — the provider calls LicenseManager.setLicenseKey() and registers all enterprise modules internally |
| agGridTheme | object | Quartz theme overrides applied to every <AgGridReact> in the package. Merged on top of DEFAULT_AG_THEME_PARAMS. Example: { accentColor: '#3b82f6', headerHeight: 32 }. See AG Grid theme. |
| muiTheme | object | Theme | MUI theme overrides (options object) deep-merged on top of DEFAULT_MUI_THEME_OPTIONS, OR a pre-built MUI Theme used as-is. Example: { palette: { primary: { main: '#6366f1' } }, shape: { borderRadius: 12 } }. See MUI theme. |
| disableMuiTheme | boolean | When true, the provider skips its inner <ThemeProvider> entirely — use this if the host app already wraps everything in its own MUI ThemeProvider and wants it to apply inside the builder pages without merging. Default false. |
| navExtensions | array | Static nav items to inject into the sidebar |
| endpoints | object | Full-URL overrides per endpoint group + name |
AG Grid note: Do not call
LicenseManagerorModuleRegistryin the host app — the provider handles it entirely.
AG Grid theme
Every <AgGridReact> in the package — reportViewer, dataGrid, the role-permission editor, the navigator picker — reads its theme from a single context. The default lives in code at src/lib/agGridTheme.js and can be overridden in two places:
1. Host-app override via the provider
Pass an object of Quartz params to agGridTheme. The object is merged on top of the package defaults — keys you set win, everything else falls back.
<RoboByteFrontBuilderProvider
agGridTheme={{
accentColor: '#3b82f6',
headerHeight: 32,
fontFamily: 'inherit',
}}
/* …other props… */
>
<App />
</RoboByteFrontBuilderProvider>See the AG Grid Quartz theming reference for the full list of params.
2. Package-wide default
Open src/lib/agGridTheme.js and edit DEFAULT_AG_THEME_PARAMS. Affects every consumer of robobyte-front-builder that doesn't supply its own agGridTheme.
Programmatic use
import {
DEFAULT_AG_THEME_PARAMS, // frozen params object
DEFAULT_AG_THEME, // pre-built Quartz theme
buildAgGridTheme, // (overrides) => Quartz theme
AgGridThemeProvider, // standalone provider (no other dependencies)
useAgGridTheme, // hook returning the resolved theme
} from 'robobyte-front-builder'
// In a host component that renders its own AG Grid:
import { AgGridReact } from 'ag-grid-react'
function MyGrid() {
const theme = useAgGridTheme()
return <AgGridReact theme={theme} columnDefs={[...]} />
}The hook falls back to DEFAULT_AG_THEME when called outside RoboByteFrontBuilderProvider, so isolated grids still render correctly.
Future plan. A "system settings" path will eventually layer between
DEFAULT_AG_THEME_PARAMSand the host'sagGridThemeprop, letting admins customize the theme without a code change. The provider API will stay the same.
MUI theme
Every Material-UI component the package renders (Button, TextField, Dialog, Tooltip, Chip, Card, Tabs, …) reads its theme from a single MUI <ThemeProvider> mounted by RoboByteFrontBuilderProvider. The default theme lives at src/lib/muiTheme.js and is designed to look distinctly not like stock MUI — Inter typography, 8px radius, soft shadows, flat buttons, no ripple, faster tooltips, dark mode pair.
Key default tokens
| Token | Value | Rationale |
|---|---|---|
| typography.fontFamily | Inter, SF Pro Display, system-ui, … | Modern UI font with graceful system fallbacks. |
| shape.borderRadius | 8 | Soft corners across the surface (vs MUI's default 4). |
| palette.primary.main | #3b82f6 | Tailwind blue-500, professional neutral primary. |
| palette.secondary.main | #FF1185 | Matches DEFAULT_AG_THEME_PARAMS.accentColor — brand color shared with AG Grid surfaces. |
| shadows[1..8] | soft, large-radius | Tailwind-like elevation instead of Material's hard shadows. |
| MuiButton.disableElevation | true | Flat buttons by default. |
| MuiButton.disableRipple | true | Desktop-first. |
| MuiTextField.size | 'small' | Builder UI is data-dense. |
| MuiTooltip.arrow / enterDelay | true / 200ms | Less hover-spam, more obvious anchoring. |
Host-app override via the provider
<RoboByteFrontBuilderProvider
muiTheme={{
palette: {
primary: { main: '#6366f1' }, // indigo-500
},
shape: { borderRadius: 12 },
typography: { fontFamily: '"Plus Jakarta Sans", sans-serif' },
}}
>
<App />
</RoboByteFrontBuilderProvider>The override is deep-merged on top of the package defaults — keys you set win, everything else falls back.
Three ways to pass muiTheme
| Pass | What happens |
|---|---|
| Nothing | Uses DEFAULT_MUI_THEME. |
| Theme options object ({ palette, shape, typography, components, … }) | Deep-merged with defaults; package builds the final Theme. |
| A pre-built MUI Theme (from your own createTheme) | Used as-is. Escape hatch for full control. |
Disable the inner ThemeProvider
If the host has its own <ThemeProvider> wrapping the entire app and wants it to apply inside the builder pages without merging, pass disableMuiTheme={true}:
<ThemeProvider theme={yourGlobalTheme}>
<RoboByteFrontBuilderProvider disableMuiTheme>
<App />
</RoboByteFrontBuilderProvider>
</ThemeProvider>Programmatic use
import {
DEFAULT_MUI_THEME_OPTIONS, // raw default options (frozen)
DARK_MUI_THEME_OPTIONS, // dark counterpart
DEFAULT_MUI_THEME, // pre-built light Theme
DEFAULT_MUI_THEME_DARK, // pre-built dark Theme
buildMuiTheme, // (overrides, { mode? }) => Theme
isResolvedMuiTheme, // (value) => boolean — detect options vs Theme
} from 'robobyte-front-builder'Coordinating with AG Grid + brand identity
The MUI palette.secondary.main (#FF1185) and the AG Grid accentColor are intentionally the same string. Change one, change the other, or wait for the future unified theme prop that will derive both from a shared token bag.
Future plan. A single unified
themeprop will derive MUI, AG Grid, and chart themes from one set of design tokens. Until then,muiThemeandagGridThemeare the two sources to coordinate.
fetchReportDataByPageId
Fetches report data by pageId without any AG Grid dependency. Always imported from the package path — the NormalModuleReplacementPlugin in next.config.js routes it to the package's canonical implementation.
import fetchReportDataByPageId from 'services/reportData/fetchReportData'
const result = await fetchReportDataByPageId({
pageId, // required
filter, // { Tfilter, TFilter, customFilterCode, ... }
isDataOnly, // return raw rows only (default false)
dataAsObject, // key rows by unique id (default false)
isPagination, // server-side pagination (default true)
isSingle, // return first row only (default false)
globalParams, // override selectionParams by index
page, // page number (default 1)
pageSize, // page size (default 50)
authContext,
context,
})
if (result.success) {
console.log(result.rows)
console.log(result.total)
}customFilterCode
const filter = {
customFilterCode: `
if (authContext?.user?.shopId) {
customFilter.push({ field: 'ShopId', value: authContext.user.shopId, operation: 'Equal' })
}
`
}ReportViewer as a component
ReportViewer can be rendered inline anywhere — not only as a full page:
import { ReportViewer } from 'robobyte-front-builder'
<ReportViewer
pageId="your-page-id"
minimized={true}
noHeader={true}
filter={{ Tfilter: [...] }}
height="400px"
/>| Prop | Type | Description |
|---|---|---|
| id | string | Report ID |
| pageId | string | Report page ID |
| filter | object | External filter |
| minimized | bool | Removes padding and box shadow |
| noHeader | bool | Hides the report title and studio button |
| height | string | Grid height (default 85vh) |
| isSingle | bool | Return only the first row |
| dataAsObject | bool | Key rows by unique id |
| setData | function | Callback receiving the loaded rows |
| setOutGridApi | function | Callback receiving the AG Grid API instance |
| refresh | any | Change this value to force a data reload |
| actions | array | Custom row action buttons |
| columnsConfig | array | Column overrides |
| globalParams | array | Override selectionParams by index |
| sessionId | string | Load filter payload from localStorage |
| updateRef | ref | Ref for programmatic updates |
Data Grid component
The Data Grid wraps AG Grid Enterprise and is configurable entirely from the builder inspector.
Inspector — Main tab
| Field | Description |
|---|---|
| Key | Reference key for reportRefs access |
| Data Key | Key to read/write row data in page data |
| Columns | Expression returning an AG Grid colDef[] array |
| Extra Columns | Visual editor for adding new columns on top of data-driven ones |
| Columns Config | Visual editor for overriding existing column properties by field name |
| Row Actions | Visual editor for per-row action buttons |
| Add Button Label | Label for the add-row button (default "Add") |
| New Row Template | Code returning the default object for a new row |
| Read Only | Expression — when truthy, disables all editing |
| Show Add Button | Toggle the add-row button |
| Show Delete Col | Toggle the delete-row column |
| Height | Grid height expression (e.g. '400px', '60vh') |
| Row Selection | none / single / multiple |
| Pagination | Enable client-side pagination |
| Page Size | Rows per page |
reportRefs API
const grid = reportRefs['myGridKey']
grid.getRows() // current row data array
grid.setRows(arr) // replace all rows
grid.addRow(obj) // append a row
grid.updateRow(index, obj) // update a row by index
grid.deleteRow(index) // delete a row by index
grid.getGridApi() // raw AG Grid API instanceDialog component
Renders a hidden MUI Dialog opened programmatically via openDialog(key) / closeDialog(key).
Inspector — Main tab
| Field | Description |
|---|---|
| Key | Identifier used to open/close — must be unique on the page |
| View ID | When set, renders a full embedded view inside the dialog body |
| Title | Dialog title bar text (expression) |
| Hide Title Bar | Hides the entire title bar |
| Max Width | xs / sm / md / lg / xl |
| Full Width | Stretch to max width breakpoint |
| Full Screen | Full-screen mode |
| Show Close Button | Shows the × icon |
| Close on Backdrop | Closes when user clicks outside |
| Action Buttons | Footer buttons, each with its own Calculation code |
Usage
// Open with optional seed data
openDialog('confirmDelete')
openDialog('editUser', { userId: row.id, name: row.name })
// Close
closeDialog('confirmDelete')Isolated data store
Each dialog gets its own data / setData scope. To read or write the parent page state from inside a dialog use pageData and pageSetData:
// Inside a dialog action:
pageSetData(prev => ({ ...prev, lastEdited: data.userId }))Popover component
A self-contained trigger (button, icon button, or text) that opens a floating panel. No openDialog call needed.
Inspector — Main tab
| Field | Description |
|---|---|
| Trigger Type | button / icon-button / text |
| Trigger Label | Label text |
| Placement | bottom-start, bottom, bottom-end, top-start, etc. |
| Trigger On | click (default) or hover |
| Controlled Open | Expression — overrides the internal open/close state |
| Close On Content Click | Closes when any child inside is clicked |
Excel Upload component
Lets users upload .xlsx, .xls, or .csv files, map columns to field names, and access the result in actions.
Display variants
| Variant | Description |
|---|---|
| dropzone | Large dashed drop zone with drag & drop |
| button | Compact outlined button |
| icon | Icon-only button |
Actions
| Event | newValue | Notes |
|---|---|---|
| onUpload | { fileName, headers, rowCount } | Fires after parsing, before the mapping dialog |
| onMapped | Array<object> | Fires before data is saved — return a modified array to override |
| onClear | [] | Fires when the user clears the data |
reportRefs API
const uploader = reportRefs['myUploaderKey']
uploader.rows // current mapped rows
uploader.setRows(arr) // replace stored rows
uploader.clear() // clear all stored rowsWizard component
A MUI Stepper with optional validation, async lifecycle hooks, and controlled or uncontrolled step state.
Inspector props — Wizard
| Prop | Type | Default | Description |
|---|---|---|---|
| orientation | 'horizontal' | 'vertical' | 'horizontal' | Stepper orientation |
| linear | boolean | true | Prevent skipping ahead |
| hideNavigation | boolean | false | Hide Back / Next / Finish buttons |
| key | string | 'wizardStep' | data key written with the current step index |
| activeStep | number | expression | — | When set, wizard is controlled by data[key] |
| onStepChange | JS action | — | Receives { from, to, direction, goToStep, nextStep, prevStep } |
| onFinish | JS action | — | Runs when user clicks Finish on the last step |
Inspector props — Wizard Step
| Prop | Type | Description |
|---|---|---|
| label | string | Step label in the stepper header |
| optional | boolean | Marks the step as optional |
| onEnter | JS action | Fires when this step becomes active |
| onNext | JS action | Return false to block navigation (validation) |
Navigation helpers
goToStep(n) // jump to step n (0-based)
nextStep() // advance one step
prevStep() // go back one stepRepeater component
Renders a list of identical template items from a static array, a dynamic count, or a fetched API endpoint.
| Mode | How to configure |
|---|---|
| Static items | Set items to a static or expression array |
| Count | Set count to a number; optionally dataKey to store values |
| Endpoint | Set endpoint + serviceId or widgetId |
Expressions inside a Repeater
| Variable | Value |
|---|---|
| dataItem | The current array element |
| itemIndex | Zero-based item index |
| form[key] | The current item's scoped form value |
Menu component
Renders a MUI Tabs bar in two modes: navigation mode (items-based, each tab is a link/action) and tab-panel mode (tabs-based, each tab owns a drop zone).
| Prop | Type | Description |
|---|---|---|
| items | array | Navigation items { title, icon?, href? } — enables navigation mode |
| tabs | array | Tab panel items { label, icon? } — enables tab-panel mode |
| vertical | boolean | Render tabs vertically |
| justified | boolean | Stretch tabs to fill full width |
View Renderer component
Embeds a saved builder view inline inside another view, with isolated or shared state.
| Prop | Type | Description |
|---|---|---|
| viewId | string | Required. ID of the saved view to embed |
| isolated | boolean | true = own data/form/refs, false = shares parent state |
| initialData | expression | Seed data passed on mount (isolated mode only) |
| externalData | expression | Additional data merged on every parent re-render |
| heightMode | 'auto' | 'fixed' | 'fixed' enables a pixel height with scroll |
| height | number | Pixel height when heightMode is 'fixed' |
Layout Grid component
A CSS Grid container whose column count, gap, and per-cell styling are configured in the builder inspector.
| Prop | Type | Default | Description |
|---|---|---|---|
| cols | number | 2 | Number of equal-width columns |
| gap | number px | 8 | Column gap |
| rowGap | number px | same as gap | Row gap |
| cellMinHeight | number/string | — | Default min-height for every cell |
| cellPadding | number/string | — | Inner padding for every cell |
| cellBackgroundColor | color | — | Background color for every cell |
| cellBorder | string | — | CSS border shorthand for every cell |
| cellBorderRadius | number/string | — | Border radius for every cell |
| cellBoxShadow | string | — | Box-shadow for every cell |
| cellJustifyContent | string | — | Flexbox justify-content inside every cell |
| cellAlignItems | string | — | Flexbox align-items inside every cell |
Breadcrumb component
Renders a MUI Breadcrumbs navigation trail.
{
"type": "breadcrumb",
"props": {
"main": {
"items": {
"valueType": "value",
"value": [
{ "label": "Home", "href": "/" },
{ "label": "Reports", "href": "/reports" },
{ "label": "Q1 2025" }
]
}
}
}
}Print Layout Builder
⚠️ Preview — needs more testing. Functional but not production-ready.
Design reusable print layouts with configurable headers, footers, multi-page bodies, watermarks, and page numbering.
Backend API endpoints required
| Method | URL | Description |
|---|---|---|
| POST | UiBuilderModule/PrintLayout | Create a new layout |
| PUT | UiBuilderModule/PrintLayout | Update an existing layout |
| GET | UiBuilderModule/PrintLayout/GetAll | List all layouts |
| GET | UiBuilderModule/PrintLayout/GetById?id=<id> | Fetch by ID |
| DELETE | UiBuilderModule/PrintLayout?id=<id> | Delete a layout |
Triggering print from a view
openPrintLayout('your-layout-id', {
invoiceNumber: data.invoiceNumber,
customerName: data.customer.name,
lines: data.lines,
})Page numbering format
Use {page} and {pages} tokens in the Format field:
Page {page} of {pages} → Page 1 of 4Calculation Scope Reference
Every Calculation function receives the same set of variables:
Core state
| Variable | Description |
|---|---|
| form | Form field values (read-only snapshot) |
| data | Reactive page state |
| setData | Write page state — setData(prev => ({ ...prev, key: value })) |
| dataRef | Mutable non-reactive store |
| reportRefs | Map of { [key]: ref } for every Data Grid / Excel Upload on the page |
Dialog / layout
| Variable | Description |
|---|---|
| openDialog(key, data?) | Open a dialog, optionally seeding its isolated state |
| closeDialog(key) | Close a dialog |
| openPrintLayout(layoutId, data?) | Open the print preview |
| closePrintLayout() | Close the active print preview |
Navigation & routing
| Variable | Description |
|---|---|
| router | Next.js router — router.push('/path'), router.query, etc. |
| urlParams | { query, pathname, asPath } snapshot |
Global store
| Variable | Description |
|---|---|
| globalData | Cross-route global state (read) |
| setGlobalData(updater) | Write global state — shallow-merges by default |
Services
| Variable | Description |
|---|---|
| GetService | Authenticated GET |
| PostService | Authenticated POST |
| UpdateService | Authenticated PUT |
| PatchService | Authenticated PATCH |
| DeleteService | Authenticated DELETE |
| fetchReportData | Fetch report data by pageId (or by an inline builderModel). |
| getReportSource(localId) | Resolve an inline-authored report from the view schema's reportSources registry. Returns the builderModel or null. Pass to fetchReportData({ builderModel }) to skip the server fetch. |
Helpers
| Variable | Description |
|---|---|
| showToast(message, type?) | 'success' | 'error' | 'warning' | 'info' | 'loading' |
Parent page scope (inside dialogs / embedded views)
| Variable | Description |
|---|---|
| page.data | Parent page's reactive state |
| page.setData | Write to the parent page's state |
| page.dataRef | Parent page's non-reactive store |
| page.reportRefs | Parent page's grid refs |
Repeater-only
| Variable | Description |
|---|---|
| dataItem | The current repeated item |
| itemIndex | Zero-based iteration index |
KPI Component Actions
KPI components support interaction events configured in the inspector Main tab → Actions section.
| Component | Event | Click-context variables |
|---|---|---|
| Metric | onClick | clickedValue |
| Rating | onChange | newValue, clickedValue |
| Chart | onDataClick | clickedItem, clickedValue, clickedField, clickedLabel, clickedIndex |
| HeatmapGrid | onCellClick | clickedItem, clickedValue, clickedRow, clickedCol, clickedRowIndex, clickedColIndex |
| Timeline | onItemClick | clickedItem, clickedIndex, clickedLabel, clickedStatus, clickedValue |
| StepStage | onStepClick | clickedItem, clickedIndex, clickedId, clickedLabel, clickedStatus |
| TagList | onTagClick | clickedItem, clickedTag, clickedLabel, clickedValue, clickedIndex |
Global Data Store
A module-level reactive singleton that survives client-side navigations.
In Calculation functions
// Read
console.log(globalData.selectedUser)
// Write
setGlobalData(prev => ({ ...prev, selectedUser: clickedItem }))
// Navigate — globalData persists to the next page
router.push('/user-detail')In React components
import { useGlobalStore } from 'robobyte-front-builder'
function MyComponent() {
const { globalData, setGlobalData } = useGlobalStore()
return <p>Selected: {globalData.selectedUser?.name}</p>
}Resetting on logout
import { resetGlobalData } from 'robobyte-front-builder'
function handleLogout() {
resetGlobalData()
// ... your auth logout
}API
| Export | Description |
|---|---|
| useGlobalStore() | React hook — { globalData, setGlobalData } |
| getGlobalData() | Synchronous read from non-React code |
| setGlobalData(updater) | Write from anywhere |
| subscribeGlobal(fn) | Subscribe to changes — returns unsubscribe function |
| resetGlobalData() | Reset to {} and notify all subscribers |
Dark / Light theme
Both the UI Builder and Print Layout Builder support dark and light modes (default: dark). A toggle button (☀️ / 🌙) is available in each builder's toolbar. The choice is persisted in localStorage under rbb:builderThemeMode. The theme is scoped to the builder pages only and does not affect the rest of the host application.
Syncing local changes
When using file: path, node_modules/robobyte-front-builder is a copy, not a symlink. After editing source files, sync manually:
SRC=RoboByteFrontBuilder/src
PKG=YourApp/node_modules/robobyte-front-builder/src
cp $SRC/lib/index.js $PKG/lib/index.js
cp $SRC/lib/providers/RoboByteFrontBuilderProvider.jsx $PKG/lib/providers/RoboByteFrontBuilderProvider.jsx
cp $SRC/services/reportData/fetchReportData.js $PKG/services/reportData/fetchReportData.js
# ... add other files as neededHot-reload picks up all file changes automatically. Only next.config.js changes require a dev server restart.
Troubleshooting
"Module not found: Can't resolve 'xlsx'"
→ Install xlsx in the host app: npm install xlsx --legacy-peer-deps
"Cannot find module 'services/...'"
→ Ensure the NormalModuleReplacementPlugin is configured in next.config.js
AG Grid table not showing / license warning
→ Pass agGridLicenseKey to RoboByteFrontBuilderProvider. Do not call LicenseManager or ModuleRegistry in the host app.
AG Grid error #200 — IntegratedChartsModule not registered
→ The provider registers IntegratedChartsModule.with(AgChartsEnterpriseModule) automatically. Ensure ag-charts-enterprise is installed in the package.
AG Grid theme override not applying
→ Pass it via <RoboByteFrontBuilderProvider agGridTheme={{ … }}>, not as a theme={…} prop on individual <AgGridReact> instances rendered by the package. Internal grids ignore per-instance themes; the provider's context is the single source of truth. See the AG Grid theme section.
ReportViewer renders at half width
→ The outer Box in reportViewer/index.js must use display: 'block', not display: 'flex'.
Static props (getLayout, acl) not picked up from package exports
→ Use the explicit import + assignment pattern. Bare export { X as default } does not carry static properties across package boundaries.
Duplicate React / MUI hook errors
→ Pin react, react-dom, and @mui/material to the host app's copies via config.resolve.alias in next.config.js.
Old routes returning 404
→ Check that host-app pages exist under /builders/... and that old paths have getServerSideProps = () => ({ notFound: true }) stubs.
Publishing
npm login # one-time setup
npm version patch # 1.0.x — bug fixes
npm version minor # 1.x.0 — new features
npm version major # x.0.0 — breaking changes
npm publishDry run (verify what will be published without actually publishing):
npm publish --dry-runChangelog
1.0.29
- Inline report sources. The view schema gains a top-level
reportSourcesmap — a registry of inline-authoredbuilderModels addressable by shortlocalId. The<reportViewer>inspector gets a new "Source" picker that toggles between Saved (existingpageId/id) and Inline (registry-backed) modes. Authors create / edit sources via a fullscreen Report Builder Dialog that embeds the real/builders/reportpage withmode='dialog'+onSaveInline/onSaveServercallbacks. Resolution priority across the system: inlinebuilderModel>reportSourceId>pageId>id. All existing schemas continue to work unchanged. fetchReportDataByPageId({ builderModel }). New optional parameter that skips theGetReportDetailsfetch when an inline model is in hand. Used by the new viewer pipeline and exposed in Calculation code via the auto-injectedgetReportSource(localId)helper, which reads from a module-levelreportSourcesRegistrysingleton (BuilderProvider / ProductionViewer keep it in sync — same pattern asrouterRef).ReportSourcesManager. Small dialog (opened from the inspector or the sidebar's View tab) for renaming / duplicating / deleting registry entries, with in-use detection (counts every node referencing each source).- View tab → Report Sources section. Sources can also be authored from the sidebar's View tab, not only from a
reportViewerinspector. Useful for views whose only consumers are autocomplete-with-data fields or hand-coded calculations — you don't need areportVieweron the canvas to manage the registry. - New context API on
useBuilder().reportSources,generateReportSourceId(),setReportSource(localId, src),removeReportSource(localId),getReportSource(localId)— full registry CRUD that participates in undo/redo throughsetSchema.
1.0.25
- Centralized AG Grid theme. Every
<AgGridReact>in the package (reportViewer,dataGrid, role-permission editor, navigator picker) now reads its Quartz theme from a single context. Host apps can override package-wide theme params (accent color, header height, fonts, border radius, etc.) via the newagGridThemeprop onRoboByteFrontBuilderProvider. Defaults live insrc/lib/agGridTheme.js. New exports:DEFAULT_AG_THEME_PARAMS,DEFAULT_AG_THEME,buildAgGridTheme,AgGridThemeProvider,useAgGridTheme. <ReportViewer>redesigned toolbar. Single-row toolbar: title + caption on the left; collapsible search, Filter (outlined button), Refresh (outlined button), and configurable viewer actions on the right. Auto-refresh interval, "Load all data" toggle, and Excel export moved into the side tool panel under Display Settings. Search popover navigable by keyboard (↑ ↓ Home End Enter Esc).<ReportViewer>new inspector fields.title,caption,viewerActions(array of page-level action buttons appended after Filter/Refresh),debug(renders a floating bug icon with a popover showing resolvedpageId/id/builder model id/etc. — hidden in production by default).- Print Layout integration. Host apps can now trigger print layouts directly via the imperative
PrintDialogref API — see docs/printLayout.md for the recommendedPrintProviderpattern withusePrintLayout(). - Public exports expanded.
fetchReportDataByPageIdnow exported from the package surface (import { fetchReportDataByPageId } from 'robobyte-front-builder'); the legacy bare-alias path still works. - Unsaved changes guard. Builder pages now warn on tab close / refresh / in-app navigation when the schema has unsaved edits.
BuilderProviderexposesloadSchema(schema)(clears history baseline),markClean()(post-save reset), andisDirty. - Session log + AI fine-tune pipeline. Every successful save (UI Builder + Print Builder) is auto-logged to localStorage with the full schema. New Session Logs toolbar dialog lets developers add training prompts to entries and export a Together AI-ready JSONL. Together is now a first-class AI provider in
/api/ai.
1.0.21
- Added Timer Engine — configurable auto-refresh timers per view
- Added full Undo / Redo history with keyboard shortcuts (Ctrl+Z / Ctrl+Y)
- Added Cut / Copy / Paste with system clipboard support (Ctrl+X / Ctrl+C / Ctrl+V)
- Added Undo / Redo buttons to the viewer toolbar
- Expanded KPI suite: Gauge, BulletChart, ColorScale, Rating, Countdown, AvatarGroup, StepStage
- Print Layout designer: multi-zone canvas,
@pageCSS, print dialog
1.0.20
- KPI components: Metric, Trend, Badge, StatusDot, IconBox, Sparkline, MiniBarChart, Donut, Funnel, HeatmapGrid, TagList, Timeline, ComparisonBars
- Threshold engine and number formatting utilities
- Dark / light theme toggle in UI builder and Print Layout builder
1.0.x
- UI Builder, Report Builder, Navigator Builder, Print Builder initial releases
- Navigation Extension API
- AG Grid and MUI data grid integration
- Drag-and-drop canvas with 50+ components
- Global Data Store
License & third-party components
robobyte-front-builder itself is released under the MIT License — the source code in this repository is free to use, modify, and distribute, including in commercial products.
Important: this package depends on third-party libraries with their own licenses. The MIT license applies only to this package's source code; it does not relicense or waive obligations under those third-party licenses.
AG Grid Enterprise — commercial license required for production
The report and grid components use AG Grid Enterprise features (server-side row model, side tool panel, status bar, integrated charts, master/detail). The ag-grid-enterprise package is a commercial product owned by AG Grid Ltd:
- Development: AG Grid Enterprise works without a license key, but renders a watermark and prints a console warning. Fine for local dev and evaluation.
- Production deployment: requires a paid AG Grid Enterprise license. See ag-grid.com/license-pricing for the current terms.
Pass your license key via the provider — the package calls LicenseManager.setLicenseKey() and registers AllEnterpriseModule + IntegratedChartsModule.with(AgChartsEnterpriseModule) internally:
<RoboByteFrontBuilderProvider
agGridLicenseKey={process.env.NEXT_PUBLIC_AG_GRID_LICENSE_KEY}
// …other props…
>
…
</RoboByteFrontBuilderProvider>MUI X — free vs. Pro / Premium tiers
@mui/x-data-grid, @mui/x-date-pickers, and related packages have a free MIT tier and paid Pro / Premium tiers. This package uses only the free tier. If you swap in @mui/x-data-grid-pro or @mui/x-date-pickers-pro in your host app, comply with MUI's commercial license: mui.com/pricing.
Everything else
All other runtime and peer dependencies are open-source under permissive licenses (MIT, Apache 2.0, ISC, BSD). Run npm ls --omit dev for the full dependency graph and a tool like license-checker for a license enumeration.
A condensed version of this notice lives in the LICENSE file shipped with the package.
Full user manual: RoboByteBuilder_User_Manual.docx (included in the package)
