Delivery is the start, not the goal. In this chapter, we will systematically explain everything from designing a maintenance system, creating handover documents, coding rules for operation, and responding to HubSpot updates, so that our clients can operate their sites stably over the long term.
Many projects enter the operational phase with the understanding that ``it's over once it's delivered.'' Confusion will ensue later.The maintenance system will be designed and agreed with the client before delivery.It's a thing.
There are two axes to running a HubSpot site: technical maintenance and content operations. First, organize who will be responsible for what.
| Contract type | Main contents | Estimated man-hours/month |
|---|---|---|
| spot maintenance | Request based. We provide estimates for any repairs or additional development that occur. | Each case |
| light maintenance | Monthly performance check and minor corrections (about 1-2 hours/month) | 2~4h/month |
| standard maintenance | Including minor repairs, one new module development, and monthly report submission. | 8~16h/month |
| full maintenance | Including content update agency, SEO measures, A/B testing, additional function development | 20h~/month |
Unify the counter into one. For ambiguous requests such as "I want to modify the design," we will conduct a hearing to find out the specific requirements. Create a rule that requires screenshots and URLs to be attached.
Verify that your changes do not affect other page modules. We will determine whether we can handle the work based on the contracted man-hours, and if it exceeds the contract, we will provide an additional estimate.
Don't touch the actual production directly, be sure to implement it on the development portal and then share the confirmation URL with the client.
As a general rule, approval should be obtained in writing (email/Slack) rather than orally. Just saying "No problem" is OK.
Type git tag and check the target page after production deployment. Report work completed to client and close ticket.
The handover document isEnabling marketers and content managers to run on their ownIt's for. If you write it from an engineer's perspective, the document will be too difficult. It is important to design your content to suit the audience.
If you have many modules, writing them all in one document will make it difficult to read. 1 page per moduleIn the style of The most commonly used format is to organize it in Notion or an internal wiki.
# Hero Banner Module Operation Guide
## What is this module?
A banner that displays a large image and catchphrase at the top of the page.
It is placed on the top page, service page, etc.
## Field description
| Field name | Contents | Notes |
|-------------|------|---------|
| Heading | Banner main text | Maximum 30 characters recommended |
| Subheading | Supplementary text below the heading | Optional |
| Background image | Background image for the entire banner | Recommended size: 1440x640px |
| CTA button text | Text to display on the button | Recommended maximum of 15 characters |
| CTA button link | Button link URL | External link opens in a separate tab |
## Recommended image size
- Width: 1440px or more
- Height: 640px ~ 800px
- File format: JPG (photo) / PNG (with transparency)
- File size: Recommended to compress to 2MB or less
## Things not to do
⚠️ Do not use vertical images (ratio less than 1:1).
The layout may be distorted when displayed on a PC.
⚠️ When you use an image with text as a background,
It may not be readable on mobile.
Along with text documents,Record the operation video with Loom or screen recorder and send itand The client's self-propelled rate will increase dramatically. With just one “5 minute video of creating a new blog article and publishing it,” You won't get asked the same questions over and over again. It is especially effective to explain how to operate HubDB, change forms, and add modules through videos.
There is a difference between "code that works" and "code that is easy to operate." An hour of ingenuity during development can save dozens of hours of confusion during client operations.
| design principles | concrete implementation |
|---|---|
| Make things that can be controlled in fields a field. | Colors, text, links, and images are all managed in fields.json fields. Allow changes to be made without touching the code. |
| Always set default values | Set meaningful default values for all fields. Even if it is not set, it will maintain a state of ``apparent appearance''. |
| Make field labels Japanese | Do not leave the label in English. Marketers are less confused by "background color" than by "bg_color." |
| Add input guide with help_text | For the image field, write "Recommended size: 1440x640px" and for the text field, write "Up to 0 characters recommended" in help_text. |
| Restrict fragile operations with choice | Make layout switching a selection method using a choice field instead of free input. Prevent input of unexpected values. |
[
{
"type": "text",
"name": "heading",
"label": "Heading",
"required": true,
"default": "Enter heading text",
"help_text": "Recommended maximum of 30 characters. If it's too long, your phone will wrap it back."
},
{
"type": "image",
"name": "bg_image",
"label": "Background image",
"help_text": "Recommended size: 1440 x 640px. Please compress to JPG format and 2MB or less.",
"default": {
"src": "",
"alt": "",
"width": 1440,
"height": 640
}
},
{
"type": "choice",
"name": "layout",
"label": "Layout",
"help_text": "Choose where to place the text.",
"choices": [
["center", "Center (default)"],
["left", "Left-aligned"],
["right", "Right alignment"]
],
"default": "center",
"display": "radio"
},
{
// Fields on STYLE tab are set as "For advanced users"
// Detach from normal editing screen
"type": "color",
"name": "overlay_color",
"label": "Overlay Color",
"tab": "STYLE",
"help_text": "The color to overlay on top of the background image. Transparency can also be set.",
"default": { "color": "#000000", "opacity": 40 }
}
]
The template file contains information for those who will touch it later (your future self or the engineer who took over). Leave a comment. From “What are you doing?”“Why did you do this?”The general rule is to write
{# ===================================================== Blog article template (blog-post.html) ===================================================== [Use] Blog article detail page[Inheritance] layouts/base.html[DnD] None (fixed layout) [Update history]2024-03-15 v1.2 Added content type form switching2024-01-10 v1.1 Added previous/next article navigation2023-11-01 v1.0 initial release [Notes]- For tag naming rules, refer to "Tag Design" in README.md- The form ID is managed in the form_config dictionary in this file.- If you want to add a form, add it to form_config ===================================================== #} {% extends "./layouts/base.html" %} {# ===== Content type determination ===== Determine the type by the tag prefix. See Chapter 6, "Tag Design Strategies" for details. type: If multiple tags are attached, the last value found will be used (only one is recommended for operational purposes) ===================================================== #} {% set ns = namespace(content_type="blog") %} {% for tag in content.tag_list %} {% if tag.slug starts_with "type:" %} {% set ns.content_type = tag.slug|replace("type:","") %} {% endif %} {% endfor %} {# ===== Form settings dictionary ===== Manage form IDs and redirect destinations for each content type. When adding a new type, just add it here. The form ID can be found in the form details URL on the HubSpot admin screen. ===================================================== #} {% set form_config = { "blog" : { "id": "BLOG_FORM_ID", "redirect": "/thanks/contact" }, "seminar" : { "id": "SEMINAR_FORM_ID", "redirect": "/thanks/seminar" }, "whitepaper" : { "id": "WHITEPAPER_FORM_ID", "redirect": "/thanks/whitepaper" } } %}
When developing and maintaining code as a team, if there are no rules, the way the code is written will be inconsistent. Maintenance costs will increase.At least a clear written agreementis required.
# HubSpot CMS Coding Standards
## File/directory naming conventions- File name/directory name: kebab-case (e.g. hero-banner, blog-post)- Module name: kebab-case + .module (e.g. hero-banner.module)- CSS class name: BEM (Block__Element--Modifier)- HubL variable name: snake_case (e.g. content_type, form_id)
## HubL Terms
### Variable definition- Define variables used outside the loop all at the beginning- Define the dictionary (map) with set and then refer to it- Use namespace (ns) only in stateful loop processing
### Template comments- Start of file: Enter purpose, update history, and notes (required)- Complex logic: write “why you did this” (you can understand what you are doing by reading it)- TODO: Make it easier to search with the "TODO:" prefix
### Existence check principle- image field: Check with {% if module.image.src %}- link field: Check with {% if module.link.url %}- Text: Check with {% if module.text %}- Do not refer to .src etc. without checking its existence
## CSS conventions
### Naming Convention (BEM).module-name {} ← Block
.module-name__element {} ← Element
.module-name--modifier {} ← Modifier
.module-name__element--mod{} ← Element + Modifier
### Responsive- Mobile first (override breakpoints with min-width)- Unify breakpoints with CSS variables --bp-sm: 480px;
--bp-md: 768px;
--bp-lg: 1024px;
--bp-xl: 1280px;
### CSS variable references- Always refer to theme.json colors and fonts via CSS variables- Do not hardcode direct values (#ff0000, etc.)
## Accessibility Terms- Set alt attribute on all img tags (decorative images are alt="")- Set aria-label on interactive elements- Maintain color contrast ratio at WCAG AA (4.5:1) or higher- Focus can be visually confirmed by keyboard operation
## Git commit message conventionsfeat: New feature addedfix: bug fixstyle: Appearance adjustment (no functional change)refactor: refactoringdocs: Changes to documentation onlydeploy: production deployment (used in conjunction with version tag)
HubSpot is a continuously updated platform. By regularly adding features, changing the UI, and responding to deprecations, You can maintain the quality of your site for a long time.
| item | frequency | Content |
|---|---|---|
| CLI version check/update | Once a month | npm update -g @hubspot/cli Updated to the latest version. Check the change history (CHANGELOG) to see if there are any Breaking Changes. |
| Check PageSpeed Insights | Once a month | Records the scores of representative pages (top page, blog list, article details). Check to see if it has worsened compared to the previous month. |
| Check Search Console | once a week | Check the coverage error/Core Web Vitals issue page. If there are any new errors, we will respond immediately. |
| Check for HubSpot product updates | Once a month | Check out HubSpot's Product Updates page and Developer Changelog at developers.hubspot.com. |
| Broken link check | Once every 3 months | Check your entire site for broken links using tools such as Screaming Frog. |
| Update your Personal Access Key | every 150 days | Renew the key before it expires (180 days). GitHub Secrets will also be updated at the same time. |
| Check for deprecation of HubSpot templates | Once every six months | Check the HubSpot developer documentation to see if any HubL features you're using have been deprecated. |
blog_recent_posts() Function specifications such as etc. may change. Regularly review the "Deprecated" section of the HubSpot developer documentation.hubdb_table_rows() There may be changes to the query parameters. Be especially careful with sites that use HubDB extensively.js.hsforms.net/forms/embed/v2.js When the version of is updated, it is necessary to check the operation.
Developer documentation: developers.hubspot.com/docs/cms
Product updates: www.hubspot.com/product-updates
Developer forum: community.hubspot.com/t5/HubSpot-Developers
GitHub(HubSpot CLI): github.com/HubSpot/hubspot-cli/releases
HubSpot Developer Changelog: developers.hubspot.com/changelog
| symptoms | Where to check for the cause | solution |
|---|---|---|
| the page turned white | Previous deployment content/HubL syntax error | Check the error with hs lint → check out the previous git tag and rollback |
| module not visible | fields.json syntax error/required field not set | Select the module in HubSpot's page editor to see error messages |
| CSS is not reflected | Whether to use browser cache/get_asset_url | Clear cache with hard reload (Ctrl+Shift+R). Re-upload using CLI. |
| form cannot be submitted | Form ID accuracy/portal ID matching/ad blocker | Check in another browser in incognito mode. Double-check the form ID in your HubSpot admin. |
| hs upload fails | Authentication token expired/network/file path incorrect | Re-authenticate with hs auth.--portal Check the flag specification. |
| HubDB data is not displayed | Misprints in table Published status, query conditions, and field names | Check if the table is "Published" on the HubDB management screen. Simplify and debug query parameters. |
| Layout is broken on smartphone | Image width/height not specified/CSS flexbox settings | Switch to responsive mode and identify elements in Chrome DevTools. Specify aspect-ratio or width/height. |
| The page's OGP image remains outdated | SNS cache | Facebook: Clear cache with OG Debugger (developers.facebook.com/tools/debug). Twitter: Check with Card Validator. |
{# ===== Check the contents of the variable ===== Be sure to delete it in the production environment! ===================================================== #} {# ① Check the type and value of the variable #} <pre>{{ module|pprint }}</pre>{# ② Check loop counter #} {% for item in module.items %} {# Output loop status #} <p>index:{{ loop.index }} / first:{{ loop.first }} / last:{{ loop.last }} / length:{{ loop.length }}</p>{% endfor %} {# ③ Confirm conditional branch (output judgment result) #} <p>content_type: {{ ns.content_type }}</p> <p>is_featured: {{ ns.is_featured }}</p>{# ④ Check HubDB data #} {% set rows = hubdb_table_rows("my_table") %} <p>取得件数: {{ rows|length }}</p> <pre>{{ rows|pprint }}</pre>{# ⑤ Check request object (URL parameters, etc.) #} <pre>{{ request|pprint }}</pre>
If included in a maintenance contract, we will provide reports to the client on a monthly basis. Including the following items will increase credibility.
npm outdated -g @hubspot/cli Apply any updates.
Agree on the division of roles, request flow, and contract details in advance. If we enter the operational phase with ambiguity, misunderstandings will occur.
For marketers, ``how to operate''. For engineers, ``Why did we design it this way?'' Write a document that separates both perspectives.
help_text/Japanese label/choice input restriction/default value. An hour of care during development can save clients from tens of hours of confusion.
Monthly PageSpeed/Search Console checks and token updates every 150 days. Put it in your calendar and deal with it ``as a system''.
From the overall picture in Chapter 0 to HubL, templates, modules, data utilization, forms, performance, CLI, and operational design.
The techniques and design concepts learned in this textbook are applicable not only to HubSpot CMS projects, but also to
It is also the answer to the question, "How do I interact with clients as an engineer?"
Code is a tool. Our goal is to advance our client's business.
When you are at a loss in the field, please use this textbook as a dictionary.