Skip to content

TBMQ related info migration to new website - #585

Open
deaflynx wants to merge 31 commits into
thingsboard:mainfrom
deaflynx:tbmq-migration
Open

TBMQ related info migration to new website#585
deaflynx wants to merge 31 commits into
thingsboard:mainfrom
deaflynx:tbmq-migration

Conversation

@deaflynx

@deaflynx deaflynx commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Description

Migrates the TBMQ (MQTT Broker) web presence from thingsboard.io to the dedicated site tbmq.io.

Net changes in this PR:

  • Edge redirects (Cloudflare): /docs/mqtt-broker/* and /docs/mqtt-broker/pe/* (plus the Jekyll-era /docs/pe/mqtt-broker/* shapes) are forwarded to the corresponding tbmq.io docs, and /products/mqtt-broker/ is forwarded to the tbmq.io landing (src/data/redirects.ts + regenerated public/_redirects / public/redirects.json). Its legal children (privacy-policy/, terms-of-use/) intentionally stay on thingsboard.io — tbmq.io has no equivalents for them yet.
  • Final origin baked in: all TBMQ redirect targets point at https://tbmq.io directly — the DNS cutover is what activates them, so there is no origin flip left in the cutover runbook. ⚠️ Do not deploy to production before tbmq.io DNS resolves: until then TBMQ URLs 301 to a dead host (loud and self-healing at cutover — unlike a cacheable 301 to staging, which browsers and crawlers would keep following long after a later flip).
  • TBMQ pricing FAQs: contact-us links pre-select the TBMQ subject, now via a shared TBMQ_CONTACT_US_URL constant. Docs links inside the FAQs intentionally stay local — like all other TBMQ entry-point links (nav, installations, home ecosystem card), the cutover happens at the edge via the redirects above, and the follow-up deletion PR repoints them.

Verification: every local TBMQ doc URL (84 CE + 90 PE = 174) plus all 28 legacy single-redirect targets were script-checked through the _redirects rules against the TBMQ site (via its tbqa.cloud staging mirror, since tbmq.io DNS is not live yet) — each mapped target returns 200, so the generic splats introduce no 301-into-404s.

Type of change

  • New / updated documentation page (src/content/docs/**)
  • Shared include file (src/content/_includes/**)
  • Component, layout, or styling change (src/components/**, src/styles/**)
  • Landing / use-case / case-study page (src/pages/**, src/data/**)
  • Redirects (src/data/redirects.ts)
  • Version bump / release (see release skill)
  • Build, CI, scripts, or tooling

Affected products

TBMQ (CE + PE). No other product pages are touched.

Related issues

Checklist

  • pnpm check passes (Astro / TypeScript)
  • pnpm lint:eslint passes
  • pnpm lint:slugcheck passes (required if pages were added/renamed/moved across languages)
  • pnpm lint:linkcheck passes locally — required to merge; run it before requesting review (use pnpm lint:linkcheck:nobuild if you already ran a build)
  • Renamed/removed pages have a redirect in src/data/redirects.ts, and pnpm generate:redirects was run
  • No hardcoded versions — values come from src/data/versions.ts
  • Screenshots attached for visual changes

@deaflynx deaflynx added the wip label Jul 27, 2026
deaflynx added 12 commits July 30, 2026 10:57
…t at root

tbmq.io is a TBMQ-only site: its docs live at /docs/<slug> and the product
landing is the site root, not /product/. Update TBMQ_DOCS_ROOT and
TBMQ_URLS.product accordingly, route the Try it now features/deployGroups
and description links through the helpers, and repoint the two cross-product
DocLinks in the MQTT integration guide at tbmq.io.
Route every local /docs/mqtt-broker/ and /products/mqtt-broker/ link in the
TBMQ pricing surfaces (CE, self-managed PAYG/perpetual, private cloud FAQs,
the CE Install CTA and the See full details button) through the
external-sites helpers so they resolve to the segment-free tbmq.io URLs.
…flare edge

Replace the four TBMQ catch-all groups with five ordered cross-origin splats
in DYNAMIC_REDIRECTS (Jekyll install/ renames before the generic rules) and
rewrite the 27 TBMQ single redirects to absolute one-hop tbmqDocsUrl targets,
so no request ever chains. external-sites.ts gains a Node-safe env guard and
a TBMQ_DOCS_BASE export for splat templates, since redirects.ts is loaded by
plain Node in the generator and by Astro's config loader.

The splats stay out of astro.redirects.ts on purpose: local TBMQ pages remain
browsable in dev and lint:linkcheck stays green until the content is deleted.
Dynamic rule budget after regeneration: 47 of Cloudflare's 100.

Deploy gate: tbmq.io must serve its docs at the new URL shape before this
reaches production — the edge 301s fire regardless of target availability.
Collapse the five-rule TBMQ cutover group to a two-rule identity forward
(/docs/mqtt-broker/* and /docs/pe/mqtt-broker/* pass through with the
segment kept) and drop the 27 cross-origin singles: tbmq.io keys its full
legacy redirect table on the original URL shape and strips the segment on
its own edge, so every rename lives in one repo. Also send
/products/mqtt-broker/ to the tbmq.io root, which is its product landing.
The identity-forward splats resolve every /docs/mqtt-broker/* and
/products/mqtt-broker/ URL at the edge, and lint:linkcheck replays
public/_redirects, so the pricing FAQ/CTA links and the two mqtt.mdx
DocLinks can stay local instead of spelling tbmq.io URLs. The contact-us
?subject=TBMQ preselection is kept. The removal inventory now notes that
the mqtt.mdx DocLinks are a build-time dependency on Products.TBMQ and
must be re-pointed when the enum entries are removed.
…o edge redirects

Revert the six link/component files to the merge-base state so the PR no
longer touches them: mega-menu and docs-selector TBMQ items, home ecosystem
card, Try-it-now panel, version switcher and the MQTT integration include
all keep their local TBMQ URLs. The identity-forward rules in
public/_redirects are the single cutover mechanism.
The plan, spec and removal inventory described the superseded
segment-stripping redirect design and in-flight link repointing that was
since reverted — the shipped mechanism is the two-rule identity forward in
public/_redirects, documented inline in src/data/redirects.ts.
With all entry-point links restored to local paths, redirects.ts was the
module's only consumer — replace it with a hardcoded TBMQ_ORIGIN const.
Points at the tbmq.tbqa.cloud staging origin for now; swap to
https://tbmq.io and regenerate when the production DNS goes live.
@deaflynx deaflynx removed the wip label Aug 7, 2026
@deaflynx
deaflynx requested a review from vvlladd28 August 7, 2026 12:45
@deaflynx deaflynx added the wip label Aug 7, 2026
The two-rule identity forward kept the mqtt-broker/ segment and relied on
tbmq.io to resolve the legacy shape, so every docs hit paid a second
redirect on the far side. Strip the segment at our edge instead: five
ordered cutover splats (Jekyll-era install/ renames first — Cloudflare
takes the first match and never chains) plus the 28 rewritten singles,
so every legacy URL resolves in one hop to its final tbmq.io page.
tbmqDocsUrl is a local one-liner on TBMQ_ORIGIN rather than a revived
external-sites module.
- Delete /docs/mqtt-broker/ and /docs/mqtt-broker/pe/ page trees and their _includes
- Delete TBMQ docs image tree, orphaned schema SVGs, tbmq-ce install icon, and bulk-import CSV resource
- Remove TBMQ sidebars, tab links, and prefix mappings from astro.sidebar.ts
- Drop TBMQ PE key-page entry from llms.txt

@vvlladd28 vvlladd28 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review summary

Reviewed 6 changed files in TBMQ related info migration to new website. Left 7 comment(s) inline.

Reviewer questions answered

"Was any redirect lost?" — No. I diffed the set of source paths in public/_redirects between main and this branch: every source present on main is still present here, and three are new (/docs/mqtt-broker/*, /docs/pe/mqtt-broker/image-gallery/, /products/mqtt-broker/). The four deleted CATCH_ALL_REDIRECTS prefix groups (mqtt-broker/install, mqtt-broker/pe/install, pe/mqtt-broker/install, pe/mqtt-broker) are each replaced by an equivalent DYNAMIC_REDIRECTS splat, and the ordering is right — the three install/* rules precede the two generic ones, which matters because Cloudflare takes the first match and never chains. No redirect target anywhere in _redirects or redirects.json still points into a local /docs/mqtt-broker/… path, and scripts/check-redirect-chains.ts passes (✓ No redirect chains found across 1040 SINGLE + 52 NON_DOCS targets). Rule budget is fine: 47 dynamic (cap 100) and 1135 total (cap 2100).

"Do the pages correctly move /docs/mqtt-broker/* → tbmq.io /docs/*?" — Structurally yes. The segment-stripping is correct and every URL resolves in one hop:

Source Target
/docs/mqtt-broker/* …/docs/:splat (also covers /docs/mqtt-broker/pe/*…/docs/pe/*)
/docs/pe/mqtt-broker/* (Jekyll) …/docs/pe/:splat
/docs/mqtt-broker/install/* …/docs/installation/:splat
/docs/mqtt-broker/pe/install/*, /docs/pe/mqtt-broker/install/* …/docs/pe/installation/:splat
27 special-case singles (apirest-api, faqwhy-tbmq, troubleshootinghelp, …) preserved 1:1

The caveat is that the two generic splats assume tbmq.io mirrors thingsboard.io's TBMQ slugs 1:1 for all 174 local TBMQ doc pages (84 CE + 90 PE). Anything renamed on the new site becomes a 301-into-404 with no signal from CI — worth a scripted spot-check of that slug list against the live tree before merge.

Additional findings

These observations are about existing code outside the PR's diff — spotted while reading surrounding context.

  • astro.redirects.ts:24devFallbackRedirects['/docs/pe/mqtt-broker/search/'] = '/docs/mqtt-broker/pe/search/' mirrored the now-deleted pe/mqtt-broker catch-all. It still resolves to a local path, so dev and prod now disagree for this URL, and it becomes dangling once the follow-up PR deletes the TBMQ docs. Dev-only, but it should go with the same change.
  • config/integrations/sitemap.ts:59isIndexableCanonicalPage includes any built page that is self-canonical and not noindex. All 174 TBMQ doc pages still build, so the production sitemap will keep advertising URLs that Cloudflare 301s off-domain. That makes the follow-up removal PR a prerequisite for a clean cutover rather than optional cleanup — worth calling out in the PR body so the two don't drift apart in time.
  • scripts/generate-redirects.ts:257-266 — the script computes dynamicRuleCount and prints it, then exits 0 regardless. Since exceeding Cloudflare's 100-dynamic cap silently drops rules rather than erroring, a process.exit(1) above 100 (or a warning at ~80) next to that existing console.log would be a cheap tripwire. Not a problem at 47, but this PR is a natural moment to add it while dynamic rules are being appended.
  • scripts/lint-linkcheck.ts:111 — the { from: '/docs/mqtt-broker/', to: '/docs/mqtt-broker/pe/' } CE↔PE pairing entry becomes meaningless once the tree is gone; another item for the follow-up.
  • PR description — it states "TBMQ pricing FAQs: documentation/CTA links point at tbmq.io". They don't in this diff: refactor(tbmq): restore local TBMQ links covered by edge redirects reverted that, and only the ?subject=TBMQ change landed. Worth correcting the body so reviewers of the follow-up aren't misled about what's already done.

This review was auto-generated. Findings may contain errors — please verify before applying changes.

Comment thread src/data/redirects.ts Outdated
* GONE — page removed, redirect to fallback
*/
// Staging origin until tbmq.io DNS goes live — swap to https://tbmq.io then.
const TBMQ_ORIGIN = 'https://tbmq.tbqa.cloud';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the one thing I'd block on. As written, merging this ships 301s from the entire TBMQ URL space on thingsboard.io to a staging hostname — /docs/mqtt-broker/*, /docs/pe/mqtt-broker/*, and /products/mqtt-broker/ all land on tbmq.tbqa.cloud. A 301 is cacheable and browsers hold onto it aggressively, so anyone who hits a TBMQ URL between merge and the DNS cutover keeps going to staging from their own cache long after the const is flipped.

