Jepsometer 3k

Building a custom card

HubSpot Admin HUG

yell loudly if you can see my screen

Hi, I'm dennis

Developer Advocate at HubSpot

Follow me for 1-2 posts per month on Linkedin

If you find HubSpot developer topics interesting,
subscribe to the HubSpot Developer YouTube channel

And dont forget about the DHUG!

what is our goal?

From here

to here

You will have questions?

and it is ok to not know the answer

I do not know how a pc works

I am going to build this with you

resources

This is a collection of resources to help you on your way

what is a custom card and how is it different from a CRM Card?

Table of contents

getting our workspace setup

There are several things we need to have set up before we can begin. To help out. I created a video detailing this part.

Installing a sample custom card

HubSpot has several sample custom cards built for you to explore. They provide a great way of reverse engineering the process as well as demosntrating some best practices. With the HubSpot CLI that has been authenticated with your account, you can install a sample custom card with easily.

On your desktop, create a new folder called Samplecard. If you are using VSCode, you can use the HubSpot extension to authenticate your project with your HubSpot account. Then navigate to this folder in your terminal. In your terminal, run the following command.

					
						hs project create --templateSource="HubSpot/ui-extensions-examples" --location="multi-step-flow"
						--name="multi-step-flow" --template="multi-step-flow"
					
				

Local Dev Setup

I believe it is important to get comfortable with the terminal so I will demonstrate creating folders and files in the terminal.

In the next slide, we will use the terminal to create all of the folders and files for the initial setup. The files will be empty at this point. We will go back and pour in the code in later steps

A completed version of the project we are building can be found here

Local Dev Setup | structure

First, create a folder called jepsometerProject on your desktop. Then navigate to this folder in your terminal

Now that we are in the folder we will be using, let's initialize the HubSpot CLI so that it can communicate with your account

The following command will guide you through authenticating the HubSpot CLI with your account. When you are done, you will have a hubspot.config.yml file in your folder


						hs init
					

Next step is to create a project which will act as the container for our app in our account. The CLI will ask you a series of questions including name of the project, location and if you want to use a template. Call your project jepsometer and choose the default location and no template


						hs project create
					

This will create a new folder called "src" and a hsproject.json file

Local Dev Setup | Optional package.json file

This file is optional, but will make your life slightly easier as you won't have to navigate to other directories to install dependencies.

From your terminal and still in the main folder, type this command

						
						cd jepsometer && touch package.json
						
					

local dev setup | private app

UI extensions require a private app to function. A single private app can be used for multiple custom cards

From your terminal and still in the main folder, type the following command


						cd src
						

						mkdir app && cd app
						

						touch app.json
					

local dev setup | extensions

We are are now at the meat of the project. The extensions folder we are about to create is where we will be building the custom card. For a custom card to work, it needs to in the extensions folder and it requires a minimum of 3 files.

  • custom-card.json
  • CustomCard.jsx or CustomCard.tsx
  • package.json

Although a custom card requires a package.json file, this file can be shared amongst multiple cards

local dev setup | extensions

Lets create our extensions folder and the files in it

From within the app folder, run the following commands in your terminal


										mkdir extensions && cd extensions
										

										touch associated-deals.json
										

										touch AssociatedDeals.jsx
										

										touch package.json
										

local dev setup | serverless functions

On its own, the front end of the custom card is very powerful and can display a wealth of data about the record it is on and its associations, but if you want to dig deeper into your CRM or if you want to interact with data outside of your CRM, serverless functions are the next step.

In this demo, we will be calling a serverless function to interact with a HubDB table hosted on a different HubSpot account. This hubdb table will control how a website page displays data.

Serverless functions are stored in a folder called app.functions and, similar to the custom card, require 3 files. If we will be making authenticated API calls, we will also need a .env file to store secrets. More on that later

  • functionName.json
  • serverless.json
  • package.json

local dev setup | serverless functions

Let's create the app.functions folder and the files in it

Again, in your terminal, we will need to navigate out of the extensions folder and back into the app folder. The we will create the new folder and files in the new folder

From within the app folder, run the following commands in your terminal


															cd .. && mkdir app.functions && cd app.functions
															

															touch thanksKyle.js
															

															touch serverless.json
															

															touch package.json
															

															touch .env
															

Pouring in the content | our optional package.json file

You should now have the structure set up for your custom card. Right now, everything is empty. Let's get to pouring in some content!

Remember that optional package.json file we created at the beginning? We are going to use this so we can run the scripts in the extensions and app.functions package.json file.
Open up the package.json file located at the top level of your project in your code editor and add the following

					
					
				

Pouring in the content | Private App

