diff --git a/DESIGN.md b/DESIGN.md index ba411dd..b3ce82c 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -552,5 +552,6 @@ const martian = Martian_Mono({ subsets: ['cyrillic', 'latin'], variable: '--font │ kvarta.unuchak.com +375 29 000-00-00 │ Martian 20px muted └────────────────────────────────────────────────────────────┘ ``` +- Тексты из site.ts: заголовок — `site.hero.title`, штамп — `site.hero.stamp`, подписи ленты — `site.freshness.days`, `alt` — `site.meta.ogTitle` (скетч выше — композиция, не текст). - Поля 64px. Без фото и без дат (картинка кешируется), только дни недели. - Satori не поддерживает SVG-фильтры и variable-шрифты: штамп — двойная рамка без «краски», шрифты — статичные TTF (Golos Text 900 и 500, Martian Mono 700), загружаются `fetch` из файлов в `src/app/og-fonts/` (подмножество кириллица+латиница). `alt`: «Кварта — свежая обжарка в Минске, обжарка по четвергам». diff --git a/apps/landing/src/app/icon.svg b/apps/landing/src/app/icon.svg new file mode 100644 index 0000000..9637f86 --- /dev/null +++ b/apps/landing/src/app/icon.svg @@ -0,0 +1 @@ + diff --git a/apps/landing/src/app/layout.tsx b/apps/landing/src/app/layout.tsx index 368dd5e..ed0e572 100644 --- a/apps/landing/src/app/layout.tsx +++ b/apps/landing/src/app/layout.tsx @@ -11,8 +11,23 @@ const golos = Golos_Text({ subsets: ['cyrillic', 'latin'], variable: '--font-gol const martian = Martian_Mono({ subsets: ['cyrillic', 'latin'], variable: '--font-martian', axes: ['wdth'], display: 'swap' }); export const metadata: Metadata = { + metadataBase: new URL('https://kvarta.unuchak.com'), title: site.meta.title, description: site.meta.description, + alternates: { canonical: '/' }, + openGraph: { + type: 'website', + locale: 'ru_RU', + url: '/', + siteName: site.footer.name, + title: site.meta.ogTitle, + description: site.meta.ogDescription, + }, + twitter: { + card: 'summary_large_image', + title: site.meta.ogTitle, + description: site.meta.ogDescription, + }, }; export const viewport: Viewport = { diff --git a/apps/landing/src/app/og-fonts/golos-500.ttf b/apps/landing/src/app/og-fonts/golos-500.ttf new file mode 100644 index 0000000..02c1aa4 Binary files /dev/null and b/apps/landing/src/app/og-fonts/golos-500.ttf differ diff --git a/apps/landing/src/app/og-fonts/golos-900.ttf b/apps/landing/src/app/og-fonts/golos-900.ttf new file mode 100644 index 0000000..bbfc881 Binary files /dev/null and b/apps/landing/src/app/og-fonts/golos-900.ttf differ diff --git a/apps/landing/src/app/og-fonts/martian-700.ttf b/apps/landing/src/app/og-fonts/martian-700.ttf new file mode 100644 index 0000000..c05007f Binary files /dev/null and b/apps/landing/src/app/og-fonts/martian-700.ttf differ diff --git a/apps/landing/src/app/opengraph-image.tsx b/apps/landing/src/app/opengraph-image.tsx new file mode 100644 index 0000000..7e752f5 --- /dev/null +++ b/apps/landing/src/app/opengraph-image.tsx @@ -0,0 +1,101 @@ +// OG 1200×630 по DESIGN.md: знак и слово, заголовок, штамп, лента недели ПН–ВС с ЧТ/ПТ красным. +// Без фото и без дат: картинка кешируется. Satori не умеет SVG-фильтры и variable-шрифты — +// штамп без «краски», шрифты — статичные TTF из ./og-fonts. +import { readFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import { ImageResponse } from 'next/og'; +import { CONTACT_PHONE } from '@/content/form'; +import { site } from '@/content/site'; + +export const alt = site.meta.ogTitle; +export const size = { width: 1200, height: 630 }; +export const contentType = 'image/png'; + +const C = { + cream: '#f3ebdd', + ink: '#2a1810', + muted: '#5e4636', + rule: '#c9b595', + cherry: '#b3221b', +}; + +const DAYS = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС']; + +export default async function OpengraphImage() { + const dir = join(process.cwd(), 'src/app/og-fonts'); + const font = (file: string) => readFile(join(dir, file)); + const [golos900, golos500, martian700] = await Promise.all([font('golos-900.ttf'), font('golos-500.ttf'), font('martian-700.ttf')]); + const [roast, delivery, cup] = site.freshness.days; + + return new ImageResponse( + ( +
+
+
+
+
+ {DAYS.map((d, i) => ( +
+ ))} +
+
{site.footer.name}
+
+
+ {site.hero.title} +
+
+
+
+
{site.hero.stamp.toUpperCase()}
+
+
+
+ +
+
+ {DAYS.map((d, i) => { + const hot = i === 3 || i === 4; + return ( +
+
{d}
+
+ ); + })} +
+
+
+
{roast?.label.toUpperCase()}
+
+
{delivery?.label.toUpperCase()}
+
+
+ {cup ? `${cup.day} · ${cup.label}`.toUpperCase() : ''} +
+
+
+
+
kvarta.unuchak.com
+
{CONTACT_PHONE.display}
+
+
+
+ ), + { + ...size, + fonts: [ + { name: 'Golos Text', data: golos900, weight: 900, style: 'normal' }, + { name: 'Golos Text', data: golos500, weight: 500, style: 'normal' }, + { name: 'Martian Mono', data: martian700, weight: 700, style: 'normal' }, + ], + }, + ); +} diff --git a/apps/landing/src/app/twitter-image.tsx b/apps/landing/src/app/twitter-image.tsx new file mode 100644 index 0000000..a320535 --- /dev/null +++ b/apps/landing/src/app/twitter-image.tsx @@ -0,0 +1 @@ +export { default, alt, size, contentType } from './opengraph-image';