Skip to content

Fix Semrush Site Audit findings: redirects, email obfuscation, titles, internal links - #163

Merged
vpetersson merged 7 commits into
sbomify:masterfrom
vpetersson-bot:fix/semrush-site-audit-20261025
Oct 25, 2026
Merged

vpetersson merged 7 commits into
sbomify:masterfrom
vpetersson-bot:fix/semrush-site-audit-20261025

Conversation

@vpetersson-bot

Copy link
Copy Markdown
Contributor

Fixes for findings from a Semrush Site Audit of sbomify.com. One commit per area.

What changed

  • Redirect chains (every page): the footer Slack links pointed at https://sbomify.com/slack, a Cloudflare redirect to join.slack.com, which redirects again. They now link the invite URL directly (single source in data/main.yml, plus two links on the pricing page). Trade-off: rotating the invite now takes a commit, not a Cloudflare rule change. Also fixed the other links that only resolved through a redirect: a case study link with no trailing slash, the LinkedIn company URL with no trailing slash, and two old app.sbomify.com public pages that now redirect (one to a login wall) and have moved to trust.sbomify.com.
  • Broken internal links / 4xx on /cdn-cgi/l/email-protection: this came from Cloudflare's Email Address Obfuscation (Scrape Shield). It rewrites every mailto: link, and every email-shaped string outside code blocks, into a link to /cdn-cgi/l/email-protection. That path 404s for crawlers and for anyone without JavaScript. The strings it caught were PURLs in inline code, such as pkg:pypi/name@1.2.3, on the FAQ and sbomify-action configuration pages. The <!--email_off--> markers in partials/content.html used to wrap only fenced code blocks. They now wrap all rendered content. The site only shows public role addresses (hello@, privacy@, security@).
  • Title element too long (6 pages): set the existing seo_title front matter so each <title> fits in about 60 characters. The <h1> keeps the full headline.
  • Tag/category pages: current Hugo picks _default/taxonomy.html over _default/term.html for term pages, so term.html was never used. Term pages showed only a grid of titles, with no descriptions and no pagination, which is why they were flagged for low word count and low text-to-HTML ratio. Both kinds now render from taxonomy.html, which branches on .Kind, and the unused term.html is gone.
  • Pages with only one internal link (28): FAQ answers now list related questions (keyword matches plus the neighbouring questions). Compliance framework pages now list the other frameworks. The blog index now links /categories/ and /tags/, which nothing linked to before. That was the reason single-post tags had only one inbound link. Term pages also link back to their index and the blog.
  • Low semantic HTML usage (code-heavy guides and runtime pages): those pages already use header/main/article/nav. Most of their elements were Chroma's unstyled wrapper spans: two per code line plus one per whitespace run. The code block render hook now unwraps them. Highlighted lines (hl_lines) are left alone. On /guides/cpp/ the span count drops from 942 to 430.
  • Links with no anchor text: the footer social icons, author bio icons and About page LinkedIn icons carried their name only in aria-label/title. The name is now in an sr-only span, so crawlers see anchor text and screen readers announce the same name.

How it was verified

  • bun run build:css and hugo --minify --environment production (Hugo extended 0.168.0, the same "latest" version CI installs) build with no errors. bun run lint:markdown passes.
  • I scanned the built public/ with scripts:
    • No internal link resolves to a missing page, a page without its trailing slash, or an alias redirect.
    • No anchor lacks text.
    • No email-shaped string sits outside an email_off region.
    • Every page in the audit's one-inbound-link list now has at least two inbound internal links.
  • Spot-checked the built HTML:
    • /privacy/ now has a plain mailto: link.
    • The six <title>s are shortened, and their <h1>s are unchanged.
    • Code blocks keep their line breaks, and the copy button still uses innerText.
    • /tags/pqc/ shows post cards, and the compliance and FAQ related lists render.
  • Checked the live redirect targets with curl before changing the links.

