A low-code UI Builder, Report Builder, Print Layout Designer, and Navigation Extension API for Next.js applications.
| 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.
- What's included
- Requirements
- Installation
- Peer dependencies
- next.config.js setup
- Provider setup
- Builder pages
- Navigation Extension API
- Provider props reference
- AG Grid 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
- 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
| Dependency | Version |
|---|---|
| Node.js | ≥ 18 |
| React / React DOM | ≥ 18 |
| Next.js | ≥ 13 |
| @mui/material | ≥ 7 |
| AG Grid | ≥ 33 |
npm install robobyte-front-builderOnly 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.
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.
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' }}
>
{children}
</RoboByteFrontBuilderProvider>
)
}
export default function App({ Component, pageProps }) {
const getLayout = Component.getLayout ?? (page => page)
return (
<YourAuthProvider>
<RoboByteBridge>
{getLayout(<Component {...pageProps} />)}
</RoboByteBridge>
</YourAuthProvider>
)
}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 |
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 ReportViewerimport { 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 = false<RoboByteFrontBuilderProvider
navExtensions={[
{
id: 'host-analytics',
title: 'Analytics',
icon: 'ChartBar',
type: 'static',
path: '/analytics',
insertAt: 'end',
},
]}
>
...
</RoboByteFrontBuilderProvider>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
}| 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 |
| 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. |
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.
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:
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.
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.
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.
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)
}const filter = {
customFilterCode: `
if (authContext?.user?.shopId) {
customFilter.push({ field: 'ShopId', value: authContext.user.shopId, operation: 'Equal' })
}
`
}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 |
The Data Grid wraps AG Grid Enterprise and is configurable entirely from the builder inspector.
| 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 |
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 instanceRenders a hidden MUI Dialog opened programmatically via openDialog(key) / closeDialog(key).
| 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 |
// Open with optional seed data
openDialog('confirmDelete')
openDialog('editUser', { userId: row.id, name: row.name })
// Close
closeDialog('confirmDelete')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 }))A self-contained trigger (button, icon button, or text) that opens a floating panel. No openDialog call needed.
| 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 |
Lets users upload .xlsx, .xls, or .csv files, map columns to field names, and access the result in actions.
| Variant | Description |
|---|---|
dropzone |
Large dashed drop zone with drag & drop |
button |
Compact outlined button |
icon |
Icon-only button |
| 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 |
const uploader = reportRefs['myUploaderKey']
uploader.rows // current mapped rows
uploader.setRows(arr) // replace stored rows
uploader.clear() // clear all stored rowsA MUI Stepper with optional validation, async lifecycle hooks, and controlled or uncontrolled step state.
| 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 |
| 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) |
goToStep(n) // jump to step n (0-based)
nextStep() // advance one step
prevStep() // go back one stepRenders 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 |
| Variable | Value |
|---|---|
dataItem |
The current array element |
itemIndex |
Zero-based item index |
form[key] |
The current item's scoped form value |
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 |
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' |
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 |
Renders a MUI Breadcrumbs navigation trail.
{
"type": "breadcrumb",
"props": {
"main": {
"items": {
"valueType": "value",
"value": [
{ "label": "Home", "href": "/" },
{ "label": "Reports", "href": "/reports" },
{ "label": "Q1 2025" }
]
}
}
}
}
⚠️ Preview — needs more testing. Functional but not production-ready.
Design reusable print layouts with configurable headers, footers, multi-page bodies, watermarks, and page numbering.
| 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 |
openPrintLayout('your-layout-id', {
invoiceNumber: data.invoiceNumber,
customerName: data.customer.name,
lines: data.lines,
})Use {page} and {pages} tokens in the Format field:
Page {page} of {pages} → Page 1 of 4
Every Calculation function receives the same set of variables:
| 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 |
| 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 |
| Variable | Description |
|---|---|
router |
Next.js router — router.push('/path'), router.query, etc. |
urlParams |
{ query, pathname, asPath } snapshot |
| Variable | Description |
|---|---|
globalData |
Cross-route global state (read) |
setGlobalData(updater) |
Write global state — shallow-merges by default |
| Variable | Description |
|---|---|
GetService |
Authenticated GET |
PostService |
Authenticated POST |
UpdateService |
Authenticated PUT |
PatchService |
Authenticated PATCH |
DeleteService |
Authenticated DELETE |
fetchReportData |
Fetch report data by pageId |
| Variable | Description |
|---|---|
showToast(message, type?) |
'success' | 'error' | 'warning' | 'info' | 'loading' |
| 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 |
| Variable | Description |
|---|---|
dataItem |
The current repeated item |
itemIndex |
Zero-based iteration index |
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 |
A module-level reactive singleton that survives client-side navigations.
// Read
console.log(globalData.selectedUser)
// Write
setGlobalData(prev => ({ ...prev, selectedUser: clickedItem }))
// Navigate — globalData persists to the next page
router.push('/user-detail')import { useGlobalStore } from 'robobyte-front-builder'
function MyComponent() {
const { globalData, setGlobalData } = useGlobalStore()
return <p>Selected: {globalData.selectedUser?.name}</p>
}import { resetGlobalData } from 'robobyte-front-builder'
function handleLogout() {
resetGlobalData()
// ... your auth logout
}| 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 |
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.
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.
"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.
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-run- 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.
- 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
- 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
- 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
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.
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-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.
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)