From 043dedcd9c8b28416c2b1189ec6bb04098a74a73 Mon Sep 17 00:00:00 2001 From: Ruslan Date: Wed, 1 Jul 2026 13:13:40 +0300 Subject: [PATCH 1/6] chore(seo): remove orphan Edge pages + /community/, add redirects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Delete 5 orphan Edge pages (no incoming links; live replacements exist): provision-customer, provision-user (→ provision-customers-and-users), provision-dashboard (→ dashboards), the edge-proxy parent Tabs page (→ edge-proxy/debian; children kept), and the empty pe/reference/configuration-reference stub (→ /docs/pe/reference/). Removes CE + PE stubs + the now-unused shared includes, adds the /user-guide/ + pe/ redirects. Remove the unlinked /community/ marketing page: delete the page, drop it from MARKETING_ALLOWLIST + the OG marketing-meta prefixes, and redirect /community/ → /. public/_redirects + public/redirects.json regenerated via pnpm generate:redirects. --- public/_redirects | 10 + public/redirects.json | 13 +- .../docs/edge/user-guide/edge-proxy.mdx | 185 ----------------- .../edge/user-guide/provision-customer.mdx | 0 .../edge/user-guide/provision-dashboard.mdx | 0 .../docs/edge/user-guide/provision-user.mdx | 0 .../docs/edge/pe/user-guide/edge-proxy.mdx | 8 - .../edge/pe/user-guide/provision-customer.mdx | 8 - .../pe/user-guide/provision-dashboard.mdx | 8 - .../edge/pe/user-guide/provision-user.mdx | 8 - .../docs/docs/edge/user-guide/edge-proxy.mdx | 8 - .../edge/user-guide/provision-customer.mdx | 8 - .../edge/user-guide/provision-dashboard.mdx | 8 - .../docs/edge/user-guide/provision-user.mdx | 8 - .../pe/reference/configuration-reference.mdx | 6 - src/data/redirects.ts | 13 ++ src/pages/community/index.astro | 192 ------------------ .../open-graph/_shared/marketing-meta.ts | 1 - src/util/ogContext.ts | 1 - 19 files changed, 32 insertions(+), 453 deletions(-) delete mode 100644 src/content/_includes/docs/edge/user-guide/edge-proxy.mdx delete mode 100644 src/content/_includes/docs/edge/user-guide/provision-customer.mdx delete mode 100644 src/content/_includes/docs/edge/user-guide/provision-dashboard.mdx delete mode 100644 src/content/_includes/docs/edge/user-guide/provision-user.mdx delete mode 100644 src/content/docs/docs/edge/pe/user-guide/edge-proxy.mdx delete mode 100644 src/content/docs/docs/edge/pe/user-guide/provision-customer.mdx delete mode 100644 src/content/docs/docs/edge/pe/user-guide/provision-dashboard.mdx delete mode 100644 src/content/docs/docs/edge/pe/user-guide/provision-user.mdx delete mode 100644 src/content/docs/docs/edge/user-guide/edge-proxy.mdx delete mode 100644 src/content/docs/docs/edge/user-guide/provision-customer.mdx delete mode 100644 src/content/docs/docs/edge/user-guide/provision-dashboard.mdx delete mode 100644 src/content/docs/docs/edge/user-guide/provision-user.mdx delete mode 100644 src/content/docs/docs/pe/reference/configuration-reference.mdx delete mode 100644 src/pages/community/index.astro diff --git a/public/_redirects b/public/_redirects index 1d543a8281..87484fe9b9 100644 --- a/public/_redirects +++ b/public/_redirects @@ -31,6 +31,10 @@ /docs/pe/edge/config/management/ /docs/edge/pe/key-concepts/edge-instance/ 301 /docs/pe/edge/config/provision-asset/ /docs/edge/pe/user-guide/asset-management/ 301 /docs/pe/edge/config/subscribe-to-attribute/ /docs/edge/pe/user-guide/attribute-sync/ 301 +/docs/pe/edge/user-guide/provision-customer/ /docs/edge/pe/user-guide/provision-customers-and-users/ 301 +/docs/pe/edge/user-guide/provision-user/ /docs/edge/pe/user-guide/provision-customers-and-users/ 301 +/docs/pe/edge/user-guide/provision-dashboard/ /docs/edge/pe/user-guide/dashboards/ 301 +/docs/pe/edge/user-guide/edge-proxy/ /docs/edge/pe/user-guide/edge-proxy/debian/ 301 /docs/pe/edge/edge-architecture/ /docs/edge/pe/reference/architecture/ 301 /docs/pe/edge/faq/ /docs/edge/pe/why-thingsboard-edge/ 301 /docs/pe/edge/user-guide/integrations/ /docs/edge/pe/user-guide/integrations/overview/ 301 @@ -142,6 +146,11 @@ /docs/edge/config/provision-entity-view/ /docs/edge/key-concepts/entities/ 301 /docs/edge/config/provision-user/ /docs/edge/user-guide/provision-customers-and-users/ 301 /docs/edge/config/subscribe-to-attribute/ /docs/edge/user-guide/attribute-sync/ 301 +/docs/edge/user-guide/provision-customer/ /docs/edge/user-guide/provision-customers-and-users/ 301 +/docs/edge/user-guide/provision-user/ /docs/edge/user-guide/provision-customers-and-users/ 301 +/docs/edge/user-guide/provision-dashboard/ /docs/edge/user-guide/dashboards/ 301 +/docs/edge/user-guide/edge-proxy/ /docs/edge/user-guide/edge-proxy/debian/ 301 +/docs/pe/reference/configuration-reference/ /docs/pe/reference/ 301 /docs/edge/edge-architecture/ /docs/edge/reference/architecture/ 301 /docs/edge/faq/ /docs/edge/why-thingsboard-edge/ 301 /docs/edge/getting-started-guides/what-is-edge/ /docs/edge/why-thingsboard-edge/ 301 @@ -979,6 +988,7 @@ /docs/paas/eu/recipes/ /docs/paas/eu/user-guide/ 301 # Non-docs redirects (from NON_DOCS_REDIRECTS) +/community/ / 301 /services/support/ /services/ 301 /products/trendz/trndz-request-demo/ /products/trendz/request-demo/ 301 /images/trendz/trndz-request-demo/ /products/trendz/request-demo/ 301 diff --git a/public/redirects.json b/public/redirects.json index 2044bcd23c..4ec60befdd 100644 --- a/public/redirects.json +++ b/public/redirects.json @@ -282,6 +282,15 @@ "/docs/edge/config/provision-user/": "/docs/edge/user-guide/provision-customers-and-users/", "/docs/edge/config/subscribe-to-attribute/": "/docs/edge/user-guide/attribute-sync/", "/docs/pe/edge/config/subscribe-to-attribute/": "/docs/edge/pe/user-guide/attribute-sync/", + "/docs/edge/user-guide/provision-customer/": "/docs/edge/user-guide/provision-customers-and-users/", + "/docs/pe/edge/user-guide/provision-customer/": "/docs/edge/pe/user-guide/provision-customers-and-users/", + "/docs/edge/user-guide/provision-user/": "/docs/edge/user-guide/provision-customers-and-users/", + "/docs/pe/edge/user-guide/provision-user/": "/docs/edge/pe/user-guide/provision-customers-and-users/", + "/docs/edge/user-guide/provision-dashboard/": "/docs/edge/user-guide/dashboards/", + "/docs/pe/edge/user-guide/provision-dashboard/": "/docs/edge/pe/user-guide/dashboards/", + "/docs/edge/user-guide/edge-proxy/": "/docs/edge/user-guide/edge-proxy/debian/", + "/docs/pe/edge/user-guide/edge-proxy/": "/docs/edge/pe/user-guide/edge-proxy/debian/", + "/docs/pe/reference/configuration-reference/": "/docs/pe/reference/", "/docs/edge/edge-architecture/": "/docs/edge/reference/architecture/", "/docs/pe/edge/edge-architecture/": "/docs/edge/pe/reference/architecture/", "/docs/edge/faq/": "/docs/edge/why-thingsboard-edge/", @@ -1917,7 +1926,6 @@ "/docs/pe/edge/user-guide/edge-management/": "/docs/edge/pe/user-guide/edge-management/", "/docs/pe/edge/user-guide/edge-proxy/debian/": "/docs/edge/pe/user-guide/edge-proxy/debian/", "/docs/pe/edge/user-guide/edge-proxy/docker/": "/docs/edge/pe/user-guide/edge-proxy/docker/", - "/docs/pe/edge/user-guide/edge-proxy/": "/docs/edge/pe/user-guide/edge-proxy/", "/docs/pe/edge/user-guide/edge-status-events/": "/docs/edge/pe/user-guide/edge-status-events/", "/docs/pe/edge/user-guide/grpc-keepalive/": "/docs/edge/pe/user-guide/grpc-keepalive/", "/docs/pe/edge/user-guide/grpc-ssl/": "/docs/edge/pe/user-guide/grpc-ssl/", @@ -1929,11 +1937,8 @@ "/docs/pe/edge/user-guide/message-statistics/": "/docs/edge/pe/user-guide/message-statistics/", "/docs/pe/edge/user-guide/ota-updates/": "/docs/edge/pe/user-guide/ota-updates/", "/docs/pe/edge/user-guide/prometheus-metrics/": "/docs/edge/pe/user-guide/prometheus-metrics/", - "/docs/pe/edge/user-guide/provision-customer/": "/docs/edge/pe/user-guide/provision-customer/", "/docs/pe/edge/user-guide/provision-customers-and-users/": "/docs/edge/pe/user-guide/provision-customers-and-users/", - "/docs/pe/edge/user-guide/provision-dashboard/": "/docs/edge/pe/user-guide/provision-dashboard/", "/docs/pe/edge/user-guide/provision-entity-view/": "/docs/edge/pe/user-guide/provision-entity-view/", - "/docs/pe/edge/user-guide/provision-user/": "/docs/edge/pe/user-guide/provision-user/", "/docs/pe/edge/user-guide/public-dashboard/": "/docs/edge/pe/user-guide/public-dashboard/", "/docs/pe/edge/user-guide/queues/": "/docs/edge/pe/user-guide/queues/", "/docs/pe/edge/user-guide/rpc/": "/docs/edge/pe/user-guide/rpc/", diff --git a/src/content/_includes/docs/edge/user-guide/edge-proxy.mdx b/src/content/_includes/docs/edge/user-guide/edge-proxy.mdx deleted file mode 100644 index bcc94b4fc5..0000000000 --- a/src/content/_includes/docs/edge/user-guide/edge-proxy.mdx +++ /dev/null @@ -1,185 +0,0 @@ -import DocLink from '@components/DocLink.astro'; -import Tabs from '@components/Tabs.astro'; -import TabItem from '@components/TabItem.astro'; -import { Aside } from '@astrojs/starlight/components'; - -Running ThingsBoard Edge behind a proxy server means all outbound communication — specifically the gRPC connection to the ThingsBoard server on port 17100 — is routed through the proxy instead of going directly to the internet. - -This setup is common in restricted network environments where direct internet access is deliberately blocked. Proxies also add a security layer by filtering and monitoring outbound traffic, and can cache resources to reduce bandwidth usage. - - - - -## Prerequisites - -- A proxy server (HTTP or HTTPS) with its host, port, and credentials if required. -- A list of addresses that should bypass the proxy (e.g., internal resources). Note that the Debian configuration uses `|` as the separator, not commas. -- Java 17 installed. -- ThingsBoard Edge installed and running. - -## Step 1. Modify the configuration file - -Edit `/etc/tb-edge/conf/tb-edge.conf` to enable the proxy: - -```bash -sudo tee -a /etc/tb-edge/conf/tb-edge.conf > /dev/null <http://localhost:8080 and log in with your tenant credentials. Go to **Edge → Status** and confirm the **Status** field shows **Connected** — this confirms Edge is reaching the server through the proxy. - - - -## Troubleshooting - -Check Edge logs for errors: - -```bash -cat /var/log/tb-edge/tb-edge.log | grep ERROR -``` - -Test connectivity through the proxy: - -```bash -curl -x http://proxy_host:proxy_port https://your_tb_cloud_url -``` - -Confirm the proxy host is reachable: - -```bash -ping proxy_host -traceroute proxy_host -``` - - - - -## Prerequisites - -- A proxy server (HTTP or HTTPS) with its host, port, and credentials if required. -- A list of addresses that should bypass the proxy, including internal resources, the database host (`postgres`), and the ThingsBoard server IP or hostname. -- ThingsBoard Edge installed and running via Docker Compose. -- Docker and Docker Compose installed. - - - -## Step 1. Stop the container - -```bash -docker compose stop -``` - -## Step 2. Update docker-compose.yml - -Open the file: - -```bash -sudo nano docker-compose.yml -``` - -Add the following lines to the `environment` block: - -```yaml - HTTP_PROXY: http://proxy_user:proxy_password@proxy_host:proxy_port - HTTPS_PROXY: http://proxy_user:proxy_password@proxy_host:proxy_port - NO_PROXY: localhost,127.0.0.1,postgres,YOUR_TB_SERVER_IP -``` - -Replace `YOUR_TB_SERVER_IP` with the IP address or hostname of your ThingsBoard server. If your proxy does not require authentication, omit the `proxy_user:proxy_password@` part from the URL. - -- **`HTTP_PROXY` / `HTTPS_PROXY`** — proxy URL for HTTP and HTTPS traffic. Example: `http://user:password@proxy.example.com:8080` -- **`NO_PROXY`** — comma-separated list of addresses that bypass the proxy. Example: `localhost,127.0.0.1,postgres,thingsboard.example.com` - -## Step 3. Restart the containers - -```bash -docker compose up -d && docker compose logs -f mytbedge -``` - -`mytbedge` is the default Edge container name. If you renamed your container, replace it in the command. - -Once started, open the Edge UI at http://localhost:8080 and log in with your tenant credentials. Go to **Edge → Status** and confirm the **Status** field shows **Connected** — this confirms Edge is reaching the server through the proxy. - - - -## Troubleshooting - -Verify proxy environment variables are set: - -```bash -echo $HTTP_PROXY -echo $HTTPS_PROXY -echo $NO_PROXY -``` - -If not set, check inside the running container: - -```bash -docker exec -it container_name printenv | grep -i proxy -``` - -Test internet access through the proxy from inside the container: - -```bash -docker exec -it container_name curl -I https://google.com -``` - -Test connectivity to ThingsBoard Cloud through the proxy: - -```bash -curl -x http://proxy_host:proxy_port https://your_tb_cloud_url -``` - -Check container logs for proxy-related errors: - -```bash -docker logs container_name -``` - - - diff --git a/src/content/_includes/docs/edge/user-guide/provision-customer.mdx b/src/content/_includes/docs/edge/user-guide/provision-customer.mdx deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/content/_includes/docs/edge/user-guide/provision-dashboard.mdx b/src/content/_includes/docs/edge/user-guide/provision-dashboard.mdx deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/content/_includes/docs/edge/user-guide/provision-user.mdx b/src/content/_includes/docs/edge/user-guide/provision-user.mdx deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/content/docs/docs/edge/pe/user-guide/edge-proxy.mdx b/src/content/docs/docs/edge/pe/user-guide/edge-proxy.mdx deleted file mode 100644 index 58bc12730a..0000000000 --- a/src/content/docs/docs/edge/pe/user-guide/edge-proxy.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Connect Edge through a proxy -description: "Configure ThingsBoard Edge to connect to the server through a proxy." ---- -import PageComponent from '@includes/docs/edge/user-guide/edge-proxy.mdx' -import { Products } from '~/models/site.models' - - diff --git a/src/content/docs/docs/edge/pe/user-guide/provision-customer.mdx b/src/content/docs/docs/edge/pe/user-guide/provision-customer.mdx deleted file mode 100644 index 1ce8ddb090..0000000000 --- a/src/content/docs/docs/edge/pe/user-guide/provision-customer.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Provision customer -description: "Provision a customer from the ThingsBoard server to Edge." ---- -import PageComponent from '@includes/docs/edge/user-guide/provision-customer.mdx' -import { Products } from '~/models/site.models' - - diff --git a/src/content/docs/docs/edge/pe/user-guide/provision-dashboard.mdx b/src/content/docs/docs/edge/pe/user-guide/provision-dashboard.mdx deleted file mode 100644 index 12de26ae68..0000000000 --- a/src/content/docs/docs/edge/pe/user-guide/provision-dashboard.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Provision dashboard -description: "Provision a dashboard from the ThingsBoard server to Edge." ---- -import PageComponent from '@includes/docs/edge/user-guide/provision-dashboard.mdx' -import { Products } from '~/models/site.models' - - diff --git a/src/content/docs/docs/edge/pe/user-guide/provision-user.mdx b/src/content/docs/docs/edge/pe/user-guide/provision-user.mdx deleted file mode 100644 index 19f2e4602b..0000000000 --- a/src/content/docs/docs/edge/pe/user-guide/provision-user.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Provision user -description: "Manage user access on ThingsBoard Edge." ---- -import PageComponent from '@includes/docs/edge/user-guide/provision-user.mdx' -import { Products } from '~/models/site.models' - - diff --git a/src/content/docs/docs/edge/user-guide/edge-proxy.mdx b/src/content/docs/docs/edge/user-guide/edge-proxy.mdx deleted file mode 100644 index 1400f1284d..0000000000 --- a/src/content/docs/docs/edge/user-guide/edge-proxy.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Connect Edge through a proxy -description: "Configure ThingsBoard Edge to connect to the server through a proxy." ---- -import PageComponent from '@includes/docs/edge/user-guide/edge-proxy.mdx' -import { Products } from '~/models/site.models' - - diff --git a/src/content/docs/docs/edge/user-guide/provision-customer.mdx b/src/content/docs/docs/edge/user-guide/provision-customer.mdx deleted file mode 100644 index c60b062805..0000000000 --- a/src/content/docs/docs/edge/user-guide/provision-customer.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Provision customer -description: "Provision a customer from the ThingsBoard server to Edge." ---- -import PageComponent from '@includes/docs/edge/user-guide/provision-customer.mdx' -import { Products } from '~/models/site.models' - - diff --git a/src/content/docs/docs/edge/user-guide/provision-dashboard.mdx b/src/content/docs/docs/edge/user-guide/provision-dashboard.mdx deleted file mode 100644 index 81d306febc..0000000000 --- a/src/content/docs/docs/edge/user-guide/provision-dashboard.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Provision dashboard -description: "Provision a dashboard from the ThingsBoard server to Edge." ---- -import PageComponent from '@includes/docs/edge/user-guide/provision-dashboard.mdx' -import { Products } from '~/models/site.models' - - diff --git a/src/content/docs/docs/edge/user-guide/provision-user.mdx b/src/content/docs/docs/edge/user-guide/provision-user.mdx deleted file mode 100644 index 26da81e513..0000000000 --- a/src/content/docs/docs/edge/user-guide/provision-user.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Provision user -description: "Manage user access on ThingsBoard Edge." ---- -import PageComponent from '@includes/docs/edge/user-guide/provision-user.mdx' -import { Products } from '~/models/site.models' - - diff --git a/src/content/docs/docs/pe/reference/configuration-reference.mdx b/src/content/docs/docs/pe/reference/configuration-reference.mdx deleted file mode 100644 index 803f9cd057..0000000000 --- a/src/content/docs/docs/pe/reference/configuration-reference.mdx +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Configuration Reference -description: ThingsBoard Professional Edition configuration reference. ---- - -TODO diff --git a/src/data/redirects.ts b/src/data/redirects.ts index 2712cb2440..d7637305f4 100644 --- a/src/data/redirects.ts +++ b/src/data/redirects.ts @@ -292,6 +292,16 @@ export const SINGLE_REDIRECTS: SingleRedirect[] = [ { oldPath: 'edge/config/provision-user', target: '/docs/edge/user-guide/provision-customers-and-users/' }, { oldPath: 'edge/config/subscribe-to-attribute', target: '/docs/edge/user-guide/attribute-sync/' }, { oldPath: 'pe/edge/config/subscribe-to-attribute', target: '/docs/edge/pe/user-guide/attribute-sync/' }, + // Orphan Edge user-guide pages removed — redirect to their live replacements. + { oldPath: 'edge/user-guide/provision-customer', target: '/docs/edge/user-guide/provision-customers-and-users/' }, + { oldPath: 'pe/edge/user-guide/provision-customer', target: '/docs/edge/pe/user-guide/provision-customers-and-users/' }, + { oldPath: 'edge/user-guide/provision-user', target: '/docs/edge/user-guide/provision-customers-and-users/' }, + { oldPath: 'pe/edge/user-guide/provision-user', target: '/docs/edge/pe/user-guide/provision-customers-and-users/' }, + { oldPath: 'edge/user-guide/provision-dashboard', target: '/docs/edge/user-guide/dashboards/' }, + { oldPath: 'pe/edge/user-guide/provision-dashboard', target: '/docs/edge/pe/user-guide/dashboards/' }, + { oldPath: 'edge/user-guide/edge-proxy', target: '/docs/edge/user-guide/edge-proxy/debian/' }, + { oldPath: 'pe/edge/user-guide/edge-proxy', target: '/docs/edge/pe/user-guide/edge-proxy/debian/' }, + { oldPath: 'pe/reference/configuration-reference', target: '/docs/pe/reference/' }, { oldPath: 'edge/edge-architecture', target: '/docs/edge/reference/architecture/' }, { oldPath: 'pe/edge/edge-architecture', target: '/docs/edge/pe/reference/architecture/' }, { oldPath: 'edge/faq', target: '/docs/edge/why-thingsboard-edge/' }, @@ -1265,6 +1275,9 @@ export const SINGLE_REDIRECTS: SingleRedirect[] = [ * literal `?query` strings (no placeholder substitution). */ export const NON_DOCS_REDIRECTS: Record = { + // Removed marketing page + '/community/': '/', + // Services '/services/support/': '/services/', diff --git a/src/pages/community/index.astro b/src/pages/community/index.astro deleted file mode 100644 index 6a91754021..0000000000 --- a/src/pages/community/index.astro +++ /dev/null @@ -1,192 +0,0 @@ ---- -import BaseLayout from '@layouts/BaseLayout.astro'; ---- - - -
- -
- -
-
- - diff --git a/src/pages/open-graph/_shared/marketing-meta.ts b/src/pages/open-graph/_shared/marketing-meta.ts index 2d384a6049..0480584e39 100644 --- a/src/pages/open-graph/_shared/marketing-meta.ts +++ b/src/pages/open-graph/_shared/marketing-meta.ts @@ -63,7 +63,6 @@ const PREFIX_RULES: PrefixRule[] = [ { prefix: '/services/', section: { sectionName: 'Services' } }, { prefix: '/careers/', section: { sectionName: 'Careers' } }, { prefix: '/partners/', section: { sectionName: 'Partners' } }, - { prefix: '/community/', section: { sectionName: 'Community' } }, { prefix: '/company/', section: { sectionName: 'Company' } }, { prefix: '/clients-feedback/', section: { sectionName: 'Customers' } }, { prefix: '/contact-us/', section: { sectionName: 'Contact' } }, diff --git a/src/util/ogContext.ts b/src/util/ogContext.ts index 64cc86232e..2afcbcf325 100644 --- a/src/util/ogContext.ts +++ b/src/util/ogContext.ts @@ -73,7 +73,6 @@ export const MARKETING_ALLOWLIST: ReadonlyArray = [ '/partners/*', '/services/*', '/careers/*', - '/community/*', '/clients-feedback/', '/mediakit/', '/contact-us/', From ad80ab3b4625da315345c48744c0494f2e4f9a90 Mon Sep 17 00:00:00 2001 From: Ruslan Date: Wed, 1 Jul 2026 13:13:40 +0300 Subject: [PATCH 2/6] fix(iot-hub): guard /iot-hub/ hrefs against empty category slug An item whose itemType has no public category (e.g. DASHBOARD, hidden for the first release) produced /iot-hub///. Guard the card-bind href to '#' and skip unknown types in the single-category grid, matching the existing groupResults/getListingHref pattern. --- src/components/IotHub/iot-hub-dynamic-search.ts | 5 ++++- src/components/IotHub/iot-hub-listing-card-bind.ts | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/components/IotHub/iot-hub-dynamic-search.ts b/src/components/IotHub/iot-hub-dynamic-search.ts index a88fe63a76..836e102512 100644 --- a/src/components/IotHub/iot-hub-dynamic-search.ts +++ b/src/components/IotHub/iot-hub-dynamic-search.ts @@ -340,7 +340,10 @@ export function setupDynamicSearch(): void { // Single-category context (category page) — emit a flat grid // without a section header, matching the static SSR shape. const cat = ITEM_TYPE_BY_TYPE.get(itemType as IotHubItemType); - const categorySlug = cat?.slug ?? ''; + // Unknown item type has no public category — skip rather than emit + // cards with a `/iot-hub//slug/` href (matches groupResults). + if (!cat) return; + const categorySlug = cat.slug; const variant = getCardVariant(itemType); const grid = document.createElement('div'); grid.className = `iot-hub-grid iot-hub-grid--${variant}`; diff --git a/src/components/IotHub/iot-hub-listing-card-bind.ts b/src/components/IotHub/iot-hub-listing-card-bind.ts index 6b1a325301..e26ce676f2 100644 --- a/src/components/IotHub/iot-hub-listing-card-bind.ts +++ b/src/components/IotHub/iot-hub-listing-card-bind.ts @@ -27,8 +27,10 @@ export function bindListingCard( ): void { const variant = getCardVariant(item.itemType); - // Root href. - root.setAttribute('href', `/iot-hub/${categorySlug}/${item.slug}/`); + // Root href. An empty categorySlug (item type with no public category, e.g. + // a type the site doesn't surface) would yield `/iot-hub//slug/` — guard it + // to '#' instead, matching getListingHref. + root.setAttribute('href', categorySlug ? `/iot-hub/${categorySlug}/${item.slug}/` : '#'); // DEVICE cards get a white preview background (vs the light gray default). root.classList.toggle('iot-hub-card--device', item.itemType === 'DEVICE'); From f0d73b865303789d128debb0328431e547851ab7 Mon Sep 17 00:00:00 2001 From: Ruslan Date: Wed, 1 Jul 2026 13:13:40 +0300 Subject: [PATCH 3/6] fix(seo): make /iot-hub/search/ indexable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the noIndex prop — the page is a full paginated IoT Hub catalog listing, a legit index page, not a query-driven search-results page. --- src/pages/iot-hub/search/[...page].astro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iot-hub/search/[...page].astro b/src/pages/iot-hub/search/[...page].astro index 648a1df1d8..3f19ec58ea 100644 --- a/src/pages/iot-hub/search/[...page].astro +++ b/src/pages/iot-hub/search/[...page].astro @@ -82,7 +82,7 @@ const description = 'Search the ThingsBoard IoT Hub catalogue of devices, widgets, rule chains and more.'; --- - +
Date: Wed, 1 Jul 2026 13:13:40 +0300 Subject: [PATCH 4/6] fix(a11y): add alt text to IoT Hub category tiles CategoryTile emitted alt="" for the meaningful category image; use the category label. --- src/components/IotHub/CategoryTile.astro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/IotHub/CategoryTile.astro b/src/components/IotHub/CategoryTile.astro index 8f7d6343d3..347d3e1283 100644 --- a/src/components/IotHub/CategoryTile.astro +++ b/src/components/IotHub/CategoryTile.astro @@ -57,7 +57,7 @@ const href = `/iot-hub/${slug}/`;
- + {label}
From 737138a5015f77af2d65421c3ee8cd1182fd1a17 Mon Sep 17 00:00:00 2001 From: Ruslan Date: Wed, 1 Jul 2026 17:19:37 +0300 Subject: [PATCH 5/6] fix(seo): cover deleted PE edge URLs; add IoT Hub image alt text Orphan-page redirects were added only for the legacy pe/edge/ URL scheme, so the canonical edge/pe/ URLs of the deleted PE stubs 404'd. Add canonical sources (keep legacy aliases for one-hop resolution). Add alt text to the category hero and creator avatar images (creator avatar now exposed to the a11y tree as 'Photo of '), and make the category-tile alt descriptive to avoid a duplicate screen-reader announcement. --- public/_redirects | 4 ++++ public/redirects.json | 4 ++++ src/components/IotHub/CategoryHero.astro | 2 +- src/components/IotHub/CategoryTile.astro | 2 +- src/components/IotHub/CreatorHero.astro | 6 +++--- src/data/redirects.ts | 7 +++++++ 6 files changed, 20 insertions(+), 5 deletions(-) diff --git a/public/_redirects b/public/_redirects index 87484fe9b9..6bf79a1c37 100644 --- a/public/_redirects +++ b/public/_redirects @@ -147,9 +147,13 @@ /docs/edge/config/provision-user/ /docs/edge/user-guide/provision-customers-and-users/ 301 /docs/edge/config/subscribe-to-attribute/ /docs/edge/user-guide/attribute-sync/ 301 /docs/edge/user-guide/provision-customer/ /docs/edge/user-guide/provision-customers-and-users/ 301 +/docs/edge/pe/user-guide/provision-customer/ /docs/edge/pe/user-guide/provision-customers-and-users/ 301 /docs/edge/user-guide/provision-user/ /docs/edge/user-guide/provision-customers-and-users/ 301 +/docs/edge/pe/user-guide/provision-user/ /docs/edge/pe/user-guide/provision-customers-and-users/ 301 /docs/edge/user-guide/provision-dashboard/ /docs/edge/user-guide/dashboards/ 301 +/docs/edge/pe/user-guide/provision-dashboard/ /docs/edge/pe/user-guide/dashboards/ 301 /docs/edge/user-guide/edge-proxy/ /docs/edge/user-guide/edge-proxy/debian/ 301 +/docs/edge/pe/user-guide/edge-proxy/ /docs/edge/pe/user-guide/edge-proxy/debian/ 301 /docs/pe/reference/configuration-reference/ /docs/pe/reference/ 301 /docs/edge/edge-architecture/ /docs/edge/reference/architecture/ 301 /docs/edge/faq/ /docs/edge/why-thingsboard-edge/ 301 diff --git a/public/redirects.json b/public/redirects.json index 4ec60befdd..9c31091973 100644 --- a/public/redirects.json +++ b/public/redirects.json @@ -283,12 +283,16 @@ "/docs/edge/config/subscribe-to-attribute/": "/docs/edge/user-guide/attribute-sync/", "/docs/pe/edge/config/subscribe-to-attribute/": "/docs/edge/pe/user-guide/attribute-sync/", "/docs/edge/user-guide/provision-customer/": "/docs/edge/user-guide/provision-customers-and-users/", + "/docs/edge/pe/user-guide/provision-customer/": "/docs/edge/pe/user-guide/provision-customers-and-users/", "/docs/pe/edge/user-guide/provision-customer/": "/docs/edge/pe/user-guide/provision-customers-and-users/", "/docs/edge/user-guide/provision-user/": "/docs/edge/user-guide/provision-customers-and-users/", + "/docs/edge/pe/user-guide/provision-user/": "/docs/edge/pe/user-guide/provision-customers-and-users/", "/docs/pe/edge/user-guide/provision-user/": "/docs/edge/pe/user-guide/provision-customers-and-users/", "/docs/edge/user-guide/provision-dashboard/": "/docs/edge/user-guide/dashboards/", + "/docs/edge/pe/user-guide/provision-dashboard/": "/docs/edge/pe/user-guide/dashboards/", "/docs/pe/edge/user-guide/provision-dashboard/": "/docs/edge/pe/user-guide/dashboards/", "/docs/edge/user-guide/edge-proxy/": "/docs/edge/user-guide/edge-proxy/debian/", + "/docs/edge/pe/user-guide/edge-proxy/": "/docs/edge/pe/user-guide/edge-proxy/debian/", "/docs/pe/edge/user-guide/edge-proxy/": "/docs/edge/pe/user-guide/edge-proxy/debian/", "/docs/pe/reference/configuration-reference/": "/docs/pe/reference/", "/docs/edge/edge-architecture/": "/docs/edge/reference/architecture/", diff --git a/src/components/IotHub/CategoryHero.astro b/src/components/IotHub/CategoryHero.astro index 1d379ac0d2..8f55f5d593 100644 --- a/src/components/IotHub/CategoryHero.astro +++ b/src/components/IotHub/CategoryHero.astro @@ -72,7 +72,7 @@ const HERO_PLACEHOLDER = diff --git a/src/components/IotHub/CategoryTile.astro b/src/components/IotHub/CategoryTile.astro index 347d3e1283..02b3e24d2c 100644 --- a/src/components/IotHub/CategoryTile.astro +++ b/src/components/IotHub/CategoryTile.astro @@ -57,7 +57,7 @@ const href = `/iot-hub/${slug}/`;
- {label} + {`${label}
diff --git a/src/components/IotHub/CreatorHero.astro b/src/components/IotHub/CreatorHero.astro index 7aab85178c..011a5adffa 100644 --- a/src/components/IotHub/CreatorHero.astro +++ b/src/components/IotHub/CreatorHero.astro @@ -28,11 +28,11 @@ const initials = getInitials(name) || '?';
-