
Updated June 18, 2026 by Sunny Chauhan.
For years, the only way to surface your data inside HubSpot was an iframe in a CRM card. Slow, ugly, broken on mobile, no native UI components. HubSpot's UI Extensions framework (which became GA in 2024 and got a major capabilities expansion in 2026) changes that. You can now render React components inside HubSpot's CRM record sidebar, in deal previews, on Home Pages, and inside workflow actions. They look native because they use HubSpot's design system. They work because they run on HubSpot's CDN. And they're a Marketplace differentiator most apps still don't use. Here's the build flow and the architectural decisions that matter.
Pro Tip
TL;DR HubSpot UI Extensions let you render React components inside HubSpot's UI, with built-in components from HubSpot's design system. App Cards (a UI Extension type) appear on CRM record pages. The framework also supports workflow actions, Home Page cards, and deal previews. Build with the HubSpot Developer Projects CLI:
hs project create→ write React with the@hubspot/ui-extensionspackage →hs project uploadto deploy. Your extension can call your backend API for data and use HubSpot'sserverlessfunctions for trusted operations. App Cards are an underused Marketplace differentiator in 2026.
What UI Extensions actually are
A UI Extension is a React component that HubSpot renders inside their own UI. Not an iframe. Not a popup. An actual component using HubSpot's design system primitives, deployed to HubSpot's infrastructure, that talks to your backend on the customer's behalf.
Three concrete things you can do:
→ Render an App Card on a CRM record. When a user opens a Contact, Deal, or Ticket, your card appears in the sidebar. You decide what it shows.
→ Render a workflow action. When a customer builds a workflow and adds your action, the configuration UI for that action is your React component.
→ Render on Home Pages. Custom widgets on a user's HubSpot Home dashboard.
A UI Extension has access to:
1/ HubSpot UI components. Buttons, tables, links, forms, panels. They look native because they are native.
2/ The CRM context. The current record id, properties, associations. Your component receives them as React props.
3/ A serverless function execution environment. For operations that need authenticated API access without exposing tokens to the browser.
4/ HubSpot's design tokens. Colors, spacing, typography. Your card looks like HubSpot, not like a 2014 iframe.
When to build a UI Extension instead of skipping the UI
Three patterns where UI Extensions earn their place:
→ Your product's data is the most useful piece of context on a CRM record. Conversation intelligence, account intelligence, billing status, contract status. The user lives in HubSpot; bringing your data into their existing view beats making them switch tabs.
→ You want to be the action surface, not just the data surface. A button that triggers your workflow from inside HubSpot. A form that creates something in your product without leaving HubSpot. Action surfaces have higher engagement than read-only data surfaces.
→ You're listing on the Marketplace and want a differentiator. Most listed apps still don't have UI Extensions. The Marketplace listing for an app with native in-HubSpot UI lands differently than one with "connects via API" as the visual.
Patterns where skipping the UI Extension is fine:
1/ Your integration is purely data-flow (sync only, no in-HubSpot interaction needed).
2/ Your app's primary surface is your own web app and the HubSpot connection is a side feature.
3/ You're shipping v1 fast and want to add UI later. Sequencing is OK; just don't ship "API-only" and never come back to it.
The build flow
UI Extensions are built using the HubSpot CLI and the Developer Projects framework. Five steps to a working extension.
1/ Install the CLI and authenticate
``bash npm install -g @hubspot/cli hs init hs auth ``
The hs auth command opens HubSpot in your browser, asks you to log into your Developer Account, and stores credentials locally.
2/ Create a project
``bash hs project create ``
The CLI prompts you for a project name and a starter template. Pick the "App + UI extension" template for the basics.
The project directory contains:
hsproject.json: project configapp.json: app metadata (scopes, name, etc.)extensions/: where your UI Extensions liveserverless/: where your serverless functions live (optional)
3/ Write the React component
A minimal App Card component:
```javascript import React from 'react'; import { Divider, Link, Text, Heading } from '@hubspot/ui-extensions'; import { hubspot } from '@hubspot/ui-extensions';
const ContactInsightsCard = ({ context, runServerlessFunction }) => { const contactId = context.crm.objectId;
return ( <> <Heading>Your Product Insights</Heading> <Text>Contact ID: {contactId}</Text> <Divider /> <Link href="https://yourdomain.com/contacts/{contactId}"> Open in Your App </Link> </> ); };
hubspot.extend(({ context, runServerlessFunction }) => ( <ContactInsightsCard context={context} runServerlessFunction={runServerlessFunction} /> )); ```
Three things to notice:
1/ You import primitives from @hubspot/ui-extensions. These are HubSpot's native components. They render with HubSpot's design system automatically.
2/ The context prop gives you the current CRM context: context.crm.objectId is the contact id, context.crm.objectTypeId tells you it's a contact.
3/ runServerlessFunction is how you call your serverless functions for authenticated backend operations.
4/ Add a serverless function (when needed)
If you need to call your backend API with the customer's OAuth token, you go through a HubSpot serverless function. The token never touches the browser.
```javascript // serverless/fetchInsights.js exports.main = async (context = {}) => { const { hs_object_id } = context.parameters;
// Call your backend with the customer's API access const response = await fetch( https://api.yourdomain.com/insights/${hs_object_id}, { headers: { 'Authorization': Bearer ${process.env.YOUR_API_KEY} }} );
return await response.json(); }; ```
Your React component calls it via runServerlessFunction({ name: 'fetchInsights', parameters: { hs_object_id: contactId }}).
5/ Upload and test
``bash hs project upload ``
This pushes your extension to HubSpot's CDN. Open a record in your sandbox and your App Card appears in the sidebar.
Iterate locally with hs project dev for hot-reload during development.
App Card placement: where they appear
UI Extension cards can target several locations in HubSpot's UI:
→ CRM record sidebars (Contact, Deal, Ticket, Custom Object). Your card appears next to the standard sidebar properties.
→ Deal previews. Inline cards on the deal board hover preview.
→ Home Page cards. Widgets on a user's HubSpot Home dashboard.
→ Inside workflows. As the configuration UI for a workflow action.
You declare placement in your extension's metadata file. One extension can target multiple placements.
Common gotchas
Three things I see trip people up:
1/ Forgetting that the browser context has no OAuth token. If your component tries to call your backend with the user's HubSpot token, it won't work. Use a serverless function with your own backend's API key. The customer's HubSpot OAuth token lives server-side only.
2/ Building outside the design system. You import primitive React components from @hubspot/ui-extensions. If you import from @mui/material instead, your card looks like Material UI in the middle of HubSpot. Bad UX, certification will note it.
3/ Loading slow. UI Extensions must render quickly or HubSpot times out. Don't make blocking API calls before first paint. Show a skeleton or a loading state, fetch async, render data when ready.
How this maps to Salesforce-side experience
For Salesforce ISVs, the closest analogy is Lightning Web Components (LWC) embedded in a Managed Package. Both render native-looking components inside the customer's CRM UI. Both use the platform's design system (HubSpot UI Extensions vs SLDS for Salesforce). Both can call back to your serverless infrastructure.
The differences: → LWC runs entirely on Salesforce's infrastructure; UI Extensions are React components running in a HubSpot-hosted iframe but with native-style API. → Salesforce LWC has licensing gotchas you have to handle manually; HubSpot UI Extensions tie permission to your app's OAuth install.
At Appnigma we generate 2GP Managed Packages that include LWC components built to AppExchange standards. The equivalent for HubSpot is a UI Extension that renders cleanly in any customer's HubSpot, respects the design system, and degrades gracefully if data is unavailable.
Pre-flight checklist before shipping a UI Extension
[ ] HubSpot CLI installed and authenticated → Yes / No
[ ] Project created via
hs project create→ Yes / No[ ] Extension uses only
@hubspot/ui-extensionsprimitives (no foreign design systems) → Yes / No[ ] Serverless function used for backend calls (token never in browser) → Yes / No
[ ] First paint renders in under 1 second (skeleton + async load) → Yes / No
[ ] Extension placement targeted to relevant CRM records → Yes / No
[ ] Tested in a sandbox with realistic data → Yes / No
[ ] Tested with no data state (new install, empty CRM) → Yes / No
[ ] Tested with stale data or backend down → Yes / No
Real-world scenario: a revenue intelligence ISV adds an App Card
A revenue intelligence product (Avoma-analog) had a HubSpot integration that synced meeting summaries to deal records. Reps had to click into the Avoma web app to read the summaries. Engagement was low.
They added a UI Extension App Card on the deal record sidebar. The card showed: → The 3 most recent meetings on this deal → A summary excerpt for each → A "View Full Summary" button that opened Avoma in a new tab → A "Generate Email Follow-up" button that triggered an action in Avoma
Two weeks after launch, engagement with the summaries jumped from 12% of synced records to 67%. The card made the data visible at the moment of need rather than buried in another app.
The Marketplace listing also benefited: the screenshots now showed a native HubSpot deal record with the Avoma card embedded. Visually different from competing apps that showed "we sync data" without UI.
Frequently Asked Questions
What is a HubSpot App Card?
A HubSpot App Card is a UI Extension that renders on a CRM record page (Contact, Deal, Ticket, Custom Object). It's a React component built with HubSpot's design system that shows in the record sidebar, looks native, and can call back to your serverless functions for data (HubSpot Developers, UI Extensions documentation).
What is the HubSpot UI Extensions framework?
A framework that lets ISVs build React components that render inside HubSpot's UI. Released GA in 2024, expanded significantly through 2026. Supports App Cards (on CRM records), Home Page widgets, deal previews, and workflow action configurations. Components use HubSpot's design system primitives.
How do I build a HubSpot UI Extension?
Use the HubSpot CLI: hs project create, write React using @hubspot/ui-extensions components, optionally add serverless functions for authenticated backend calls, then hs project upload to deploy. The starter template handles project structure setup.
Does my UI Extension run on HubSpot's servers or mine?
Your React component runs in the customer's browser, hosted on HubSpot's CDN. Your serverless functions run on HubSpot's infrastructure. Your backend API (where your actual product lives) runs on your servers. The pattern keeps the customer's OAuth token server-side and routes data through your authenticated backend.
Can I use my own design system in a HubSpot UI Extension?
Strongly discouraged. The framework expects you to use @hubspot/ui-extensions primitives so your card looks native. Mixing in another design system breaks the visual coherence and certification review will note it.
What CRM record types support App Cards?
Contacts, Deals, Tickets, and Custom Objects. The placement is declared in your extension's metadata file. One extension can target multiple record types.
Are HubSpot UI Extensions required for Marketplace certification?
No. They're optional. But they're a meaningful differentiator in 2026 because most listed apps don't use them yet. If your product surface naturally benefits from in-HubSpot UI, building one increases install rate and engagement.
About the author
Sunny Chauhan is the founder and CEO of Appnigma AI, a no-code platform that generates Salesforce AppExchange-ready Managed Packages from natural-language prompts. He holds Salesforce certifications in Platform Developer II, Platform App Builder, Administrator, Data Cloud Consultant, and AI Associate. Appnigma generates Salesforce Lightning Web Components inside Managed Packages with proper license enforcement and SLDS design system compliance; the architectural patterns transfer to HubSpot UI Extensions.
Originally published June 18, 2026. Last reviewed June 18, 2026. UI Extension capabilities verified against HubSpot's UI Extensions documentation and Marketplace listing patterns current as of the published date.
Related articles
Sources
1/ HubSpot Developers, UI Extensions Overview 2/ HubSpot Developers, Building Your First UI Extension 3/ HubSpot Developers, UI Components Reference 4/ HubSpot Marketplace Certification Requirements
What's the moment in your customer's HubSpot workflow where your data would be the most useful thing to see?
Ready to transform your Salesforce experience?
Start exploring the Salesforce Exchange today and discover apps that can take your CRM efficiency to the next level.
