Technical Seo Audit 2026 06 17
Technical SEO audit — public Next.js apps
Date: 2026-06-17
Scope: static review of apps/www, apps/blog, apps/docs, and apps/academy for metadata base URL handling, robots, sitemaps, canonicals, OpenGraph/Twitter defaults, noindex usage, redirects, and public routing behavior. No product changes were made.
Findings#
High — www production metadata depends on NEXT_PUBLIC_VERCEL_ENV, but Cloudflare/OpenNext builds may not set it#
- Files:
apps/www/lib/constants.ts,apps/www/app/layout.tsx,apps/www/next.config.mjs - Evidence:
SITE_ORIGINishttps://www.assistance.bgonly whenprocess.env.NEXT_PUBLIC_VERCEL_ENV === 'production'; otherwise it usesNEXT_PUBLIC_VERCEL_BRANCH_URLor falls back tohttp://localhost:3040. - Why it matters: root metadata uses
metadataBase: new URL(SITE_ORIGIN), OpenGraph image URLs, and canonical resolution fromapps/www/app/layout.tsx. A production build/deploy path that does not set the Vercel-specific public env can emit localhost or preview absolute URLs in SEO metadata. - Recommendation: make the canonical public origin explicit for
www(for exampleNEXT_PUBLIC_SITE_URLwith a production default ofhttps://www.assistance.bg) rather than deriving it from Vercel-only environment names.
High — www sitemap generation is built around legacy Pages Router paths, not current App Router routes#
- Files:
apps/www/internals/generate-sitemap.mjs,apps/www/package.json,apps/www/public/sitemap_www.xml,apps/www/public/robots.txt - Evidence:
apps/www/package.jsonrunsnode ./internals/generate-sitemap.mjsafter build. The generator globspages/*.tsx,pages/**/*.tsx,data/**/*.mdx,_blog/*.mdx,_case-studies/*.mdx,_customers/*.mdx, and_events/*.mdx; it does not globapp/**/page.tsx. Current public routes live underapps/www/app/**/page.tsx. - Why it matters:
apps/www/public/robots.txtadvertiseshttps://www.assistance.bg/sitemap_www.xml, but the generator can omit App Router routes and include legacy/content-derived URLs that may not match the deployed route graph. - Recommendation: replace or update
apps/www/internals/generate-sitemap.mjsto source current App Router routes and current content collections, then regeneratepublic/sitemap.xmlandpublic/sitemap_www.xml.
Medium — sitemap index does not include the Academy sitemap#
- Files:
apps/www/internals/generate-sitemap.mjs,apps/academy/app/sitemap.ts,apps/academy/app/robots.ts - Evidence:
apps/www/internals/generate-sitemap.mjswrites a sitemap index containing only/sitemap_www.xmland/docs/sitemap.xml. Academy exposeshttps://assistance.bg/academy/sitemap.xmlfromapps/academy/app/sitemap.tsand advertises it fromapps/academy/app/robots.ts. - Why it matters: if Search Console or crawlers discover only the root sitemap index, Academy URLs are not included there. Crawlers can still discover Academy via its own robots file when they request
/academy/robots.txt, but the root index is incomplete for the public app set. - Recommendation: include the Academy sitemap in the root sitemap index if Academy is intended to be discoverable from the main property sitemap submission.
Medium — Docs has environment-specific robots controls, but no App Router robots.ts or sitemap.ts#
- Files:
apps/docs/public/robots.txt,apps/docs/internals/generate-sitemap.ts,apps/docs/next.config.mjs,apps/docs/app/layout.tsx - Evidence: docs relies on static
public/robots.txtand generatedpublic/sitemap.xml; there are noapps/docs/app/robots.tsorapps/docs/app/sitemap.tsfiles.apps/docs/next.config.mjsaddsX-Robots-Tag: allfor hostassistance.bgandX-Robots-Tag: noindexfor preview hosts matching*.vercel.appor*.pages.dev.apps/docs/app/layout.tsxalso sets page-level robots fromNEXT_PUBLIC_VERCEL_ENV === 'production'. - Why it matters: the static robots/sitemap path is valid, but page metadata and response headers use different environment/host signals. A production Cloudflare route on
www.assistance.bg/docs/*depends on the header host matching behavior and may not align with the Vercel-specific metadata flag. - Recommendation: standardize docs indexability on deployment host/origin configuration and consider App Router
robots.ts/sitemap.tsif runtime-generated route metadata becomes necessary.
Low — Blog and Academy have stronger App Router SEO primitives than www/Docs#
- Files:
apps/blog/app/layout.tsx,apps/blog/app/robots.ts,apps/blog/app/sitemap.ts,apps/academy/app/layout.tsx,apps/academy/app/robots.ts,apps/academy/app/sitemap.ts - Evidence: Blog defines
metadataBase, root canonical, OpenGraph/Twitter defaults,robots.ts, andsitemap.ts. Academy definesmetadataBase, root canonical, OpenGraph/Twitter defaults, protected-route noindex metadata,robots.ts, andsitemap.ts. - Note: Blog defaults
SITE_ORIGINtohttps://assistance.bg/blog(apps/blog/lib/constants.ts) while deployment documentation references bothwww.assistance.bg/blogand Cloudflare Worker/custom-domain options. Confirm the intended canonical host before changing.
Low — Noindex usage is targeted and limited#
- Files:
apps/www/app/dashboard/sign-in/page.tsx,apps/academy/app/(protected)/layout.tsx,apps/blog/app/services/[slug]/page.tsx,apps/docs/app/not-found.tsx,apps/docs/next.config.mjs - Evidence: noindex appears on auth/protected/moved/404 surfaces and docs preview-host headers. No broad accidental
noindexwas found in the audited public app code. - Recommendation: keep this pattern; avoid adding route-group-level robots metadata without verifying child route inheritance.
Static verification performed#
bash
1find apps/www apps/blog apps/docs apps/academy -path '*/app/*' \2 \( -name 'robots.ts' -o -name 'sitemap.ts' -o -name 'layout.tsx' -o -name 'page.tsx' \) -printbash
1rg -n "metadataBase|alternates|canonical|openGraph|twitter|robots|noindex|sitemap|redirect|permanentRedirect|NextResponse.redirect|SITE_URL|NEXT_PUBLIC_SITE|X-Robots-Tag" \2 apps/www apps/blog apps/docs apps/academy apps/*/next.config.mjs -Sbash
1find apps/www apps/docs -path '*/app/*' \( -name 'robots.ts' -o -name 'sitemap.ts' \) -print2find apps/www -name '*sitemap*' -o -name '*robots*' | sort3find apps/docs -name '*sitemap*' -o -name '*robots*' | sortbash
1rg -n "generate-sitemap|sitemap" package.json apps/*/package.json turbo.json .mise.toml -S