-
Notifications
You must be signed in to change notification settings - Fork 200
feat: added dynamic sitemap generation using sitemap.ts in nextjs - 🏗️ #353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f2b6a78
4144ba0
9b61d58
5ab541f
b9d8a2a
2fd2303
a9e70f6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,225 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { MetadataRoute } from 'next' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const WP_API_URL = process.env.NEXT_PUBLIC_WORDPRESS_API_URL || 'https://wp.keploy.io/graphql' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interface WPPostNode { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| slug: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| modified: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| categories?: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nodes: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| slug: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }[] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async function fetchGraphQL<T>(query: string, variables: Record<string, any> = {}): Promise<T | null> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const res = await fetch(WP_API_URL, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| method: 'POST', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headers: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'Content-Type': 'application/json', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| body: JSON.stringify({ query, variables }), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| next: { revalidate: 86400 }, // 24-hour cache | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!res.ok) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error("fetchGraphQL res not ok:", res.status, res.statusText) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const json = await res.json() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return json.data as T | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('WPGraphQL fetch error:', error) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
amaan-bhati marked this conversation as resolved.
Comment on lines
+27
to
+33
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error("fetchGraphQL res not ok:", res.status, res.statusText) | |
| return null | |
| } | |
| const json = await res.json() | |
| return json.data as T | |
| } catch (error) { | |
| console.error('WPGraphQL fetch error:', error) | |
| console.error( | |
| 'fetchGraphQL HTTP error:', | |
| res.status, | |
| res.statusText, | |
| '- please verify the WPGraphQL endpoint URL and check server logs for more details.' | |
| ) | |
| return null | |
| } | |
| const json = await res.json() | |
| if (json && Array.isArray(json.errors) && json.errors.length > 0) { | |
| console.error( | |
| 'fetchGraphQL GraphQL error(s) returned from WPGraphQL. Inspect the query and server logs for details:', | |
| json.errors | |
| ) | |
| return null | |
| } | |
| return json.data as T | |
| } catch (error) { | |
| console.error( | |
| 'WPGraphQL fetch error. Please check network connectivity, the WPGraphQL endpoint configuration, and server logs:', | |
| error | |
| ) |
Copilot
AI
Mar 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These error logs don’t provide a clear next step, and they’ll appear in production if WPGraphQL is transiently unavailable (e.g., rate limiting). Consider improving the message to include actionable guidance (e.g., check WPGraphQL endpoint/env vars, retry later) and/or handling retries/backoff; also consider avoiding logging full errors repeatedly during ISR to reduce log noise.
Copilot
AI
Mar 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fetchAllTaxonomies uses posts(first: 1) without an explicit orderby. This makes lastModified potentially incorrect (often returns most recent by DATE, not by MODIFIED), which undermines the goal of accurate <lastmod> values. Add an explicit order (e.g., order by MODIFIED DESC) to ensure the returned modified is actually the latest for that taxonomy/author.
Copilot
AI
Mar 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are unconditional console.log “DEBUG:” statements in the sitemap generator. This will produce noisy logs during builds/ISR and doesn’t follow the logging guideline here (debug logs should be gated, and error logs should include a clear next step). Please remove these logs or gate them behind an explicit debug flag (e.g., an env var) and keep production output minimal/actionable.
Copilot
AI
Mar 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new sitemap endpoint is SEO-critical but isn’t covered by existing e2e tests. Consider adding a Playwright test that requests /blog/sitemap.xml, asserts a 200 + application/xml content-type, and verifies it contains a few expected URLs.
Copilot
AI
Mar 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are Playwright E2E tests for SEO, but none cover /blog/sitemap.xml. Adding a basic test that requests the sitemap and asserts it returns XML with a few expected URLs (and no obvious 404 targets) would help prevent regressions in sitemap generation and routing alignment.
Copilot
AI
Mar 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sitemap tag URLs are built from tag.slug, but the site’s tag routes/links appear to use the tag name (e.g. components/tag.tsx links to /tag/${name}, and the previous sitemap contained URLs like /tag/Feature%20Flags). Using slug here may create URLs that are inconsistent with internal linking (and can cause duplicate/incorrect indexing). Consider generating tag URLs using the same value the route expects (or update routing to consistently use slugs).
Copilot
AI
Mar 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sitemap currently emits URLs for all WP categories (${baseUrl}/${cat.slug}), but the Next.js routes in this repo only support /technology and /community (no generic category route). If WP ever contains other categories with posts, this will publish invalid URLs to crawlers. Consider filtering categories (and post primaryCategory) to the set of routes the frontend actually serves, or mapping WP categories to supported route segments.
Copilot
AI
Mar 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Author sitemap entries are built from WPGraphQL users.node.slug (/authors/${slug}), but the existing author route (pages/authors/[slug].tsx) generates/looks up slugs via sanitizeAuthorSlug(ppmaAuthorName) derived from posts. These formats likely won’t match, leading to sitemap URLs that 404. Consider deriving author slugs the same way the route does (from ppmaAuthorName) or reusing sanitizeAuthorSlug when building author URLs.
Copilot
AI
Mar 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Author URLs in the sitemap are built from WP user slug, but the site’s author routing uses sanitizeAuthorSlug(ppmaAuthorName) (see components/AuthorMapping.tsx / pages/authors/[slug].tsx). This mismatch can yield non-canonical or even 404 author URLs in the sitemap. Consider deriving author slugs using sanitizeAuthorSlug (e.g., by aggregating author names from posts) or by querying name and sanitizing it instead of using WP slug directly.
Uh oh!
There was an error while loading. Please reload this page.