Merge branch 'main' into chore/lint-formatter-setup

This commit is contained in:
Dominik K. 2025-07-24 14:12:16 +02:00 committed by GitHub
commit 7dace46f26
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 187 additions and 23 deletions

View File

@ -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",

View File

@ -1,37 +1,32 @@
import type { 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";
import { SITE_INFO, SITE_URL } from "@/constants/site";
export const baseMetaData: Metadata = {
metadataBase: new URL("https://opencut.app"),
title,
description,
metadataBase: new URL(SITE_URL),
title: SITE_INFO.title,
description: SITE_INFO.description,
openGraph: {
title,
description,
url: "https://opencut.app",
siteName: "OpenCut",
title: SITE_INFO.title,
description: SITE_INFO.description,
url: SITE_URL,
siteName: SITE_INFO.title,
locale: "en_US",
type: "website",
images: [
{
url: openGraphImageUrl,
url: SITE_INFO.openGraphImage,
width: 1200,
height: 630,
alt: "OpenCut",
alt: "OpenCut Wordmark",
},
],
},
twitter: {
card: "summary_large_image",
title,
description,
title: SITE_INFO.title,
description: SITE_INFO.description,
creator: "@opencutapp",
images: [twitterImageUrl],
images: [SITE_INFO.twitterImage],
},
pinterest: {
richPin: false,
@ -82,7 +77,7 @@ export const baseMetaData: Metadata = {
},
appleWebApp: {
capable: true,
title,
title: SITE_INFO.title,
},
manifest: "/manifest.json",
other: {

View File

@ -1,8 +1,16 @@
import { Footer } from "@/components/footer";
import type { Metadata } from "next";
import { SITE_URL } from "@/constants/site";
import { Header } from "@/components/header";
import { Hero } from "@/components/landing/hero";
export default async function Home() {
export const metadata: Metadata = {
alternates: {
canonical: SITE_URL,
},
};
export default function Home() {
return (
<div>
<Header />

View File

@ -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`,
};
}

View File

@ -0,0 +1,46 @@
import { Feed } from 'feed';
import { getPosts } from '@/lib/blog-query';
import { SITE_INFO, SITE_URL } from '@/constants/site';
export async function GET() {
try {
const { posts } = await getPosts();
const feed = new Feed({
title: `${SITE_INFO.title} Blog`,
description: SITE_INFO.description,
id: `${SITE_URL}`,
link: `${SITE_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_URL}/blog/${post.slug}`,
link: `${SITE_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 });
}
}

View File

@ -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,
];
}

View File

@ -0,0 +1,11 @@
export const SITE_URL = "https://opencut.app";
export const SITE_INFO = {
title: "OpenCut",
description:
"A simple but powerful video editor that gets the job done. In your browser.",
url: SITE_URL,
openGraphImage: "/open-graph/default.jpg",
twitterImage: "/open-graph/default.jpg",
favicon: "/favicon.ico",
};

View File

@ -44,11 +44,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",
@ -851,6 +852,7 @@
"fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
"fdir": ["fdir@6.4.6", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w=="],
"feed": ["feed@5.1.0", "", { "dependencies": { "xml-js": "^1.6.11" } }, "sha512-qGNhgYygnefSkAHHrNHqC7p3R8J0/xQDS/cYUud8er/qD9EFGWyCdUDfULHTJQN1d3H3WprzVwMc9MfB4J50Wg=="],
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
@ -1292,6 +1294,8 @@
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
"sax": ["sax@1.4.1", "", {}, "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="],
"scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="],
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
@ -1466,6 +1470,8 @@
"wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
"xml-js": ["xml-js@1.6.11", "", { "dependencies": { "sax": "^1.2.4" }, "bin": { "xml-js": "./bin/cli.js" } }, "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g=="],
"xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
@ -1491,7 +1497,6 @@
"@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
"@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
"better-auth/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
"chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
@ -1518,6 +1523,8 @@
"next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
"opencut/next": ["next@15.4.3", "", { "dependencies": { "@next/env": "15.4.3", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.4.3", "@next/swc-darwin-x64": "15.4.3", "@next/swc-linux-arm64-gnu": "15.4.3", "@next/swc-linux-arm64-musl": "15.4.3", "@next/swc-linux-x64-gnu": "15.4.3", "@next/swc-linux-x64-musl": "15.4.3", "@next/swc-win32-arm64-msvc": "15.4.3", "@next/swc-win32-x64-msvc": "15.4.3", "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-uW7Qe6poVasNIE1X382nI29oxSdFJzjQzTgJFLD43MxyPfGKKxCMySllhBpvqr48f58Om+tLMivzRwBpXEytvA=="],
"opencut/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
"parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
@ -1613,6 +1620,28 @@
"motion/framer-motion/motion-utils": ["motion-utils@12.23.6", "", {}, "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ=="],
"wrap-ansi/string-width/emoji-regex": ["emoji-regex@10.4.0", "", {}, "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="],
"opencut/next/@next/env": ["@next/env@15.4.3", "", {}, "sha512-lKJ9KJAvaWzqurIsz6NWdQOLj96mdhuDMusLSYHw9HBe2On7BjUwU1WeRvq19x7NrEK3iOgMeSBV5qEhVH1cMw=="],
"opencut/next/@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.4.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-YAhZWKeEYY7LHQJiQ8fe3Y6ymfcDcTn7rDC8PDu/pdeIl1Z2LHD4uyPNuQUGCEQT//MSNv6oZCeQzZfTCKZv+A=="],
"opencut/next/@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.4.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZPHRdd51xaxCMpT4viQ6h8TgYM1zPW1JIeksPY9wKlyvBVUQqrWqw8kEh1sa7/x0Ied+U7pYHkAkutrUwxbMcg=="],
"opencut/next/@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.4.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-QUdqftCXC5vw5cowucqi9FeOPQ0vdMxoOHLY0J5jPdercwSJFjdi9CkEO4Xkq1eG4t1TB/BG81n6rmTsWoILnw=="],
"opencut/next/@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.4.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-HTL31NsmoafX+r5g91Yj3+q34nrn1xKmCWVuNA+fUWO4X0pr+n83uGzLyEOn0kUqbMZ40KmWx+4wsbMoUChkiQ=="],
"opencut/next/@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.4.3", "", { "os": "linux", "cpu": "x64" }, "sha512-HRQLWoeFkKXd2YCEEy9GhfwOijRm37x4w5r0MMVHxBKSA6ms3JoPUXvGhfHT6srnGRcEUWNrQ2vzkHir5ZWTSw=="],
"opencut/next/@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.4.3", "", { "os": "linux", "cpu": "x64" }, "sha512-NyXUx6G7AayaRGUsVPenuwhyAoyxjQuQPaK50AXoaAHPwRuif4WmSrXUs8/Y0HJIZh8E/YXRm9H7uuGfiacpuQ=="],
"opencut/next/@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.4.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-2CUTmpzN/7cL1a7GjdLkDFlfH3nwMwW8a6JiaAUsL9MtKmNNO3fnXqnY0Zk30fii3hVEl4dr7ztrpYt0t2CcGQ=="],
"opencut/next/@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.4.3", "", { "os": "win32", "cpu": "x64" }, "sha512-i54YgUhvrUQxQD84SjAbkfWhYkOdm/DNRAVekCHLWxVg3aUbyC6NFQn9TwgCkX5QAS2pXCJo3kFboSFvrsd7dA=="],
"opencut/next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
"string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],