Two things would make the swap safe:

  1. The comment should say that flipping the const is only half the job — pnpm generate:redirects has to be re-run and the regenerated public/_redirects + public/redirects.json committed, or the edge keeps serving tbmq.tbqa.cloud while the source claims otherwise.
  2. Could this be an assertion rather than a note? A couple of lines in scripts/check-redirect-chains.ts (or the generator) that fail when TBMQ_ORIGIN still contains tbqa.cloud and, say, ALLOW_STAGING_ORIGIN=1 isn't set would turn a silent regression into a red build.

Or — is there a reason not to point at https://tbmq.io right now and let the DNS cutover be the thing that flips? Until tbmq.io serves content the redirect target is dead either way, and a temporary 301-to-nothing seems less costly than a cached 301-to-staging.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went with your third option: TBMQ_ORIGIN now points at https://tbmq.io directly (3a94981), so the DNS cutover is what activates the redirects and there is no flip step left in the runbook. The caching asymmetry decides it, as you said — a cached 301 to the permanent address is harmless, a cached 301 to staging would linger in browsers and crawlers. The operative constraint is documented on the const and in the PR body: don't deploy to production before tbmq.io DNS resolves; in that window TBMQ URLs 301 to a dead host, which fails loud and self-heals at cutover.

On the assertion: considered it, but kept the generator untouched in this PR — with the staging host gone from the redirect data entirely, it no longer has anything to guard. And to de-risk the 1:1-slug assumption from your summary: all 174 local TBMQ doc URLs (84 CE + 90 PE) plus the 28 legacy single-redirect targets were script-checked through the _redirects rules against the site tbmq.io will serve (its staging mirror, since DNS isn't live yet) — every target returns 200.

Comment thread src/data/redirects.ts Outdated

// tbmq.io is TBMQ-only: its docs tree carries no mqtt-broker/ segment, so
// thingsboard.io's /docs/mqtt-broker/<slug> is /docs/<slug> there.
const tbmqDocsUrl = (slug: string): string => `${TBMQ_ORIGIN}/docs/${slug}`;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter is named slug, but every one of the 27 call sites actually passes a path with a trailing slash ('rest-api/', 'pe/installation/upgrade-instructions/'), and that trailing slash is load-bearing for the redirect target under trailingSlash: 'always'. Nothing in the signature says so — compare RedirectEntry.target just below, which spells out "Absolute target path with trailing slash". Either normalize inside the helper (append / when absent) or rename to path and document the convention, so call site 28 doesn't quietly drop it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to path with the convention documented (bb9d515): the value is appended verbatim — page paths carry their trailing slash, and :splat passes through untouched (the splat capture already carries the request's trailing slash). Documenting rather than normalizing was deliberate: appending / inside the helper would corrupt :splat targets now that the dynamic entries route through it too.

