diff --git a/app/pages/blog/[...slug].example.vue b/app/pages/blog/[...slug].example.vue deleted file mode 100644 index 57c5398..0000000 --- a/app/pages/blog/[...slug].example.vue +++ /dev/null @@ -1,195 +0,0 @@ - - - diff --git a/app/pages/blog/[...slug].vue b/app/pages/blog/[...slug].vue index 896313b..e529ff6 100644 --- a/app/pages/blog/[...slug].vue +++ b/app/pages/blog/[...slug].vue @@ -56,6 +56,8 @@ const siteUrl = 'https://aliarghyani.vercel.app' // TODO: Move to runtime config // Custom meta tags if (post.value) { const postData = post.value as any + const canonicalPath = postData.path ? postData.path.replace(/^\/(en|fa)/, '') : '' + const canonicalUrl = canonicalPath ? `${siteUrl}${canonicalPath}` : siteUrl useSeoMeta({ title: `${postData.title} | ${t('blog.title')}`, @@ -64,7 +66,7 @@ if (post.value) { ogDescription: postData.description, ogImage: postData.image || '/img/blog/default-cover.jpg', ogType: 'article', - ogUrl: `${siteUrl}${postData.path}`, + ogUrl: canonicalUrl, twitterCard: 'summary_large_image', twitterTitle: postData.title, twitterDescription: postData.description, @@ -77,6 +79,14 @@ if (post.value) { // JSON-LD structured data useHead({ + link: canonicalPath + ? [ + { + rel: 'canonical', + href: canonicalUrl + } + ] + : [], script: [ { type: 'application/ld+json', @@ -140,7 +150,7 @@ if (post.value) { - + diff --git a/nuxt.config.ts b/nuxt.config.ts index 6249169..950bea7 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -175,9 +175,10 @@ export default defineNuxtConfig({ nitro: { prerender: { crawlLinks: true, - routes: ['/', '/blog', '/fa/blog'], + routes: ['/', '/blog', '/fa/blog', '/blog/rss.xml', '/fa/blog/rss.xml'], failOnError: false, - ignore: ['/_vercel/image'] + // Avoid crawling and prerendering internal/asset endpoints (speeds up builds significantly) + ignore: ['/_vercel/image', '/_ipx', '/_nuxt', '/_i18n', '/__nuxt_content'] }, devProxy: { host: '0.0.0.0' diff --git a/server/routes/blog/rss.xml.ts b/server/routes/blog/rss.xml.ts index 1039275..c2e42ea 100644 --- a/server/routes/blog/rss.xml.ts +++ b/server/routes/blog/rss.xml.ts @@ -2,14 +2,14 @@ export default defineEventHandler(async (event) => { const config = useRuntimeConfig() const siteUrl = config.public.siteUrl || 'https://example.com' - // Detect locale from path const locale = 'en' - // Fetch published blog posts - const posts = await serverQueryContent(event, `${locale}/blog`) - .where({ draft: { $ne: true } }) - .sort({ date: -1 }) - .find() + // In Nitro server routes, `queryCollection` expects the H3 event as the first argument. + const allPosts = await queryCollection(event, 'blog').all() + + const posts = allPosts + .filter((post: any) => post.path?.startsWith('/en/blog/') && post.draft !== true) + .sort((a: any, b: any) => new Date(b.date).getTime() - new Date(a.date).getTime()) const escapeXml = (str: string) => { return str @@ -22,7 +22,8 @@ export default defineEventHandler(async (event) => { const rssItems = posts .map((post) => { - const link = `${siteUrl}${post._path}` + const routePath = post.path?.replace(/^\/en/, '') || '' + const link = `${siteUrl}${routePath}` const pubDate = new Date(post.date).toUTCString() return ` diff --git a/server/routes/fa/blog/rss.xml.ts b/server/routes/fa/blog/rss.xml.ts index 174d0dd..1c7677d 100644 --- a/server/routes/fa/blog/rss.xml.ts +++ b/server/routes/fa/blog/rss.xml.ts @@ -2,14 +2,14 @@ export default defineEventHandler(async (event) => { const config = useRuntimeConfig() const siteUrl = config.public.siteUrl || 'https://example.com' - // Persian locale const locale = 'fa' - // Fetch published blog posts - const posts = await serverQueryContent(event, `${locale}/blog`) - .where({ draft: { $ne: true } }) - .sort({ date: -1 }) - .find() + // In Nitro server routes, `queryCollection` expects the H3 event as the first argument. + const allPosts = await queryCollection(event, 'blog').all() + + const posts = allPosts + .filter((post: any) => post.path?.startsWith('/fa/blog/') && post.draft !== true) + .sort((a: any, b: any) => new Date(b.date).getTime() - new Date(a.date).getTime()) const escapeXml = (str: string) => { return str @@ -22,7 +22,7 @@ export default defineEventHandler(async (event) => { const rssItems = posts .map((post) => { - const link = `${siteUrl}${post._path}` + const link = `${siteUrl}${post.path}` const pubDate = new Date(post.date).toUTCString() return `