Skip to content

fix: keep private and gated pages out of the search index - #6385

Merged
idoshamun merged 2 commits into
mainfrom
fix/noindex-private-and-gated-pages
Jul 28, 2026
Merged

fix: keep private and gated pages out of the search index#6385
idoshamun merged 2 commits into
mainfrom
fix/noindex-private-and-gated-pages

Conversation

@idoshamun

@idoshamun idoshamun commented Jul 28, 2026

Copy link
Copy Markdown
Member

What

Private squad pages were still served as index, follow. #6322 fixed the robots-tag plumbing, but not the path private squads actually take.

Root cause

getServerSideProps runs unauthenticated, so ensureSourcePermissions in the API rejects every private squad with FORBIDDEN on the first source query. That throws straight past the noindex: !squad.public line into the catch, which returned { props: { handle } } with no seo. _app only renders the page-level NextSeo when a page supplies seo, so those pages fell back to DefaultSeo and advertised as indexable.

The post page has the identical bug: FORBIDDEN is exactly what a post inside a private squad returns from the unauthenticated ISR fetch, and its catch branch also shipped no seo.

Changes

The reported bug

  • squads/[handle]: noindex,nofollow on the error fallback (FORBIDDEN, NOT_FOUND, rate limited). Visibility check is now squad?.public === true, so an unknown/missing public fails closed for both the robots tags and the JSON-LD block.
  • posts/[id]: same fallback fix; shouldNoindexPost also fails closed for post.private and non-public sources, so a page cached before a squad went private cannot stay indexable.

Same class, found while auditing the rest of the pages

  • posts/[id]/index.tsx reintroduced robots through additionalMetaTags, which is what the comment in next-seo.ts explicitly forbids: those are keyed by meta name, escape next/head's dedupe, and would silently override a page-level noindex. Removed. It was redundant with robotsProps.maxImagePreview.
  • Auth-gated squad surfaces with no seo at all: [handle]/analytics, squads/moderate, and [handle]/[token] (personal invite links, private squads included).
  • posts/[id]/analytics: author-only page that emitted a fully indexable seo block.
  • The recruiter app: recruiterSeo is shared by all three recruiter layouts, so every dashboard, opportunity, candidate review, org settings and payment page said index,follow while rendering nothing for a crawler.
  • join/organization: token-bearing org invite links.
  • Auth flows (verification, reset-password, callback) and backoffice/*.

Public squads, posts, feeds, sources, tags and profiles are untouched and keep index,follow with the max-* directives.

Verification

  • Regression tests for every path above: the three squad error codes, unknown visibility (asserts no jsonLd leaks either), private/non-public posts, the post error fallback, and layout-level locks for the gated pages.
  • Full webapp suite passes (44 suites / 306 tests), lint clean, tsc --noEmit reports nothing on the changed files. The strict-changed guard flags only pre-existing nullability backlog in the touched files, left alone.

Not changed, flagging as judgment calls rather than deciding unilaterally: embed/*, image-generator/* and popup/* are non-content utility surfaces that are also indexable today.

https://claude.ai/code/session_01JP6oFXEXeuSsjr6VZQ6KMs

Preview domain

https://fix-noindex-private-and-gated-pa.preview.app.daily.dev

Private squads still rendered as index,follow. getServerSideProps runs
unauthenticated, so the API rejects every private squad with FORBIDDEN
before the `noindex: !squad.public` line is reached, and the catch branch
returned props with no seo at all, falling back to the indexable default.

Same failure mode on the post page, where FORBIDDEN is what every post in
a private squad returns from the unauthenticated ISR fetch.

- squads/[handle]: noindex the error fallback, fail closed when `public`
  is not positively true (robots tags and JSON-LD alike)
- posts/[id]: noindex the error fallback, fail closed for private posts
  and non-public sources, and drop the `robots` additionalMetaTags entry
  that escapes next-seo's dedupe (already covered by robotsProps)
- noindex auth-gated squad surfaces: invite tokens, analytics, moderation
- noindex the recruiter app, post analytics, org invite links, the auth
  flows (verification, reset-password, callback) and backoffice
- regression tests for each path

Claude-Session: https://claude.ai/code/session_01JP6oFXEXeuSsjr6VZQ6KMs
@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
daily-webapp Ready Ready Preview Jul 28, 2026 2:11pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
storybook Ignored Ignored Jul 28, 2026 2:11pm

Request Review

These pages were touched only to attach noindex seo; their strict errors
predate this branch.

Claude-Session: https://claude.ai/code/session_01JP6oFXEXeuSsjr6VZQ6KMs
@idoshamun
idoshamun merged commit f2abf5a into main Jul 28, 2026
12 checks passed
@idoshamun
idoshamun deleted the fix/noindex-private-and-gated-pages branch July 28, 2026 14:12
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.

1 participant