-
Notifications
You must be signed in to change notification settings - Fork 8
Add SEO features #21
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
Open
seesharprun
wants to merge
10
commits into
documentdb:main
Choose a base branch
from
seesharprun-documentdb-prototype:implement-sitemap
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Add SEO features #21
Changes from 2 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
f8c67e6
Add sitemap functionality for SEO
seesharprun 94d23fa
Split content collection into reusable service
seesharprun a5bf57a
Apply suggestion from @seesharprun
seesharprun bf43978
Enhance SEO image generation
seesharprun 676b4cf
Merge branch 'implement-sitemap' of https://github.com/seesharprun-do…
seesharprun adc6779
Merge branch 'documentdb:main' into implement-sitemap
seesharprun d9251eb
Merge branch 'implement-dynamic-seo-cards' of https://github.com/sees…
seesharprun 2e592f6
Update package-lock
seesharprun 8d4042e
Revert scripts/package.json
seesharprun a6cec3b
Fix bug
seesharprun File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,183 @@ | ||
| import { getAllArticlePaths, getArticleByPath } from './articleService'; | ||
| import { getAllPosts } from './blogService'; | ||
| import { getReferencesGroupedByTypeAndCategory, getAllReferenceParams, getReferenceByPath } from './referenceService'; | ||
| import path from 'path'; | ||
| import { Entity } from '../types/Entity'; | ||
|
|
||
| export function getAllContent(): Entity[] { | ||
| const pages: Entity[] = []; | ||
|
|
||
| // 1. Home page | ||
| pages.push({ | ||
| url: '/', | ||
| slug: 'home.png', | ||
| title: 'DocumentDB', | ||
| description: 'A powerful, scalable open-source document database solution', | ||
| type: 'home', | ||
| }); | ||
|
|
||
| // 2. Docs landing | ||
| pages.push({ | ||
| url: '/docs', | ||
| slug: 'docs.png', | ||
| title: 'Documentation', | ||
| description: 'Complete DocumentDB documentation and guides', | ||
| section: 'docs', | ||
| type: 'landing', | ||
| }); | ||
|
|
||
| // 3. All article/documentation pages | ||
| const articlePaths = getAllArticlePaths(); | ||
| for (const articlePath of articlePaths) { | ||
| const article = getArticleByPath(articlePath.section, articlePath.slug); | ||
| if (article) { | ||
| const selectedNavItem = article.navigation.find((item: any) => | ||
| item.link.includes(articlePath.slug[articlePath.slug.length - 1] || 'index') | ||
| ); | ||
| const title = article.frontmatter.title || selectedNavItem?.title || articlePath.section; | ||
|
|
||
| let url = `/docs/${articlePath.section}`; | ||
| if (articlePath.slug.length > 0) { | ||
| url += `/${articlePath.slug.join('/')}`; | ||
| } | ||
|
|
||
| const mdFilePath = path.join( | ||
| process.cwd(), | ||
| 'articles', | ||
| articlePath.section, | ||
| ...articlePath.slug, | ||
| 'index.md' | ||
| ); | ||
|
|
||
| // Convert URL to slug filename | ||
| const slug = url === '/' | ||
| ? 'home.png' | ||
| : url.slice(1).replace(/\//g, '-') + '.png'; | ||
|
|
||
| pages.push({ | ||
| url, | ||
| slug, | ||
| title, | ||
| description: article.frontmatter.description || `${title} - DocumentDB Documentation`, | ||
| section: articlePath.section, | ||
| type: 'docs', | ||
| filePath: mdFilePath, | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| // 4. Blogs landing | ||
| pages.push({ | ||
| url: '/blogs', | ||
| slug: 'blogs.png', | ||
| title: 'Blog', | ||
| description: 'Latest insights and updates from DocumentDB', | ||
| section: 'blog', | ||
| type: 'landing', | ||
| }); | ||
|
|
||
| // 5. Individual blog posts (external URIs) | ||
| const posts = getAllPosts(); | ||
| for (const post of posts) { | ||
| // Generate slug from title (for external blog posts without slugs) | ||
| const slug = post.title | ||
| .toLowerCase() | ||
| .replace(/[^a-z0-9]+/g, '-') | ||
| .replace(/^-+|-+$/g, ''); | ||
|
|
||
| const url = `/blogs/${slug}`; | ||
| const filename = url.slice(1).replace(/\//g, '-') + '.png'; | ||
|
|
||
| pages.push({ | ||
| url, | ||
| slug: filename, | ||
| title: post.title, | ||
| description: post.description, | ||
| section: 'blog', | ||
| type: 'blog', | ||
| isExternal: true, // Mark as external since these redirect to external URIs | ||
| }); | ||
| } | ||
|
|
||
| // 6. Reference landing page | ||
| pages.push({ | ||
| url: '/docs/reference', | ||
| slug: 'docs-reference.png', | ||
| title: 'API Reference', | ||
| description: 'Complete DocumentDB API reference documentation', | ||
| section: 'reference', | ||
| type: 'landing', | ||
| }); | ||
|
|
||
| // 7. Reference type pages (e.g., /docs/reference/commands) | ||
| const referenceContent = getReferencesGroupedByTypeAndCategory(); | ||
| for (const [type] of Object.entries(referenceContent)) { | ||
| const url = `/docs/reference/${type}`; | ||
| const slug = url.slice(1).replace(/\//g, '-') + '.png'; | ||
|
|
||
| pages.push({ | ||
| url, | ||
| slug, | ||
| title: `${type.charAt(0).toUpperCase() + type.slice(1)} Reference`, | ||
| description: `DocumentDB ${type} reference documentation`, | ||
| section: 'reference', | ||
| type: 'landing', | ||
| }); | ||
| } | ||
|
|
||
| // 8. Reference category pages (e.g., /docs/reference/operators/aggregation) | ||
| for (const [type, categories] of Object.entries(referenceContent)) { | ||
| for (const [category] of Object.entries(categories)) { | ||
| const url = `/docs/reference/${type}/${category}`; | ||
| const slug = url.slice(1).replace(/\//g, '-') + '.png'; | ||
|
|
||
| pages.push({ | ||
| url, | ||
| slug, | ||
| title: `${category} - ${type.charAt(0).toUpperCase() + type.slice(1)}`, | ||
| description: `${category} ${type} reference documentation`, | ||
| section: 'reference', | ||
| type: 'landing', | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| // 9. Individual reference items | ||
| const referenceParams = getAllReferenceParams(); | ||
| for (const param of referenceParams) { | ||
| const reference = getReferenceByPath(param.type, param.category, param.name); | ||
| if (reference) { | ||
| const url = `/docs/reference/${param.type}/${param.category}/${param.name}`; | ||
| const slug = url.slice(1).replace(/\//g, '-') + '.png'; | ||
|
|
||
| const mdFilePath = path.join( | ||
| process.cwd(), | ||
| 'reference', | ||
| param.type, | ||
| param.category, | ||
| `${param.name}.yml` | ||
| ); | ||
|
|
||
| pages.push({ | ||
| url, | ||
| slug, | ||
| title: reference.name || param.name, | ||
| description: reference.description || `${param.name} - DocumentDB Reference`, | ||
| section: 'reference', | ||
| type: 'reference', | ||
| filePath: mdFilePath, | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| // 10. Packages page | ||
| pages.push({ | ||
| url: '/packages', | ||
| slug: 'packages.png', | ||
| title: 'Packages', | ||
| description: 'Download and install DocumentDB packages', | ||
| type: 'packages', | ||
| }); | ||
|
|
||
| return pages; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| // Determine base URL for entire site | ||
| export function getBaseUrl(): string { | ||
| return 'https://documentdb.io'; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| import { MetadataRoute } from 'next'; | ||
| import { getAllContent } from './services/contentService'; | ||
| import { getBaseUrl } from './services/siteService'; | ||
| import { execSync } from 'child_process'; | ||
| import path from 'path'; | ||
|
|
||
| // Required to evaluate at build time | ||
| export const dynamic = 'force-static'; | ||
|
|
||
| // Get the last git commit date for a specific file | ||
| const getGitLastModified = (filePath: string): Date => { | ||
| try { | ||
| // Convert absolute path to relative path from repo root | ||
| const relativePath = path.relative(process.cwd(), filePath).replace(/\\/g, '/'); | ||
| const output = execSync( | ||
| `git log -1 --format=%cI -- "${relativePath}"`, | ||
| { encoding: 'utf-8', cwd: process.cwd() } | ||
| ).trim(); | ||
|
|
||
| return output ? new Date(output) : new Date(); | ||
| } catch (error) { | ||
| console.warn(`Could not get git date for ${filePath}`); | ||
| return new Date(); | ||
| } | ||
| }; | ||
|
|
||
| export default function sitemap(): MetadataRoute.Sitemap { | ||
| const baseUrl = getBaseUrl(); | ||
| const entities = getAllContent(); | ||
|
|
||
| return entities | ||
| .filter(entity => !entity.isExternal) // Exclude external blog posts | ||
| .map(entity => { | ||
| // Determine priority and change frequency based on page type and depth | ||
| let priority = 0.00; | ||
| let changeFrequency: 'yearly' | 'monthly' | 'weekly' = 'yearly'; | ||
|
|
||
| if (entity.type === 'home') { | ||
| priority = 1.0; | ||
| changeFrequency = 'yearly'; | ||
| } else if (entity.type === 'docs') { | ||
| priority = 0.85; | ||
| changeFrequency = 'weekly'; | ||
| } else if (entity.type === 'packages') { | ||
| priority = 0.70; | ||
| changeFrequency = 'weekly'; | ||
| } else if (entity.type === 'reference') { | ||
| priority = 0.55; | ||
| changeFrequency = 'monthly'; | ||
| } else if (entity.type === 'blog') { | ||
| priority = 0.40; | ||
| changeFrequency = 'monthly'; | ||
| } else if (entity.type === 'landing') { | ||
| priority = 0.25; | ||
| changeFrequency = 'monthly'; | ||
| } | ||
|
|
||
| // Get last modified date from git | ||
| const lastModified = entity.filePath | ||
| ? getGitLastModified(entity.filePath) | ||
| : new Date(); | ||
|
|
||
| return { | ||
| url: `${baseUrl}${entity.url}`, | ||
| lastModified, | ||
| changeFrequency, | ||
| priority, | ||
| }; | ||
| }); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| export interface Entity { | ||
| url: string; // Relative URL path (e.g., '/docs/quickstart') | ||
| slug?: string; // Where to save assets (relative path) | ||
| title: string; // Page title | ||
| description: string; // Page description | ||
| section?: string; // Section category (e.g., 'docs', 'blog', 'reference') | ||
| filePath?: string; // Source file path (for git lastModified) | ||
| isExternal?: boolean; // Indicates if the content is external | ||
| type: 'home' | 'landing' | 'docs' | 'blog' | 'reference' | 'packages'; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # robots.txt for DocumentDB documentation site | ||
|
|
||
| # Allow all crawlers | ||
| User-agent: * | ||
| Allow: / | ||
|
|
||
| # Sitemap location | ||
| Sitemap: https://documentdb.io/sitemap.xml | ||
|
|
||
| # Crawl-delay (optional, uncomment if needed) | ||
| # Crawl-delay: 1 |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.