Learn how to run a local development server for building CMS React projects.
@hubspot/cms-dev-server
is a package that facilitates starting an Express + Vite development server, enabling an auto-reloading local development workflow that is nearly identical to your deployed components. The cms-dev-server
also enables rendering local versions of your components on live CMS pages to aid in development.
hs-cms-dev-server/path/to/components-directory
in a project that has @hubspot/cms-dev-server
installed.
For example, a CMS page https://cmssite.com/page
with JS rendered components would be accessible by visiting one of:
http://cmssite.com.hslocal.net:3000/page
http://cmssite.com.localhost:3000/page
http://hslocal.net:3000/proxy
and pasting in the page you want to proxy.
Similar to how previewing a page from the page editor works, you can force the page to render with the context of a known contact by passing an email
parameter. For example http://cmssite.com.hslocal.net:3000/page?email=bh@hubspot.com
will cause the contact object to be populated based on the email parameter value.
You may also start the dev server with the --ssl
option, which enables:
https://cmssite.com.hslocal.net:3000/page
https://cmssite.com.localhost:3000/page
components/modules
directory, then will dynamically create routes based on the modules that it finds. There are two routes for previewing your modules: /module/moduleName
and /preview/module/moduleName
.
http/module/moduleName
The /module/moduleName
route is rendered entirely locally without connecting with the HubSpot backend. This enables you to work offline and unauthenticated at this route.
Field values that are used are derived entirely from the Field default values and from parameter-level overrides. Parameter-level overrides can be passed via the fields
parameter, which expects stringified JSON of fieldValues
that matches the passed fieldValues
prop (matching the fields definition structure).
Using this route includes some caveats for querying data:
?hsLocalQueryKey
query parameter.hublDataTemplate
is not supported at this route.Icon
, CTA
, and other @hubspot/cms-component
field helpers are not supported at this route./preview/module/moduleName
route interacts with the HubSpot backend and behaves similarly to viewing a module in the design manager previewer.
Field values that are used rely on defaults, as there is no module instance to pull from. There is no fields
parameter available for overrides.
When querying data on this route:
hublDataTemplate
is supported.Icon
, CTA
, and other @hubspot/cms-component
field helpers are supported.hslocal.net:3000
or localhost:3000
to the root domain, just as you would with proxying a public page.
To view the page as a specific contact, you can add an email
query parameter to the URL, followed by the contact’s email address, as shown below:
https://mydomain.hslocal.net:3000/private-page-path?email=hi@hubspot.com
That email will be used for the request_contact
HubL variable, and can be passed to React using hublDataTemplate
.
hslocal.net:3000
or localhost:3000
to the root domain. To view the page as a specific contact, you can add an email
query parameter to the URL, followed by the contact’s email address, as shown below:
https://mydomain.hslocal.net:3000/private-page-path?hs_preview=[preview_key]&email=hi@hubspot.com
--storybook
option when running the command to start the local development server.
Once started, you can add .stories.jsx
files alongside your components to build stories for testing or development. At the root http://hslocal.net:3000
page, a link will be included to the Storybook UI for your project. To make building stories for HubSpot modules easier, cms-dev-server provides helpers to auto-generate argTypes
based on module fields. See the GraphQL and Storybook example project for usage of moduleStory()
.
Storybook is built with client components in mind, so components that cross island boundaries can have unexpected lifecycle behavior when rendered in a story. Because server-only components never make it to the browser, they cannot be hot reloaded, so a full re-render is necessary to update the server response. To fully emulate hybrid rendering in Storybook at the cost of hot module reloading, you can use moduleStoryWithIsland()
in your story in place of moduleStory()
.
--generateFieldTypes
argument when starting the development server. This command will watch for changes to the fields
object that is exported from module files and create a .types.ts
file inside of the module directory. You can then import this module directly in your module component and use it in the generate ModuleProps<T>
type.
For example, suppose you have the following fields.jsx
file:
hs-cms-dev-server /path/to/project --generateFieldsTypes
will generate a modules/MyModule/fields.types.ts
file with a default exported type MyModuleFieldsType
. The above fields.tsx
will generate the following file:
fields.types.ts
file will be overwritten every time there is an update made to the fields object. To disable this behavior, remove the THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
comment at the top of the file.
@hubspot/cms-dev-server
, create a .env
file to define secret values for local use only. Keys in this file need to be prefixed with HS_
for the development server to recognize it as a secret.
HS_
prefix you included in your .env
file. In the example above, the secret can be accessed with getSecret('TEST_SECRET')
.