Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions apps/web/src/app/robots.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type { MetadataRoute } from "next";

const DEFAULT_SITE_URL = "https://www.solid-connection.com";

const getSiteUrl = () => (process.env.NEXT_PUBLIC_WEB_URL ?? DEFAULT_SITE_URL).replace(/\/$/, "");

export default function robots(): MetadataRoute.Robots {
const siteUrl = getSiteUrl();
const vercelEnv = process.env.VERCEL_ENV;
const isNonIndexEnvironment =
vercelEnv === "preview" ||
vercelEnv === "development" ||
siteUrl.includes("stage") ||
siteUrl.includes("localhost") ||
siteUrl.includes("127.0.0.1");

if (isNonIndexEnvironment) {
return {
rules: {
userAgent: "*",
disallow: "/",
},
};
}

return {
rules: {
userAgent: "*",
allow: "/",
},
sitemap: `${siteUrl}/sitemap.xml`,
host: new URL(siteUrl).host,
};
}
42 changes: 42 additions & 0 deletions apps/web/src/app/sitemap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { MetadataRoute } from "next";

const DEFAULT_SITE_URL = "https://www.solid-connection.com";

const getSiteUrl = () => (process.env.NEXT_PUBLIC_WEB_URL ?? DEFAULT_SITE_URL).replace(/\/$/, "");

export default function sitemap(): MetadataRoute.Sitemap {
const siteUrl = getSiteUrl();

if (siteUrl.includes("stage") || siteUrl.includes("localhost") || siteUrl.includes("127.0.0.1")) {
return [];
}

const lastModified = new Date();

return [
{
url: `${siteUrl}/`,
lastModified,
changeFrequency: "daily",
priority: 1,
},
{
url: `${siteUrl}/mentor`,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Remove auth-gated URLs from sitemap entries

The sitemap now includes /mentor, but this route is still listed in loginNeedPages in middleware.ts and redirects unauthenticated requests to /login. Search crawlers will therefore hit a redirect (or login wall) for a URL advertised as indexable, which can produce sitemap/indexing errors and weakens crawl quality. Only publicly accessible canonical URLs should be emitted here.

Useful? React with 👍 / 👎.

lastModified,
changeFrequency: "weekly",
priority: 0.8,
},
{
url: `${siteUrl}/university`,
lastModified,
changeFrequency: "weekly",
priority: 0.8,
},
{
url: `${siteUrl}/terms`,
lastModified,
changeFrequency: "yearly",
priority: 0.5,
},
];
}
2 changes: 1 addition & 1 deletion apps/web/src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,6 @@ export function middleware(request: NextRequest) {
}
export const config = {
matcher: [
"/((?!api|_next/static|_next/image|static/chunks|images|assets|favicon.ico|sw.js|viewer|fonts|.*\\.splat).*)",
"/((?!api|_next/static|_next/image|static/chunks|images|assets|favicon.ico|robots.txt|sitemap.xml|sw.js|viewer|fonts|.*\\.splat).*)",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Escape literal dots in matcher exclusions

The new matcher exclusions robots.txt and sitemap.xml are interpreted as regex fragments, so . matches any character and the pattern is prefix-based; this now skips middleware for paths like /sitemap.xml.php or /robotsXtxt, not just the two metadata files. In those cases, isProbePath and auth redirect checks are bypassed entirely, which regresses the probe-blocking behavior this middleware currently enforces. Please make these exclusions exact/literal (e.g., escaped dots and bounded matching) so only /robots.txt and /sitemap.xml are exempted.

Useful? React with 👍 / 👎.

],
};
Loading