From 2fa13ed8b0dd5bad58340189262779a02ee6a97d Mon Sep 17 00:00:00 2001 From: Haitao Pan Date: Fri, 23 Jan 2026 17:03:28 +0800 Subject: [PATCH] feat: sync blog content from external repo and rename /blog to /blogs --- .gitignore | 2 +- package.json | 4 +- scripts/sync-blog-content.sh | 34 ++++++++ src/app/{blog => blogs}/[...slug]/page.tsx | 4 +- src/app/{blog => blogs}/page.tsx | 0 src/app/sitemap.ts | 4 +- src/components/Navbar.tsx | 90 +++++++++++----------- src/components/blog/BlogList.tsx | 50 +++++------- src/components/home/CommunityFeed.tsx | 6 +- src/lib/marketingContent.ts | 7 +- src/modules/products/xcloudflow.ts | 2 +- src/modules/products/xscopehub.ts | 2 +- src/modules/products/xstream.ts | 2 +- 13 files changed, 115 insertions(+), 92 deletions(-) create mode 100755 scripts/sync-blog-content.sh rename src/app/{blog => blogs}/[...slug]/page.tsx (98%) rename src/app/{blog => blogs}/page.tsx (100%) diff --git a/.gitignore b/.gitignore index 9b1dc25..5cb0995 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,7 @@ public/dl-index/ # Contentlayer cache ui/docs/.contentlayer/ -src/content/blog/ +src/content/blogs/ # Lock files (如果不希望追踪) uyarn.lock diff --git a/package.json b/package.json index b603145..9653509 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ }, "scripts": { "dev": "bash scripts/Dev-MCP-Server.sh && next dev --turbo", - "prebuild": "tsx scripts/generate-content.ts && node scripts/build-contentlayer.mjs", + "prebuild": "bash scripts/sync-blog-content.sh && tsx scripts/generate-content.ts && node scripts/build-contentlayer.mjs", "build": "next build", "build:static": "npm run prebuild && next build", "start": "node ./scripts/start.js", @@ -100,4 +100,4 @@ "glob": "10.5.0" }, "packageManager": "yarn@4.12.0" -} +} \ No newline at end of file diff --git a/scripts/sync-blog-content.sh b/scripts/sync-blog-content.sh new file mode 100755 index 0000000..11b4888 --- /dev/null +++ b/scripts/sync-blog-content.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +set -euo pipefail + +CONTENT_DIR="src/content/blogs" +REPO_URL="https://github.com/cloud-neutral-workshop/knowledge.git" + +# Ensure we're in the project root +cd "$(dirname "$0")/.." + +if [ -d "${CONTENT_DIR}/.git" ]; then + echo "Updating existing git repo in ${CONTENT_DIR}..." + git -C "${CONTENT_DIR}" fetch --depth=1 origin main + git -C "${CONTENT_DIR}" reset --hard origin/main + git -C "${CONTENT_DIR}" clean -fdx + exit 0 +fi + +echo "Syncing content from ${REPO_URL} to ${CONTENT_DIR}..." + +TMP_DIR=$(mktemp -d) +trap 'rm -rf "${TMP_DIR}"' EXIT + +git clone --depth=1 "${REPO_URL}" "${TMP_DIR}/repo" + +mkdir -p "${CONTENT_DIR}" + +# Remove existing content but keep the directory +# Find and delete all files and directories inside CONTENT_DIR, but ignore errors if empty +find "${CONTENT_DIR}" -mindepth 1 -delete 2>/dev/null || true + +# Copy content from repo to content dir, excluding .git +tar -C "${TMP_DIR}/repo" --exclude='.git' -cf - . | tar -C "${CONTENT_DIR}" -xf - + +echo "Content synced successfully." diff --git a/src/app/blog/[...slug]/page.tsx b/src/app/blogs/[...slug]/page.tsx similarity index 98% rename from src/app/blog/[...slug]/page.tsx rename to src/app/blogs/[...slug]/page.tsx index 2506846..0081c9e 100644 --- a/src/app/blog/[...slug]/page.tsx +++ b/src/app/blogs/[...slug]/page.tsx @@ -61,7 +61,7 @@ export default async function BlogPostPage({ params }: PageProps) {
← {post.date ? 'Back to Blog' : '返回博客'} @@ -98,7 +98,7 @@ export default async function BlogPostPage({ params }: PageProps) {
← Back to Blog diff --git a/src/app/blog/page.tsx b/src/app/blogs/page.tsx similarity index 100% rename from src/app/blog/page.tsx rename to src/app/blogs/page.tsx diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts index cc8f0b6..624e27a 100644 --- a/src/app/sitemap.ts +++ b/src/app/sitemap.ts @@ -13,7 +13,7 @@ const staticEntries: MetadataRoute.Sitemap = [ priority: 1, }, { - url: `${baseUrl}/blog`, + url: `${baseUrl}/blogs`, changeFrequency: 'weekly', priority: 0.8, }, @@ -43,7 +43,7 @@ export default async function sitemap(): Promise { const [posts, collections] = await Promise.all([getBlogPosts(), getDocCollections()]) const blogEntries: MetadataRoute.Sitemap = posts.map((post) => ({ - url: `${baseUrl}/blog/${post.slug}`, + url: `${baseUrl}/blogs/${post.slug}`, lastModified: post.date ? new Date(post.date) : undefined, changeFrequency: 'weekly', priority: 0.7, diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index a4fbacd..96c5f35 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -27,9 +27,9 @@ type NavSubItem = { export default function Navbar() { const pathname = usePathname() const isHiddenRoute = pathname - ? ['/login', '/register', '/xstream', '/xcloudflow', '/xscopehub', '/blog'].some((prefix) => - pathname.startsWith(prefix), - ) + ? ['/login', '/register', '/xstream', '/xcloudflow', '/xscopehub', '/blogs'].some((prefix) => + pathname.startsWith(prefix), + ) : false const [menuOpen, setMenuOpen] = useState(false) const [selectedChannels, setSelectedChannels] = useState(['stable']) @@ -98,48 +98,48 @@ export default function Navbar() { const accountChildren: NavSubItem[] = user ? [ - { - key: 'userCenter', - label: accountCopy.userCenter, - href: '/panel', - togglePath: '/panel', - }, - ...(user?.isAdmin || user?.isOperator - ? [ - { - key: 'management', - label: accountCopy.management, - href: '/panel/management', - togglePath: '/panel/management', - } satisfies NavSubItem, - ] - : []), - { - key: 'logout', - label: accountCopy.logout, - href: '/logout', - }, - ] + { + key: 'userCenter', + label: accountCopy.userCenter, + href: '/panel', + togglePath: '/panel', + }, + ...(user?.isAdmin || user?.isOperator + ? [ + { + key: 'management', + label: accountCopy.management, + href: '/panel/management', + togglePath: '/panel/management', + } satisfies NavSubItem, + ] + : []), + { + key: 'logout', + label: accountCopy.logout, + href: '/logout', + }, + ] : [ - { - key: 'register', - label: nav.account.register, - href: '/register', - togglePath: '/register', - }, - { - key: 'login', - label: nav.account.login, - href: '/login', - togglePath: '/login', - }, - { - key: 'demo', - label: nav.account.demo, - href: '/demo', - togglePath: '/demo', - }, - ] + { + key: 'register', + label: nav.account.register, + href: '/register', + togglePath: '/register', + }, + { + key: 'login', + label: nav.account.login, + href: '/login', + togglePath: '/login', + }, + { + key: 'demo', + label: nav.account.demo, + href: '/demo', + togglePath: '/demo', + }, + ] const accountLabel = nav.account.title @@ -194,7 +194,7 @@ export default function Navbar() { { key: 'docs', label: labels.docs, href: '/docs' }, ] - const downloadLink = { key: 'blog', label: labels.download, href: '/blog' } + const downloadLink = { key: 'blog', label: labels.download, href: '/blogs' } const servicesLink = { key: 'services', diff --git a/src/components/blog/BlogList.tsx b/src/components/blog/BlogList.tsx index 4424a5c..cacbcd9 100644 --- a/src/components/blog/BlogList.tsx +++ b/src/components/blog/BlogList.tsx @@ -118,20 +118,18 @@ export default function BlogList({ posts, categories }: BlogListProps) { return ( {tab.label} {labelWithCount ? ( {labelWithCount} @@ -140,18 +138,16 @@ export default function BlogList({ posts, categories }: BlogListProps) { ) })} 全部 {posts.length} @@ -191,7 +187,7 @@ export default function BlogList({ posts, categories }: BlogListProps) {
)} Read more → @@ -204,12 +200,11 @@ export default function BlogList({ posts, categories }: BlogListProps) { {totalPages > 1 && (