No-write payload and mapping preview
SEO_BLOG_PUBLISH_TOKEN='<tenant-token>' \
SEO_BLOG_SITE_SLUG='<slug>' \
HUBSPOT_PRIVATE_APP_TOKEN='<hubspot-private-app-token>' \
HUBSPOT_CONTENT_GROUP_ID='<hubspot-content-group-id>' \
HUBSPOT_AUTHOR_ID='<hubspot-author-id>' \
SEO_BLOG_SITE_ORIGIN='<origin>' \
npx --yes @wotaso/seo-blog-admin-cli publish-cms --cms hubspot --site-slug '<slug>' --site-origin '<origin>' --dry-run
For a currently due approved post, --dry-run builds the destination payload without writing to the provider. It does not contact the provider or prove credentials, remote schema compatibility, deployment, or a live page; when no post is due, provider inputs are not exercised.
Scheduled runner health heartbeat
SEO_BLOG_PUBLISH_TOKEN='<tenant-token>' \
SEO_BLOG_SITE_SLUG='<slug>' \
HUBSPOT_PRIVATE_APP_TOKEN='<hubspot-private-app-token>' \
HUBSPOT_CONTENT_GROUP_ID='<hubspot-content-group-id>' \
HUBSPOT_AUTHOR_ID='<hubspot-author-id>' \
SEO_BLOG_SITE_ORIGIN='<origin>' \
SEO_BLOG_SCHEDULED='true' \
npx --yes @wotaso/seo-blog-admin-cli health --config seo-blog.config.json --mode cms --site-slug '<slug>' --site-origin '<origin>'
Run this from the real scheduled runner after seo-blog.config.json contains the selected connector configuration and the listed secrets are loaded. It reports configuration readiness, not a live article. The dashboard expires readiness at the returned deadline, with a 36-hour fallback when no deadline is available.
Fields and data model
- Content group and author are explicit required mappings
- Meta description, HTML title, body, and summary use native blog fields
- Featured image and alt text are sent when a durable URL exists
Canonical and route
HubSpot CMS owns the domain connection, URL structure, canonical markup, sitemap, templates, analytics, and public rendering. SEODrafts accepts the post URL returned by HubSpot as authoritative.
Known limits
- The private app needs the correct CMS scopes for reading and writing blog posts.
- Content Group and Author IDs must belong to the destination account.
- HubSpot theme modules beyond standard blog fields require custom template or field work.
Recovery
- Create a draft in the target blog and verify its author, template, and preview URL.
- Inspect private-app scopes and account IDs when HubSpot returns authorization errors.
- Rerun with the same slug after fixing the mapping so the adapter updates instead of duplicates.