Comment thread src/data/redirects.ts
'/services/support/': '/services/',

// TBMQ — moved to tbmq.io, whose site root is the product landing
'/products/mqtt-broker/': `${TBMQ_ORIGIN}/`,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only key in NON_DOCS_REDIRECTS that collides with a real page — I checked all 52 against src/pages/, and /products/mqtt-broker/src/pages/products/mqtt-broker/index.astro is the sole hit. That collision isn't a no-op: in astro/dist/core/routing/create-manifest.js (v6.3.8, lines 474-477) file-based routes whose route matches a redirect route are filtered out, so the redirect wins and the TBMQ product landing stops being built at all. In pnpm dev/preview the page becomes unreachable and bounces to the staging host.

If that's intended, fine — but it's worth stating, because the group comment on the DYNAMIC_REDIRECTS block below says the TBMQ rules are "Deliberately absent from astro.redirects.ts so the local TBMQ pages stay browsable in dev", and that rationale doesn't survive here: astro.redirects.ts spreads NON_DOCS_REDIRECTS and public/redirects.json (which carries the 27 rewritten singles), so only the five splats are actually dev-exempt.

Separately — /products/mqtt-broker/privacy-policy/ and /products/mqtt-broker/terms-of-use/ exist as pages and are not redirected, so the parent moves to tbmq.io while its two legal children stay on thingsboard.io. Intentional (legal pages often need to stay put), or an oversight?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intended, and now stated on the entry (bb9d515): the redirect deliberately supersedes src/pages/products/mqtt-broker/index.astro — Astro drops the colliding file-based route, so dev/preview bounce to the new origin just like prod. The dynamic-group comment is fixed too: it now says only the five splats are dev-exempt, and that the TBMQ singles / /products/mqtt-broker/ reach dev via redirects.json / NON_DOCS_REDIRECTS — none of which shadows a local page.