As mentioned earlier, a custom card requires a private app. To create a private app, we are going to fill in the data in the app.json file located in the app folder

					
					
				

Pouring in the content | Custom Card | associated-deals.json

Now we are going to pour in the content for the custom card. We will start with the associated-deals.json file located in the extensions folder

					
					
				

Pouring in the content | Custom Card | AssociatedDeals.jsx

Next up, the react file. For now, we are going to create the absolute minimum in this file. We will revisit it later

					
					
				

Pouring in the content | Custom Card | package.json

Finally for our front-end, we are going to pour in the content for the package.json file located in the extensions folder

					
					
				

Pouring in the content | Serverless Functions | package.json

Now we are going to pour in the content for the serverless function. We will start with the package.json file located in the app.functions folder

					

Pouring in the content | Serverless Functions | thanksKyle.js

Next up, the serverless function file. For now, we are going to create the absolute minimum in this file. We will revisit it later

					const axios = require('axios');

exports.main = async () => {}

Pouring in the content | Serverless Functions | serverless.json

Finally for our back-end, we are going to pour in the content for the serverless.json file located in the app.functions folder

					
{
	"appFunctions": {
		"jepsonupdater": {
			"file": "thanksKyle.js",
			"secrets": []
		}
	}
}

					
				

Upload the project to your HubSpot account

We have done a lot! And now we have the minimum required files and content to register this extension with our HubSpot account.

Let's head back to the terminal. Make sure you are in the root directory which would be the one that contains the hsproject.json file. Once you are there, run this command

										
											npm install
										
									
					
					hs project upload
					
				

If all went well, you should be able to login to you account and add this card to contact records!

Let's get our local dev server running!

Now that you have uploaded your card, we will fire up our local dev server so we can build out our cards. With local dev, you can safely build and break you card without fear of the production card being affected.

From the terminal, run the following command

						
						hs project dev
						
					

Once you run this command, you can open your HubSpot account and navigate to a contact record. If you have added the custom card, you will see it with a label above it indicating that you are actively developing this custom card. This is only viewable to you and not anyone else

Almost time to make the custom card do something...but first

Let's talk about keeping our react components organized

We can reused these components and swap in different data for the next card

Let's further organize

Navigate to the extensions folder and create a new folder called components

Within this folder, we are going to create 5 files.

  • Clicker.jsx
    This will be our View More Button
  • DealPanel.jsx
    This is the outer level of the panel
  • DealPanelInner.jsx
    This is where we will set what the data that we receive for the panel
  • Layout.jsx
    This controls the layout for the component
  • Stats.jsx
    This is the component that shows the data before we open the panel

Building the custom card | Layout.jsx

The first component we will create is the layout component for the card.

					

Building the custom card | Stats.jsx

Next, we will build the subcomponents for the layout.

									

Building the custom card | Clicker.jsx

Next, we will build the subcomponents for the layout.

									

Building the custom card | AssociatedDeals.jsx

Let's add our components to our custom card

									

Building the custom card | DealPanel.jsx

Next up, creating the panel which will be comprised of 2 components: DealPanel.jsx and DealPanelInner.jsx

Go ahead and open up DealPanel.jsx

					

Building the custom card | DealPanelInner.jsx

Moving on to the DealPanelInner.jsx

															

Building the custom card | AssociatedDeals.jsx

Finally, we will add the DealPanel and DealPanelInner components to our custom card

					
					
				

Building the custom card | AssociatedDeals.jsx

At this point, we have a fully functioning card returning deal data for this contact! Now let's pay tribute to Kyle by adding a thank you button to this card. The button will use a severless function that will update a HubDB table. This table will in turn update thanks.kyle.team

In your AssociatedDeals.jsx file we will add a button component.

				
				

Building the serverless function | serverless.json

On the front end, we now have a button click that triggers a serverless function we have named "jepsonmeter"

If you remember, in our serverless.json file is where we added the name of the serverless function

					

Building the serverless function | Storing authentication

Our serverless function is going to be making an authenticated API call so we need to store the authentication method in a secret.

					

Building the serverless function | Storing authentication

Now we need to register the secret with HubSpot. In your terminal, we will need to stop watching the project and add the key

					

You will be asked for the code which is

Building the serverless function | Storing authentication

We have registered the token with HubSpot, but for security reasons, it will not be available for local development so we need to add it to the .env file as well

Open the .env file and add the following

					

Building the serverless function | thanksKyle.js

We are ready to create our serverless function! Open up thanksKyle.js and enter the following

					

200 SUCCESS!

Congrats! You should now have an custom card ready to deploy. We need to run the upload command one last time to push our changes