https://www.youtube.com/watch?v=Y_YayvH0dAE

Tutorial on building custom React apps for HubSpot CRM using UI extensions. Learn to create components, integrate APIs, and deploy a Global Contact Availability app card directly into HubSpot.
Ever wondered how to build and embed custom react apps directly into your HubSpot CRM that don't just work, but look and feel seamlessly? Native HubSpot's UI extensions make it possible, and I'm going to show you exactly how to create the user interface for an app card that fits right in this is the fourth video in our series of building a custom public app card with HubSpot's UI extensions from scratch. In the previous videos, we've covered setting up our project and initializing our public app card building, then securely installed it by diving deep into OAuth and finally built and deployed our next JS backend, complete with powerful API endpoints. In this video, we're going to bring all of those components together in our Global Contact Availability card. We'll explore helpful design tools to plan our card's layout, then build the UI using HubSpot's UI components. We'll integrate the Contact availability logic from our next JS backend using HubSpot folder, and finally deploy our Production Ready UI extension card directly into the HubSpot CRM. Before we hop into creating the card itself, let's go back for just a quick second. In the last video, we used Next JS API routes to create and expose our own API to help us tackle a tricky problem trying to figure out when the best time to call a contact Is. We use two APIs to compose an endpoint that delivers the current date and time for a contact, their availability free or otherwise, and upcoming public holidays, all based on a contact's location. We want to use this data to create create our public app card on a contact record within the HubSpot CRM. So how do we go from having an idea to execution? If you're anything like me, you need to have a visual of what you're trying to build before you actually start diving into code. Thankfully, there are two design tools for HubSpot's UI extensions that are going to help us with this. These tools don't just make it easy for us as developers to plan and design before coding. They also make it easy to collaborate with your colleagues who prefer not to dive into code. The two tools we'll discuss today are both used in figma, which is a collaborative design and prototyping tool. The first tool is going to be the HubSpot Figma Design Kit. This kit is a visual representation of the UI components that you can use to create app cards with UI extensions. It also contains visual examples, high level design information, and a breakdown of a card's anatomy and examples based on their location. This design kit is particularly useful when needing to share demos or keep teams aligned during the development process. Want to learn more about it? Check out this video by Brooke, who is another one of our amazing developer advocates all about using the HubSpot Figma Design Kit the next tool is the HubSpot Developers UI Extensions AutoCard Builder. This is a Figma plugin that allows you to prototype UI extensions in an instant. This plugin allows you to view the list of available UI components, select how many you need, and then it scaffolds the card for you. Almost like magic. Once the card has been generated, you can reorder components and customize them to your needs. Brook also created a super handy video for how to use this one as well. I've used Figma to create a mockup for our card and it has a few main components. The first is a header with the contact's name. Next we'll move on to the Local Information section to display their location, local time and availability status. Moving on, we have the Holiday Alert section which will show any upcoming public holidays within the next 30 days. And finally we have our Recommendation status. Now that we have our data in a clear direction of where we're going, let's jump into the editor and create our App card in the Contact Availability directory. Currently we just have our example card, but we want to create a new card for our Contact Availability card. In order to do that we need to create and update a few different files. First we need to create the REACT based UI extension. This is going to be a JavaScript or TypeScript file and the naming convention is going to be to give it a card name card JSX or TSX depending on if you're using JavaScript or typescript and this file is going to be the entry point for our card. It's important to note that even though this is a react based component, HubSpot's UI components must be used. You won't be able to add your own HTML elements or custom CSS. The important piece here is going to be importing HubSpot from the HubSpot UI extensions library and using HubSpot extend to serve our component. For now, we'll add a simple message and come back to this file. Next we need the JSON file that contains the metadata about our REACT extension. This file is going to be a JSON file of the same name but using Kebab casing. Here we want to define the title of our card, give it a unique UID set its location, which is a record tab, or otherwise tell it where to find our react component, and finally define the object type that the card can be used on. Lastly, once we have those two new files, we're going to head over to the public app JSON. In the Extensions CRM Cards array, we're going to add a new file that points to the JSON file we just created that contains the metadata for our extension. Now that we have our new files in place and an updated public app JSON, we're going to need to upload these changes to HubSpot and start our local development server. If you haven't already done so, I recommend watching video two in this series where we covered OAuth and installed the app card onto a contact record to understand how we got to this point. In your terminal, use hsproject Upload to upload the updates to our project, and then we're going to use hsproject dev to start the local development server. Then we're going to navigate to a developer test account to add the new card to a contact record. Then we should see the local development flag next to the name of our card. Now let's head back to our editor. Off camera, I've scaffolded a static version of the Global Contact Availability card. First, let's talk about two optional parameters we can pass to our Extension Context and Actions. Context provides data related to the authenticated user and the HubSpot account, along with data about where the extension was loaded. This object is where you can retrieve information like the object type and id, portal ID and data, as well as user information like the first name and locale. Actions is going to make actions available to our UI extension. This includes actions such as fetching CRM property data, which we will will do shortly, displaying alert banners, opening overlays, and more. There's so much you can do with the UI Extensions SDK, so if you've never had a peek at the docs, I highly recommend checking them out. I'll leave a link to the docs in the description below, and if there's anything that you see that you think we should cover here, let us know in a comment. Now let's pass actions to our extension. We're going to utilize the Fetch CRM object Properties action to retrieve the contact's name and location. We're going to use a simple usestate to store the name and a use effect to call the function to grab the property for us. Then once we have the property, we'll set it accordingly. In our header. When we save and take a look at the ui, we can see that our static and temporary placeholder has now been replaced by our contacts name. We're also going to want to grab our Contact city, state and country in order to call our Contact Availability API. In order to use the API that we created in the last video with next JS API routes, we need to use the HubSpot fetch API. But before we do so, there's one small tweak we have to make in order to whitelist the URL for our project configuration. Let's open PublicApp JSON one more time, and this time we're going to be looking at the allowed URLs array. This is where you can go about adding an endpoint for our new API. URLs that are not included in this array cannot be requested by the extension. So for my instance I will add the base URL for my project. Now what if you're still developing your API or you want to be able to use a local version? You can set up a proxy to remap the HubSpot fetch request made during local development. You'll configure this through the local JSON file, and just note that this will initially be called Local JSON sample. Now that we've whitelisted our API endpoint either via the allowed URLs array or the local proxy, we can use HubSpot fetch to call it. Now let's talk about how we're going to handle this. I've set up a few pieces of state to store the name and location that we receive from FetchCRM, object properties, the availability data that we receive from our API, and a piece of state to handle any errors that we may encounter along the way. I've also created a few types to help out with our API response as well. We want to fetch our data from HubSpot and also from the Contact Availability API when the component loads. So for simplicity, for this card we'll use a useeffect that's only called once. First we need to retrieve the name and location properties. We're going to use the Fetch CRM object properties to fetch four properties for the name, city, state, and country for the contact. Then, based on the response from HubSpot, we'll return early and show an error state if the first name, city, or country are missing in our response. State is useful, but it is not required for the purposes of our API, so we can still retrieve availability even if it's missing. Next, we want to store the name and location that we retrieve. Then we need to build the URL we're going to pass to HubSpot fetch to gather availability. This is going to be based on the pieces of information that we've gathered so far. Next, you're going to want to actually call HubSpot Fetch with our composed URL. We're going to be using the Get HTTP method by default, but you can also pass options to fetch that include the method timeout in Request Body. Now all that's left is to parse the response and store in a state variable and use that in just a moment. Now that we have the data from the Global Contact Availability API, it's time to replace our static data. Let's start with our location section. Status has four possible options in office, public holiday, weekend and off hours to give a visual understanding of status. I've used the Status tag component and have the variant prop set to Success for In Office and Danger for all others. Now we'll update the location in our description list with the location that we received from HubSpot. Lastly, we'll concat the pieces of our date, time and time zone together. So if we have a look at this for a few different contacts, we can see that Brie is in the Eastern time zone, so she's in office, but it's quite late or very early for both Esme and Elizabeth. Now let's tackle the array of upcoming holidays. We'll simply map through the array of holidays coming up in the next 30 days and display them in an unordered list. And if there are no holidays coming up, we'll show that as well. The last thing to replace is the string for the recommendation. Then we'll have a fully dynamic and functional app card that gives us the location, date and time and call availability for a contact. Now, just be sure to run HS project upload to ensure that your changes persist. Now we've created a full stack public app card with HubSpot's UI extensions. We've created our HubSpot project, explore the development settings and tools, configured secure OAuth and even deployed our own backend with next JS API routes. Finally, in this video we have put all the pieces together, but I want to hear from you. What are the ways that you think we could extend the functionality of this card? A few ways that come to mind for me immediately are using bidirectional data refresh to make sure that the card updates when a location is changed on a record, or maybe updating the time zone fields on the CRM based on the response from our API, even being able to use a custom property like Call preferences and taking that into account when providing the call recommendation. But what do you think that we should do next for this project? Let me know in the comments below for the docs GitHub repo with all the code for this project and more. Be sure to check out the description below to make sure that you're in the know for videos like these and others for HubSpot developers. Make sure that you're subscribed and have notifications turned on so you'll be the first to know when a new video drops. Until next time.