Not addressed

  • No HSTS support (sbomify.com and www): the site is served from GitHub Pages behind Cloudflare, and nothing in this repo sets response headers (the Dockerfile is only for local development). Enable it in Cloudflare (SSL/TLS > Edge Certificates > HTTP Strict Transport Security).
  • Redirect via http://www.sbomify.com: it goes to https://www.sbomify.com/ and then to https://sbomify.com/. That is Cloudflare configuration. A single redirect rule straight to https://sbomify.com/ would remove the extra hop.
  • Email obfuscation, Cloudflare side: the alternative to the markers is to turn off Scrape Shield > Email Address Obfuscation for the zone.
  • Nofollow attributes in external links: intentional. Outbound links get rel="nofollow noopener noreferrer" by site policy ([params.links] in hugo.toml, documented in CLAUDE.md).
  • Content not optimized / remaining low word count: these need content writing.
  • Blocked from crawling /resources/: the page sets noindex: true on purpose.
  • Pages with utm_* query strings: these URLs come from links in the app and trust center (another repo). They resolve to the homepage, which has a canonical URL.
  • Other long titles: about 70 more pages that the audit did not crawl also have <title>s over 65 characters. Shortening them is an editorial choice, so it is left for a follow-up.
  • https://app.sbomify.com CTA links: they redirect through the app's login flow, which is outside this repo.

🤖 Generated with Claude Code

vpetersson-bot and others added 7 commits October 25, 2026 11:08
Semrush Site Audit reported a redirect chain on every page. The footer
and social links pointed at https://sbomify.com/slack, which 302s to
join.slack.com, which redirects again to the workspace invite. Link the
invite URL directly (single source in data/main.yml, plus the two
pricing page links).

Also fix the remaining internal links that only resolved via a redirect:
a case study link without its trailing slash, the LinkedIn URL without
its trailing slash, and two old app.sbomify.com public pages that now
redirect (to a login wall, or to the trust center).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
Semrush Site Audit reported broken internal links and a 4xx page at
/cdn-cgi/l/email-protection. Cloudflare's Email Address Obfuscation
rewrites every mailto: link, and every email-shaped string outside code
blocks (PURLs such as pkg:pypi/name@1.2.3 in inline code), into a link
to that path, which 404s for crawlers and for visitors without
JavaScript.

The <!--email_off--> markers only wrapped fenced code blocks. Wrap the
whole rendered content instead; the addresses on the site are public
role addresses that are also listed in security.txt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
Semrush Site Audit flagged six pages whose <title> runs past ~70
characters. Set the existing seo_title front matter on them so the
<title> fits the search result display limit, while the visible <h1>
keeps the full editorial headline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
Current Hugo resolves term pages (/tags/sbom/) to _default/taxonomy.html
ahead of _default/term.html, so term.html was never used: term pages
rendered as a bare grid of post titles, with no descriptions and no
pagination, even though paginator.html already paginated them for the
rel=prev/next links. Semrush Site Audit flagged most of them for low
word count and low text to HTML ratio.

Render both kinds from taxonomy.html, branching on .Kind, and drop the
dead term.html. Term pages also link back to their taxonomy index and
the blog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
Semrush Site Audit listed pages that only one internal link points to:
most FAQ answers (linked only from /faq/), the UK Software Security
Code of Practice page (linked only from /compliance/), and tags used by
a single post (/tags/ and /categories/ were not linked from anywhere).

- FAQ answers list related questions (keyword matches plus the
  neighbouring questions in FAQ order).
- Compliance framework pages list the other frameworks.
- The blog index links the category and topic indexes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
Semrush Site Audit flagged the code-heavy guides and runtime pages for
low semantic HTML usage. The pages already use header/main/article/nav,
but Chroma wraps each code line in two spans (.line > .cl) and each run
of whitespace in a third (.w), which made up over a third of all
elements on those pages. None of them are styled, so unwrap them in the
code block render hook. This also trims the HTML size of every page
with code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
Semrush Site Audit reported links with no anchor text. The footer
social links, author bio links and the About page LinkedIn links held
only a decorative icon, with the name in aria-label or title, which
crawlers do not treat as anchor text. Put the name in an sr-only span
instead; screen readers announce the same name as before.

assets/css/styles.css is regenerated with bun run build:css, which also
picks up sm:grid-cols-2 used by the compliance framework list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
@vpetersson
vpetersson merged commit 9b273bc into sbomify:master Oct 25, 2026
2 checks passed
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