diff options
Diffstat (limited to 'apps')
| -rw-r--r-- | apps/web/package.json | 3 | ||||
| -rw-r--r-- | apps/web/src/app/metadata.ts | 32 | ||||
| -rw-r--r-- | apps/web/src/app/robots.ts | 13 | ||||
| -rw-r--r-- | apps/web/src/app/rss.xml/route.ts | 46 | ||||
| -rw-r--r-- | apps/web/src/app/sitemap.ts | 61 | ||||
| -rw-r--r-- | apps/web/src/constants/site.ts | 1 |
6 files changed, 141 insertions, 15 deletions
diff --git a/apps/web/package.json b/apps/web/package.json index c409136c..f5cd7da4 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -38,11 +38,12 @@ "dotenv": "^16.5.0", "drizzle-orm": "^0.44.2", "embla-carousel-react": "^8.5.1", + "feed": "^5.1.0", "framer-motion": "^11.13.1", "input-otp": "^1.4.1", "lucide-react": "^0.468.0", "motion": "^12.18.1", - "next": "^15.4.1", + "next": "^15.4.3", "next-themes": "^0.4.4", "pg": "^8.16.2", "radix-ui": "^1.4.2", diff --git a/apps/web/src/app/metadata.ts b/apps/web/src/app/metadata.ts index 6f9e6023..de8cf6f0 100644 --- a/apps/web/src/app/metadata.ts +++ b/apps/web/src/app/metadata.ts @@ -1,25 +1,29 @@ import { Metadata } from "next"; -const title = "OpenCut"; -const description = - "A simple but powerful video editor that gets the job done. In your browser."; -const openGraphImageUrl = "https://opencut.app/open-graph/default.jpg"; -const twitterImageUrl = "/open-graph/default.jpg"; +export const SITE_INFO = { + title: "OpenCut", + description: + "A simple but powerful video editor that gets the job done. In your browser.", + url: "https://opencut.app", + openGraphImage: "https://opencut.app/open-graph/default.jpg", + twitterImage: "/open-graph/default.jpg", + favicon: "/favicon.ico", +}; export const baseMetaData: Metadata = { metadataBase: new URL("https://opencut.app"), - title: title, - description: description, + title: SITE_INFO.title, + description: SITE_INFO.description, openGraph: { - title: title, - description: description, + title: SITE_INFO.title, + description: SITE_INFO.description, url: "https://opencut.app", siteName: "OpenCut", locale: "en_US", type: "website", images: [ { - url: openGraphImageUrl, + url: SITE_INFO.openGraphImage, width: 1200, height: 630, alt: "OpenCut", @@ -28,10 +32,10 @@ export const baseMetaData: Metadata = { }, twitter: { card: "summary_large_image", - title: title, - description: description, + title: SITE_INFO.title, + description: SITE_INFO.description, creator: "@opencutapp", - images: [twitterImageUrl], + images: [SITE_INFO.twitterImage], }, pinterest: { richPin: false, @@ -82,7 +86,7 @@ export const baseMetaData: Metadata = { }, appleWebApp: { capable: true, - title: title, + title: SITE_INFO.title, }, manifest: "/manifest.json", other: { diff --git a/apps/web/src/app/robots.ts b/apps/web/src/app/robots.ts new file mode 100644 index 00000000..ad6c31c8 --- /dev/null +++ b/apps/web/src/app/robots.ts @@ -0,0 +1,13 @@ +import type { MetadataRoute } from "next"; +import { SITE_URL } from "@/constants/site"; + +export default function robots(): MetadataRoute.Robots { + return { + rules: { + userAgent: "*", + allow: "/", + disallow: ["/_next/", "/projects/", "/editor/"], + }, + sitemap: `${SITE_URL}/sitemap.xml`, + }; +} diff --git a/apps/web/src/app/rss.xml/route.ts b/apps/web/src/app/rss.xml/route.ts new file mode 100644 index 00000000..b16bd856 --- /dev/null +++ b/apps/web/src/app/rss.xml/route.ts @@ -0,0 +1,46 @@ +import { Feed } from 'feed'; +import { getPosts } from '@/lib/blog-query'; +import { SITE_INFO } from '../metadata'; + +export async function GET() { + try { + const { posts } = await getPosts(); + + const feed = new Feed({ + title: 'OpenCut Blog', + description: SITE_INFO.description, + id: `${SITE_INFO.url}`, + link: `${SITE_INFO.url}/blog/`, + language: 'en', + image: `${SITE_INFO.openGraphImage}`, + favicon: `${SITE_INFO.favicon}`, + copyright: `All rights reserved ${new Date().getFullYear()}, ${ + SITE_INFO.title + }`, + }); + + for (const post of posts) { + feed.addItem({ + title: post.title, + id: `${SITE_INFO.url}/blog/${post.slug}`, + link: `${SITE_INFO.url}/blog/${post.slug}`, + description: post.description, + author: post.authors.map((author) => ({ + name: author.name, + })), + date: new Date(post.publishedAt), + image: post.coverImage || SITE_INFO.openGraphImage, + }); + } + + return new Response(feed.rss2(), { + headers: { + 'Content-Type': 'text/xml', + 'Cache-Control': 'public, max-age=86400, stale-while-revalidate', + }, + }); + } catch (error) { + console.error('Error generating RSS feed', error); + return new Response('Internal Server Error', { status: 500 }); + } +}
\ No newline at end of file diff --git a/apps/web/src/app/sitemap.ts b/apps/web/src/app/sitemap.ts new file mode 100644 index 00000000..81a5ebf4 --- /dev/null +++ b/apps/web/src/app/sitemap.ts @@ -0,0 +1,61 @@ +import { SITE_URL } from "@/constants/site"; +import { getPosts } from "@/lib/blog-query"; +import type { MetadataRoute } from "next"; + +export default async function sitemap(): Promise<MetadataRoute.Sitemap> { + const data = await getPosts(); + + const postPages: MetadataRoute.Sitemap = + data?.posts?.map((post) => ({ + url: `${SITE_URL}/blog/${post.slug}`, + lastModified: new Date(post.publishedAt), + changeFrequency: "weekly", + priority: 0.8, + })) ?? []; + + return [ + { + url: SITE_URL, + lastModified: new Date(), + changeFrequency: "weekly", + priority: 1, + }, + { + url: `${SITE_URL}/contributors`, + lastModified: new Date(), + changeFrequency: "daily", + priority: 0.5, + }, + { + url: `${SITE_URL}/roadmap`, + lastModified: new Date(), + changeFrequency: "weekly", + priority: 1, + }, + { + url: `${SITE_URL}/privacy`, + lastModified: new Date(), + changeFrequency: "monthly", + priority: 0.5, + }, + { + url: `${SITE_URL}/terms`, + lastModified: new Date(), + changeFrequency: "monthly", + priority: 0.5, + }, + { + url: `${SITE_URL}/why-not-capcut`, + lastModified: new Date(), + changeFrequency: "yearly", + priority: 1, + }, + { + url: `${SITE_URL}/blog`, + lastModified: new Date(), + changeFrequency: "weekly", + priority: 1, + }, + ...postPages, + ]; +} diff --git a/apps/web/src/constants/site.ts b/apps/web/src/constants/site.ts new file mode 100644 index 00000000..61ec29c1 --- /dev/null +++ b/apps/web/src/constants/site.ts @@ -0,0 +1 @@ +export const SITE_URL = "https://opencut.app";
\ No newline at end of file |
