+ {/* Horizontal lines */}
+
+
+
+ {/* Vertical lines */}
+
+
+
+
+
+ {title}
+
+ {description && (
+
+ {description}
+
+ )}
+
+
+
,
+ {
+ width: 1920,
+ height: 1080,
+ fonts: [
+ {
+ name: "Inter",
+ data: fontData,
+ style: "normal",
+ },
+ ],
+ },
+ );
+}
diff --git a/apps/docs/src/app/api/og/proxy/route.ts b/apps/docs/src/app/api/og/proxy/route.ts
new file mode 100644
index 0000000..738b767
--- /dev/null
+++ b/apps/docs/src/app/api/og/proxy/route.ts
@@ -0,0 +1,45 @@
+import { NextRequest, NextResponse } from 'next/server';
+
+export async function GET(request: NextRequest) {
+ try {
+ // Get the URL parameter
+ const url = new URL(request.url);
+ const imageUrl = url.searchParams.get('url');
+
+ if (!imageUrl) {
+ return NextResponse.json({ error: 'Missing URL parameter' }, { status: 400 });
+ }
+
+ // Fetch the image
+ const response = await fetch(imageUrl, {
+ headers: {
+ 'User-Agent': 'Mozilla/5.0 (compatible; ImageProxy/1.0)',
+ },
+ });
+
+ if (!response.ok) {
+ return NextResponse.json(
+ { error: `Failed to fetch image: ${response.status}` },
+ { status: response.status }
+ );
+ }
+
+ // Get the image data
+ const contentType = response.headers.get('content-type') || 'image/jpeg';
+ const imageData = await response.arrayBuffer();
+
+ // Return the image with appropriate headers
+ return new NextResponse(imageData, {
+ headers: {
+ 'Content-Type': contentType,
+ 'Cache-Control': 'public, max-age=86400',
+ },
+ });
+ } catch (error) {
+ console.error('Error proxying image:', error);
+ return NextResponse.json(
+ { error: 'Failed to proxy image' },
+ { status: 500 }
+ );
+ }
+}
diff --git a/apps/docs/src/app/changelog/layout.tsx b/apps/docs/src/app/changelog/layout.tsx
new file mode 100644
index 0000000..9e90788
--- /dev/null
+++ b/apps/docs/src/app/changelog/layout.tsx
@@ -0,0 +1,20 @@
+import { Row } from "@once-ui-system/core";
+import { Sidebar } from "@/product";
+import React, { memo } from "react";
+
+const DocsLayout = memo(({
+ children,
+}: {
+ children: React.ReactNode;
+}) => {
+ return (
+