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
30 changes: 30 additions & 0 deletions app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,36 @@ export default async function BlogPostPage({ params }: BlogPostPageProps) {
</aside>
) : null}
</div>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
"@context": "https://schema.org",
"@type": "BlogPosting",
headline: post.title,
description: post.description,
image: shouldShowImage(post.image) ? post.image : undefined,
datePublished: post.date,
dateModified: post.date,
author: {
"@type": "Person",
name: post.author
},
publisher: {
"@type": "Organization",
name: "RustFS",
logo: {
"@type": "ImageObject",
url: "https://rustfs.com/images/rustfs-logo.png"
}
},
mainEntityOfPage: {
"@type": "WebPage",
"@id": `${SITE_CONFIG.primaryDomain}/blog/${post.slug}/`
}
})
}}
/>
</div>
</article>
</main>
Expand Down
25 changes: 24 additions & 1 deletion app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export const metadata: Metadata = {
alternates: { canonical: "/" },
title: "RustFS | High-Performance S3 Object Storage for AI & Cloud-Native",
description: 'RustFS is an open-source, Apache 2.0-licensed distributed object storage system built in Rust. A high-performance, drop-in replacement for MinIO and Amazon S3 engineered for AI workloads.',
keywords: 'RustFS, object storage, distributed storage, open source, Rust, Amazon S3, MinIO alternative, MinIO migration, Apache 2.0, cloud native storage, AI infrastructure',
authors: [{ name: 'RustFS Team' }],
openGraph: {
title: "RustFS | High-Performance S3 Object Storage for AI & Cloud-Native",
Expand Down Expand Up @@ -50,6 +49,30 @@ export default async function HomePage() {
<HomeBlog />
<HomeContactCard />
</div>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
"@context": "https://schema.org",
"@type": "Organization",
name: "RustFS",
url: "https://rustfs.com",
logo: "https://rustfs.com/images/rustfs-logo.png",
description: "RustFS is an open-source, Apache 2.0-licensed distributed object storage system built in Rust.",
foundingDate: "2024",
sameAs: [
"https://github.com/rustfs/rustfs",
"https://x.com/rustfsofficial",
"https://discord.gg/rustfs"
],
contactPoint: {
"@type": "ContactPoint",
contactType: "sales",
url: "https://rustfs.com/contact-us/"
}
})
}}
/>
</main>
);
}
2 changes: 1 addition & 1 deletion components/business/home-blog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default async function HomeBlog({ className }: HomeBlogProps) {
<div className="relative aspect-[16/7] overflow-hidden border-b border-border bg-background">
<img
src={featuredPost.image}
alt=""
alt={featuredPost.title}
className="h-full w-full object-cover transition duration-300 group-hover:scale-[1.02]"
loading="lazy"
/>
Expand Down
64 changes: 60 additions & 4 deletions scripts/generate-sitemap.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import fs from 'node:fs';
import path from 'node:path';
import { execSync } from 'node:child_process';
import { pathToFileURL } from 'node:url';

// Configuration
Expand All @@ -22,6 +23,61 @@ const PAGE_CHANGE_FREQ = {
'/download/': 'monthly',
}


/**
* Get the last git commit date for a given directory/file path.
* Falls back to current time if git is unavailable or path is untracked.
*/
function getGitLastMod(filePath) {
try {
const result = execSync(
`git log -1 --format=%cI -- "${filePath}"`,
{ encoding: 'utf8', timeout: 3000 }
).trim();
if (result) return result;
} catch {
// git not available or path not in repo; fall through
}
return new Date().toISOString();
}

const URL_SOURCE_MAP = {
'/': ['app/page.tsx', 'app/layout.tsx'],
'/download/': ['app/download/page.tsx'],
'/download/server/': ['app/download/server/page.tsx'],
'/download/cli/': ['app/download/cli/page.tsx'],
'/pricing/': ['app/pricing/page.tsx'],
'/about/': ['app/about/page.tsx'],
}

function urlToSourcePath(url) {
if (URL_SOURCE_MAP[url]) return URL_SOURCE_MAP[url];
if (url.startsWith('/blog/') && url !== '/blog/' && !url.startsWith('/blog/tag/')) {
const slug = url.replace('/blog/', '').replace(/\/$/, '');
// Blog dirs are content/blog/<date>-<slug>/index.mdx
const matchingDirs = fs.readdirSync('content/blog').filter(d => d.endsWith(slug));
if (matchingDirs.length > 0) {
return [`content/blog/${matchingDirs[0]}/index.mdx`];
}
return [`content/blog/${slug}/index.mdx`];
}
if (url.startsWith('/product/')) {
return [`app${url}page.tsx`];
}
return [`app${url}page.tsx`];
}

function getLastMod(url) {
const sourcePaths = urlToSourcePath(url);
let latestDate = null;
for (const src of sourcePaths) {
if (!fs.existsSync(src)) continue;
const date = getGitLastMod(src);
if (!latestDate || date > latestDate) latestDate = date;
}
return latestDate || new Date().toISOString();
}

// Scan directory and generate URL list
function scanDirectory(dirPath, basePath = '') {
const urls = []
Expand Down Expand Up @@ -62,18 +118,16 @@ function getPageChangeFreq(url) {

// Generate sitemap XML
function generateSitemap(urls) {
const now = new Date().toISOString()

let xml = '<?xml version="1.0" encoding="UTF-8"?>\n'
xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n'

for (const url of urls) {
const lastmod = getLastMod(url)
xml += ' <url>\n'
xml += ` <loc>${BASE_URL}${url}</loc>\n`
xml += ` <lastmod>${now}</lastmod>\n`
xml += ` <lastmod>${lastmod}</lastmod>\n`
xml += ` <changefreq>${getPageChangeFreq(url)}</changefreq>\n`
xml += ` <priority>${getPagePriority(url)}</priority>\n`

xml += ' </url>\n'
}

Expand Down Expand Up @@ -129,6 +183,8 @@ function main() {
console.log(`📝 Found ${urls.length} URLs:`)
urls.forEach(url => console.log(` ${url}`))

console.log('🕐 Fetching git commit dates for realistic lastmod values...');

// Generate sitemap
const sitemap = generateSitemap(urls)

Expand Down