= ({ title, desc }) => {
+ return (
+
+
+
+ {title}
+
+
+ {desc}
+
+
+
+ );
+};
+
+export async function getHtml(parsedReq: ParsedRequest) {
+ const { title, desc } = parsedReq;
+ const { renderToString } = await import('react-dom/server');
+
+ const result = renderToString();
+
+ return result;
+}
diff --git a/src/app/api/og-image/lib/types.ts b/src/app/api/og-image/lib/types.ts
new file mode 100644
index 0000000..3d61829
--- /dev/null
+++ b/src/app/api/og-image/lib/types.ts
@@ -0,0 +1,4 @@
+export interface ParsedRequest {
+ title?: string;
+ desc?: string;
+}
diff --git a/src/app/api/og-image/route.ts b/src/app/api/og-image/route.ts
new file mode 100644
index 0000000..8d81020
--- /dev/null
+++ b/src/app/api/og-image/route.ts
@@ -0,0 +1,33 @@
+import { getHtml } from './lib/template';
+import { getScreenshot } from './lib/render';
+import { NextRequest } from 'next/server';
+
+export async function GET(request: NextRequest) {
+ try {
+ const params = Object.fromEntries(request.nextUrl.searchParams);
+ const html = await getHtml(params);
+ const file = await getScreenshot(html);
+
+ return new Response(file, {
+ status: 200,
+ statusText: 'OK',
+ headers: {
+ // 'Access-Control-Allow-Origin': '*',
+ // 'Access-Control-Allow-Methods': 'GET',
+ 'Content-Type': `image/png`,
+ 'Cache-Control': `public, immutable, no-transform, s-maxage=31536000, max-age=31536000`,
+ },
+ });
+ } catch (e) {
+ console.error(e);
+ return new Response(
+ 'Internal Error
Sorry, there was a problem
',
+ {
+ status: 500,
+ headers: {
+ 'Content-Type': 'text/html',
+ },
+ },
+ );
+ }
+}
diff --git a/src/app/api/og/route.ts b/src/app/api/og/route.ts
new file mode 100644
index 0000000..f981df6
--- /dev/null
+++ b/src/app/api/og/route.ts
@@ -0,0 +1,53 @@
+import { NextRequest, NextResponse } from 'next/server';
+import puppeteer from 'puppeteer';
+
+export const dynamic = 'force-dynamic';
+
+export async function GET(req: NextRequest) {
+ const title = req.nextUrl.searchParams.get('title') ?? 'Default title';
+ const desc = req.nextUrl.searchParams.get('desc') ?? 'Default description';
+
+ const imageUrl = `${req.nextUrl.origin}/images/ogBg.png`;
+ const logoUrl = `${req.nextUrl.origin}/images/logo-dtr-white.png`;
+
+ const html = `
+
+
+
+
+
+
+
+ `;
+
+ // Запуск браузера
+ const browser = await puppeteer.launch({
+ args: ['--no-sandbox', '--disable-setuid-sandbox'],
+ });
+
+ const page = await browser.newPage();
+ await page.setContent(html, { waitUntil: 'networkidle0' });
+ await page.setViewport({ width: 600, height: 315 });
+ const screenshot = await page.screenshot({ type: 'png' });
+ await browser.close();
+
+ return new NextResponse(screenshot, {
+ headers: {
+ 'Content-Type': 'image/png',
+ 'Cache-Control': 'max-age=60',
+ },
+ });
+}