Skip to content

fix(seo): move noindex logic from middleware.ts into proxy.ts#44

Merged
JohnRDOrazio merged 2 commits intomainfrom
fix/move-noindex-into-proxy
Apr 30, 2026
Merged

fix(seo): move noindex logic from middleware.ts into proxy.ts#44
JohnRDOrazio merged 2 commits intomainfrom
fix/move-noindex-into-proxy

Conversation

@JohnRDOrazio
Copy link
Copy Markdown
Member

@JohnRDOrazio JohnRDOrazio commented Apr 30, 2026

Summary

Hotfix. Next.js 16 deprecated middleware.ts in favor of
proxy.ts. The repo already had proxy.ts (using next-intl for
locale routing); PR #42 unknowingly added middleware.ts alongside
it, and Next.js refuses to build with both:

Error: Both middleware file "./middleware.ts" and proxy file
"./proxy.ts" are detected. Please use "./proxy.ts" only.

Production deploy run 25180664827
failed at build with this error after PRs #42 + #43 merged.

Fix

  • Delete middleware.ts
  • Compose the noindex logic into proxy.ts as a custom proxy()
    function:
    1. Run next-intl middleware on the routes it owns (existing
      exclusion regex /(api|_next|wp-admin|wp-login|wp-json|graphql|wp-content|favicon.ico|logo.svg|.*\..*))
    2. Pass through otherwise
    3. Set X-Robots-Tag: noindex, nofollow on any non-production
      host (allowlist derived from NEXT_PUBLIC_SITE_URL with safe
      fallback, same logic as before)
  • Broaden the matcher from the previous intl-only exclusion to
    /((?!_next/static|_next/image).*) so the noindex header reaches
    /api/*, /robots.txt, and /sitemap*.xml on staging too.
    Locale routing is gated by an in-function regex check so the
    broader matcher doesn't change intl behavior.

Test plan

  • npm run build clean locally; route summary shows
    ƒ Proxy (Middleware) confirming proxy is wired
  • Merge → re-run Build and Deploy workflow_dispatch →
    confirm build succeeds and deploys
  • curl -I https://catholicdigitalcommons.org/ → no
    X-Robots-Tag
  • After staging redeploy: curl -I https://staging.catholicdigitalcommons.org/api/sitemap
    X-Robots-Tag: noindex, nofollow

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor
    • Consolidated request-handling logic into a single proxy layer, removing the separate middleware file.
    • Improved internationalization routing with explicit pathname exclusions so some paths bypass locale routing.
    • Broadened route coverage for non-production environments so more responses (including API/robots/sitemap) inherit search-engine noindex behavior.

Next.js 16 deprecated middleware.ts in favor of proxy.ts. The repo
already had proxy.ts (using next-intl/middleware for locale routing),
and PR #42 unknowingly added middleware.ts alongside it. Next.js
refuses to build with both files:

  Error: Both middleware file "./middleware.ts" and proxy file
  "./proxy.ts" are detected. Please use "./proxy.ts" only.

Production deploy run 25180664827 failed at build with this error.

Fix:
- Delete middleware.ts.
- Fold the host-allowlist + X-Robots-Tag logic into proxy.ts as a
  composed proxy() function: it runs next-intl middleware on the
  routes intl owns (existing exclusion regex), passes through
  otherwise, then sets X-Robots-Tag: noindex, nofollow on any
  non-production host.
- Broaden the matcher from the previous intl-only exclusion to
  '/((?!_next/static|_next/image).*)' so the noindex header also
  reaches /api/*, /robots.txt, and /sitemap*.xml on staging.
  Locale routing is gated by an in-function regex check so the
  broader matcher doesn't change intl behavior.

Verified locally: npm run build completes; route summary shows
"ƒ Proxy (Middleware)" indicating the proxy is wired in.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8de18f59-e9b8-463e-9344-4d4b5bded1e3

📥 Commits

Reviewing files that changed from the base of the PR and between 1d6e0bb and 42be21c.

📒 Files selected for processing (1)
  • proxy.ts

📝 Walkthrough

Walkthrough

The removed middleware.ts (robot-exclusion logic) is consolidated into proxy.ts. proxy is refactored from a middleware-creator constant to an exported function that conditionally bypasses next-intl routing for INTL_EXCLUDE paths, normalizes hostnames into a production allowlist, and sets X-Robots-Tag: noindex, nofollow for non-production hosts. The middleware matcher is widened to exclude only Next.js internals.

Changes

Cohort / File(s) Summary
Removed middleware
middleware.ts
File deleted. Previously computed production hostnames from NEXT_PUBLIC_SITE_URL, normalized www./bare variants, and added X-Robots-Tag: noindex, nofollow for non-production hosts via Next.js middleware.
Proxy refactor & matcher update
proxy.ts
Export changed from const proxy = createMiddleware(routing) to export function proxy(request: NextRequest). Integrates prior middleware host-allowlist and robots header logic, adds conditional early-return for INTL_EXCLUDE paths, lowercases hostnames, and widens config.matcher from the previous exclusion list to `'/((?!_next/static

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰
I hopped from middleware hill to proxy glade,
Where hostnames meet the allowlist's shade,
Robots hush on staging's floor,
One file gone, the headers roar,
A little rabbit cheers, and hops some more!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: moving the noindex SEO logic from middleware.ts (removed) into proxy.ts (modified).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/move-noindex-into-proxy

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented Apr 30, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 10 complexity · 0 duplication

Metric Results
Complexity 10
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@JohnRDOrazio
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@proxy.ts`:
- Around line 52-58: The INTL_EXCLUDE regex used in proxy() is too permissive
and excludes paths that merely start with those names (e.g., /apiary); tighten
it by requiring a segment boundary or exact filename: update the INTL_EXCLUDE
pattern so each literal (api, _next, wp-admin, wp-login, wp-json, graphql,
wp-content, favicon.ico, logo.svg) is matched only if followed by end-of-string
or a slash (or in the case of filenames, end-of-string), e.g. use grouping with
(?:$|/) or explicit filename anchors; keep the proxy() flow using that
INTL_EXCLUDE and still call intlProxy(request) when it does not match.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a169253d-ffee-4439-9587-120889b2252a

📥 Commits

Reviewing files that changed from the base of the PR and between 843840f and 1d6e0bb.

📒 Files selected for processing (2)
  • middleware.ts
  • proxy.ts
💤 Files with no reviewable changes (1)
  • middleware.ts

Comment thread proxy.ts Outdated
CodeRabbit caught a soundness bug in the regex: literals like `api`,
`_next`, `wp-json`, `graphql` matched anything starting with those
strings, so paths like `/apiary`, `/_nextish`, `/wp-jsonary`,
`/graphqlbang` were wrongly excluded from next-intl routing.

Tightened so each path-segment literal must be followed by `/` or
end-of-string, and filename literals (`favicon.ico`, `logo.svg`) must
anchor to end. The trailing `.*\..*` keeps catching asset-like paths
containing a dot.

Smoke-tested 26 cases including all the suffix-attack paths,
genuinely-excluded paths, and intl-eligible paths. All pass.
\`npm run build\` still succeeds locally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@JohnRDOrazio
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@JohnRDOrazio JohnRDOrazio merged commit 2663d91 into main Apr 30, 2026
9 checks passed
@JohnRDOrazio JohnRDOrazio deleted the fix/move-noindex-into-proxy branch April 30, 2026 19:59
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