Legal children: deliberate. tbmq.io has no privacy-policy / terms-of-use equivalents (checked — 404 on the new site), so both stay on thingsboard.io; also noted in the comment.

Comment thread src/data/redirects.ts Outdated
'first match and never chains. Deliberately absent from astro.redirects.ts so ' +
'the local TBMQ pages stay browsable in dev until deleted.',
entries: [
{ source: '/docs/mqtt-broker/pe/install/*', target: `${TBMQ_ORIGIN}/docs/pe/installation/:splat` },

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbmqDocsUrl was introduced a few hundred lines up specifically to encode "tbmq.io's docs tree has no mqtt-broker/ segment", but these five entries bypass it and re-open-code ${TBMQ_ORIGIN}/docs/…. That leaves two spellings of the same rule in one file, so if tbmq.io ever changes its docs base (adds a version segment, drops /docs), the next person has to find and fix both shapes. tbmqDocsUrl('pe/installation/:splat') reads the same and keeps the knowledge in one place — the helper is plain concatenation, so :splat passes straight through.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done (bb9d515) — all five entries now go through tbmqDocsUrl(...), :splat included.

Comment thread src/data/redirects.ts Outdated
{ source: '/docs/pe/mqtt-broker/install/*', target: `${TBMQ_ORIGIN}/docs/pe/installation/:splat` },
{ source: '/docs/mqtt-broker/install/*', target: `${TBMQ_ORIGIN}/docs/installation/:splat` },
{ source: '/docs/pe/mqtt-broker/*', target: `${TBMQ_ORIGIN}/docs/pe/:splat` },
{ source: '/docs/mqtt-broker/*', target: `${TBMQ_ORIGIN}/docs/:splat` },

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth a line in the group comment, because this splat quietly disables the repo's own safety net for the follow-up PR: scripts/lint-linkcheck.ts passes redirectsFilePath: './public/_redirects' and replays these rules before the on-disk lookup, so from here on every internal /docs/mqtt-broker/… link resolves to an off-origin URL and stops being existence-checked.

There are still 126 such links across 25 files outside the TBMQ docs tree — src/data/installations.ts, src/data/navigation.ts, src/data/pricing/**, src/pages/products/mqtt-broker/index.astro, src/components/MqttBroker/*, src/components/starlight/Header.astro, and 7 published blog posts. The practical effect is that linkcheck stays green through the deletion PR whether or not those links were repointed — exactly when you'd most want it to shout. (check-redirect-chains.ts has the same blind spot by construction: it only matches targets against local /docs/… patterns, so cross-origin targets are invisible to it.) Neither is broken, but it's worth either noting it here or adding a temporary check that the TBMQ links resolve on the new origin.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted in the group comment now (bb9d515), including that the follow-up deletion PR must repoint the remaining local TBMQ links itself since linkcheck won't flag them. Instead of wiring a remote-origin check into CI (a flaky external dependency), I ran the scripted verification: all 174 local TBMQ doc URLs plus the 28 legacy single targets resolve 200 on the TBMQ origin's staging mirror.

id: 'tbmq-perp-setup-help',
question: 'How can I get help with installation and setup?',
answer: `<p>All perpetual license packages provide dedicated support with predefined response time and access to the ThingsBoard Support Portal. Our expert support team is available to assist you with system deployment by following our recommended <a target="_blank" href="/docs/mqtt-broker/installation/" rel="noopener noreferrer">installation methods</a> and architecture, ensuring a smooth and efficient setup. For custom installation scripts or alternative deployment scenarios, additional support options are available and you can <a target="_blank" href="/contact-us/" rel="noopener noreferrer">contact us</a> to discuss your needs.</p>`,
answer: `<p>All perpetual license packages provide dedicated support with predefined response time and access to the ThingsBoard Support Portal. Our expert support team is available to assist you with system deployment by following our recommended <a target="_blank" href="/docs/mqtt-broker/installation/" rel="noopener noreferrer">installation methods</a> and architecture, ensuring a smooth and efficient setup. For custom installation scripts or alternative deployment scenarios, additional support options are available and you can <a target="_blank" href="/contact-us/?subject=TBMQ" rel="noopener noreferrer">contact us</a> to discuss your needs.</p>`,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This answer was edited here — the contact-us link at the end gained ?subject=TBMQ — but the docs link earlier in the same string still points at /docs/mqtt-broker/installation/, which now takes a 301 hop to tbmq.io. Given that scripts/check-redirect-chains.ts exists precisely to keep upstream targets pointing at the final destination, migrating the CTA while leaving the doc link for the edge to rewrite reads inconsistent within one line.

Same pattern elsewhere in the pricing tree: src/data/pricing/tbmq-ce.ts:15 (ctaHref), tbmq-self-managed-payg.ts:16,21,280, tbmq-ce.ts:26,46,67,77,103,108,123,144, tbmq-private-cloud.ts:243. I get the deliberate decision to leave entry-point links alone until the pages are deleted — the ask is just to be explicit, since the PR body currently claims these already point at tbmq.io. If the FAQs are being touched anyway, repointing their TBMQ docs links in the same pass would spare users the hop and keep the file internally consistent.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs links stay local on purpose — repointing just the FAQs would fragment the "all local TBMQ links cut over at the edge, the follow-up repoints everything in one pass" strategy (126 links across 25 files, as you counted). The ?subject=TBMQ addition isn't a partial migration of that line — it's a contact-form UX tweak that stands on its own. The PR description was the actual bug here, and it's fixed: it no longer claims the FAQ docs links point at tbmq.io, and it now calls out the follow-up as a cutover prerequisite.

Comment thread src/data/pricing/faq/tbmq-ce.ts Outdated
id: 'tbmq-ce-migration-pe',
question: 'Is it possible to migrate from the Community Edition to the self-managed TBMQ Professional Edition?',
answer: '<p>Yes, you can upgrade from TBMQ Community Edition to Professional Edition without losing any data and/or configurations. The upgrade process preserves your existing setup, ensuring a seamless transition. However, please note that any custom modifications made directly to the source code of the Community Edition will be removed during the upgrade process. For more information about the migration procedure, please <a target="_blank" href="/contact-us/" rel="noopener noreferrer">contact us</a>.</p>',
answer: '<p>Yes, you can upgrade from TBMQ Community Edition to Professional Edition without losing any data and/or configurations. The upgrade process preserves your existing setup, ensuring a seamless transition. However, please note that any custom modifications made directly to the source code of the Community Edition will be removed during the upgrade process. For more information about the migration procedure, please <a target="_blank" href="/contact-us/?subject=TBMQ" rel="noopener noreferrer">contact us</a>.</p>',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's 22 hand-written copies of /contact-us/?subject=TBMQ across the three files (5 + 6 + 11), and the wider repo has no shared helper for contact-us URLs — every caller open-codes the query string with drifting encodings: ?subject=ThingsBoard%20Products in src/data/pricing/tb-self-managed.ts, encodeURIComponent('TBMQ') in src/scripts/pricing/calc-tbmq-perp.ts, ?subject=TBMQ&tbmqorder&message=… in src/pages/products/mqtt-broker/index.astro.

A small contactUsUrl({ subject, message }) in src/util/ would collapse all of it and — with a union type on subject — guarantee the value matches an actual <option> in ContactForm.astro. I did verify TBMQ matches (ContactForm.astro:88), and that the prefill at line 291 is a bare sel.value = subject, so a typo silently no-ops with no visible error. Trade-off: these answers are raw HTML string literals and tbmq-ce.ts uses single quotes, so a helper means switching it to template literals (the other two files already use backticks). If that churn isn't wanted now, even a module-level const TBMQ_CONTACT = '/contact-us/?subject=TBMQ' per file makes a future change one edit instead of 22.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took the lighter option: a shared TBMQ_CONTACT_US_URL in the new src/models/tbmq.ts (0107957), used by all three FAQ files — one edit instead of 22. The tbmq-ce.ts answers touched by it moved to template literals; rendered HTML is byte-identical (verified by evaluating the modules). Passed on the full contactUsUrl({ subject, message }) helper for now: the remaining open-coded call sites have divergent query shapes (&tbmqorder&message=…, calculator-built messages) and several sit on TBMQ surfaces the follow-up may move wholesale — a union-typed helper is a good refactor once that dust settles. src/models/tbmq.ts is also the intended home for tbmq.io link helpers when the follow-up repoints local links.

…mments

- Route the five TBMQ dynamic targets through tbmqDocsUrl so the
  "no mqtt-broker/ segment on tbmq.io" rule has one spelling; rename the
  helper param to `path` and document the load-bearing trailing-slash /
  :splat convention.
- Document the two-step staging-origin swap (flip const, regenerate,
  commit) next to TBMQ_ORIGIN.
- State that /products/mqtt-broker/ intentionally supersedes the local
  landing route (Astro drops file-based routes that collide with a
  redirect) and that its legal children stay local on purpose.
- Correct the dynamic-group comment: only the five splats are dev-exempt,
  and note the linkcheck blind spot for internal /docs/mqtt-broker/ links.
- Drop the /docs/pe/mqtt-broker/search/ dev fallback that mirrored the
  deleted pe/mqtt-broker catch-all and still resolved to a local path.
Follow-up to the TBMQ docs removal, addressing review feedback:

- delete zero-reference orphans: LiveDemoCard.astro (+ its
  tbmq-demo-root-ca.pem asset, now redirected to the TBMQ site's own
  copy), TbmqIntegrations.astro, product-selector/tbmq.svg, and the
  TBMQ_VER / TBMQ_PE_VER / TBMQ_BRANCH version constants
- retarget the two cross-product DocLinks in the MQTT integration guide
  to absolute tbmq.io URLs (verified both pages exist on the new site)
- drop TBMQ from live docs navigation: VersionSwitcher product family,
  SearchButton prefix routes, Header GitHub-platform detection
- reword the llms.txt site description to point TBMQ at tbmq.io
- remove the dev-only search fallback that targeted a deleted page
Collapse 22 hand-written copies of /contact-us/?subject=TBMQ across the
three TBMQ FAQ files into TBMQ_CONTACT_US_URL so a future change is one
edit. The subject value must match an <option> in ContactForm.astro — the
prefill silently no-ops on unknown values. tbmq-ce.ts answers touched by
this switch move from single-quoted strings to template literals; rendered
HTML is unchanged.
Swap TBMQ_ORIGIN from the tbqa.cloud staging host to https://tbmq.io, per
review. The DNS cutover is now what activates the redirects, removing the
flip-regenerate-commit step from the cutover runbook entirely. Trade-off:
this PR must not reach production before tbmq.io DNS resolves — until then
TBMQ URLs 301 to a dead host, which fails loud and self-heals at cutover,
whereas a cacheable 301 to staging would linger in browsers and crawlers
long after a later flip.

All 60 rewritten targets in public/_redirects + public/redirects.json are a
verified host-only swap (paths identical).
@deaflynx

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough pass — everything actionable landed in bb9d515 / 0107957 / 3a94981; per-item responses are on the inline threads. On the additional findings:

  • astro.redirects.ts:24 — removed (bb9d515); it was the last survivor of the deleted pe/mqtt-broker catch-all and would have gone dangling after the deletion PR.
  • Sitemap — agreed; the PR body now states the follow-up removal is a cutover prerequisite, and since feat(tbmq): remove TBMQ docs content, sidebar config, and doc assets deaflynx/thingsboard.io#1 targets this branch, both reach main together.
  • generate-redirects.ts tripwire — opted to keep the generator untouched in this PR. The staging-origin assertion became moot once TBMQ_ORIGIN was flipped to the final https://tbmq.io (nothing points at staging anymore); the dynamic-cap process.exit(1) is a good idea for a separate small PR.
  • lint-linkcheck.ts:111 — agreed, tracked for the follow-up deletion PR (the pairing stays valid while the pages exist, which this PR preserves).
  • PR description — corrected: the FAQ-links claim is gone, and the origin decision, slug verification, and cutover sequencing are documented.

On the summary's 1:1-slug caveat: verified — all 174 local TBMQ doc URLs (84 CE + 90 PE) and the 28 legacy single targets were mapped through public/_redirects and probed against the TBMQ site (staging mirror; tbmq.io DNS not live yet). Every target returns 200.

deaflynx and others added 2 commits August 14, 2026 17:00
feat(tbmq): remove TBMQ docs content, sidebar config, and doc assets
@deaflynx deaflynx removed the wip label Aug 14, 2026
The edge splats still cover every old URL, but the ecosystem cards, nav
mega-menu, pricing FAQ, blog and installations links now target tbmq.io
directly via a shared TBMQ_SITE_URL constant instead of paying the 301
hop through the retired local pages. Drop the OG override for the
superseded /products/mqtt-broker/ landing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants