Customization · Setup
Component Library
Build Your Own Widgets, Safely
How to add a small custom panel to a record page — like a lead score summary — without a developer ever touching the CRM's core code.
About & Business Case #
Why "just add one small widget" is usually hard #
"I just want a little box on the Lead page showing our lead score and a quick summary. I don't need a whole new feature, and I definitely don't want to file a request with engineering just for that."
A "widget" is a small, self-contained panel of information, like a little box on a page. These small, page-specific widgets are too minor for a full engineering project, but too custom for the standard record layout — the normal arrangement of fields on a page.
Admins need a safe way to add their own mini-panels, without any risk of breaking the rest of the CRM, or seeing data they shouldn't.
What you'll be able to do
Admins can build small custom panels for record pages themselves, in minutes — with guardrails that stop a widget from ever seeing more of a record than it's explicitly allowed to.
Implementation #
One HTML file, a sandbox, and a field allowlist #
A Custom Component is a single, self-contained HTML file — with its styling (CSS) and behavior (JavaScript) built right in, no separate files needed. You pick which CRM object it attaches to. Then you explicitly check which fields it's allowed to read, and which of those it's also allowed to write back to.
SmartLiteComponent.getRecord() to read the record and updateRecord(fields) to write to it — never a direct database or API call.Only checked fields are visible
Any field you don't explicitly mark as Readable is completely invisible to the component. It isn't just hidden on screen — the component genuinely cannot see the rest of the record.
1 Build a simple Lead sidebar widget #
2 Give a widget real logic: call a Custom Class #
A widget isn't limited to just showing its own record's fields. It can also call a Custom Class — the same governed-script primitive covered in the Custom Classes & Pages trail — to fetch or compute anything else it needs, using SmartLiteComponent.callClass(apiName, params) from inside the component's own JavaScript, exactly the way a Custom Page does.
SmartLiteComponent.getRecord() always includes the current record's own ID (as id) alongside whatever fields you checked Readable — so the widget can pass that ID straight into a Custom Class that looks up Contacts for it.listAccountContacts reads the Account ID from PARAMS, queries Contacts with CRM.query('contact', 'account_id', PARAMS.accountId), and returns the list.SmartLiteComponent.getRecord().then(r => SmartLiteComponent.callClass('listAccountContacts', { accountId: r.id })), then render the returned list as a table.How to Use #
Day-to-day: reps viewing the record #
Day-to-day: admins #
What to try next
Look at the Custom Classes & Pages trail to write the Custom Classes your widgets call for real logic — cross-object lookups, calculations, anything beyond the widget's own bound record.
Quiz #
Test what you learned #
SmartLiteComponent.getRecord() always includes the record's own id, which the widget passes into a Custom Class via callClass