diff --git a/PRODUCT.md b/PRODUCT.md new file mode 100644 index 0000000..694ccb5 --- /dev/null +++ b/PRODUCT.md @@ -0,0 +1,57 @@ +# Product + + + +> Записано по брифу автора и `docs/plan.md` без интервью: все решения приняты автором заранее. Источник фактов — `docs/plan.md`, раздел «Факты из ТЗ». + +## Platform + +web + +## Users + +Жители Минска 25–45 лет, приходят с телефона из Instagram и Яндекса. Задача: понять, чем эта обжарка лучше пачки из магазина, выбрать сорт или подписку и оставить заявку. Менеджер перезванивает. + +## Product Purpose + +Одностраничный лендинг обжарки «Кварта». Успех — отправленная **заявка** (имя, телефон, интерес, комментарий), которая доходит до менеджера в Telegram с источником визита. + +## Positioning + +Свежесть по расписанию: обжарка по четвергам партиями по 5 кг, развоз по Минску в пятницу, зерно у клиента на 1–3 день после обжарки. «Кварта» — «четвёртая», четверг — четвёртый день недели. У соседей по рынку такого расписания нет. + +## Operating Context + +- Обжарка с 2019 года, основатели Аня и Дмитрий, бывшие бариста. +- Ассортимент: Эфиопия Иргачеффе (цветочный, бергамот, светлая обжарка) 250 г — 32 BYN; Колумбия Уила (карамель, красное яблоко) 250 г — 29 BYN; Бразилия Серрадо (орех, шоколад, под эспрессо) 250 г — 26 BYN; дрип-пакеты ассорти, 10 шт — 18 BYN. +- Подписка: 2 пачки по 250 г раз в месяц, доставка бесплатно — 54 BYN/мес. +- Самовывоз: Минск, ул. Короля, 9. Пн–пт 8:00–20:00, сб–вс 10:00–18:00. +- Доставка по Минску в пятницу, от 50 BYN бесплатно; дешевле — «стоимость уточнит менеджер». +- Телефон вымышленный: +375 29 000-00-00. + +## Capabilities and Constraints + +- Next.js 16 App Router, Tailwind 4 (CSS-first `@theme`), next/font, next/og. Без UI-китов. +- Форма и логика уже есть (`apps/landing/src/components/LeadForm.tsx`, `CtaButton.tsx`, `lib/leadPrefill.ts`); вёрстка ложится на них, логика не меняется. +- Все тексты — в `apps/landing/src/content/site.ts` и `content/form.ts`. +- Термины — `GLOSSARY.md`: заявка, уточнение, интерес, посетитель, менеджер. + +## Brand Commitments + +Тон тёплый, простой, без пафоса. Название «Кварта» = «четвёртая», обжарка по четвергам. + +## Evidence on Hand + +- Фото (Unsplash License, без людей): зерно крупным планом — Mona Jain; открытый мешок с зерном на тёмном — Tina Guina; охладитель ростера — Scott Soltys-Curry. Это не фото самой «Кварты», подписи не должны выдавать их за её цех. +- Отзывов, клиентов, наград, цифр продаж, соцсетей, логотипа нет. Не выдумывать. + +## Product Principles + +1. Свежесть показываем датой, а не прилагательным. +2. Каждая цена и условие из ТЗ видны без клика. +3. От любой CTA до отправленной заявки — один экран формы, без лишних шагов. +4. Ничего сверх фактов ТЗ. + +## Accessibility & Inclusion + +WCAG 2.2 AA: контраст, видимый фокус, тач-цели ≥ 44px, `prefers-reduced-motion`. Мобильный трафик: проверка на 390 и 1440. diff --git a/apps/landing/src/components/LeadForm.tsx b/apps/landing/src/components/LeadForm.tsx index 2ea6583..fe5a436 100644 --- a/apps/landing/src/components/LeadForm.tsx +++ b/apps/landing/src/components/LeadForm.tsx @@ -44,12 +44,9 @@ function Notice({ notice }: { notice: SubmitNotice | null }) { return

{FORM_TEXT.clarified}

; case 'rate_limited': return ( -
-

{FORM_TEXT.rateLimited}

-

- {FORM_TEXT.callUs} -

-
+

+ {FORM_TEXT.rateLimited} +

); case 'failed': return ( diff --git a/apps/landing/src/content/form.ts b/apps/landing/src/content/form.ts index e17f890..d62ec01 100644 --- a/apps/landing/src/content/form.ts +++ b/apps/landing/src/content/form.ts @@ -12,16 +12,15 @@ export const FORM_TEXT = { name: { label: 'Имя', placeholder: 'Как к вам обращаться' }, phone: { label: 'Телефон', placeholder: '+375 29 123-45-67' }, interest: { legend: 'Что вас интересует' }, - comment: { label: 'Комментарий', placeholder: 'Сорт, помол, удобное время звонка — по желанию' }, + comment: { label: 'Комментарий', placeholder: 'Сорт, количество, удобное время звонка — по желанию' }, honeypot: { label: 'Компания (не заполняйте)' }, submit: 'Отправить', submitting: 'Отправляем…', - success: 'Спасибо! Перезвоним в рабочее время', - clarified: 'Дописали к вашей заявке', + success: 'Спасибо, заявка у нас. Перезвоним в рабочее время.', + clarified: 'Дописали это к вашей прошлой заявке.', sendAnother: 'Отправить ещё одну', - rateLimited: 'Слишком много попыток. Подождите немного', + rateLimited: 'Слишком много попыток. Попробуйте через 10 минут или позвоните:', failed: 'Не получилось отправить. Попробуйте ещё раз или позвоните:', - callUs: 'Позвоните нам:', } as const; export type CtaPreset = { label: string; interest: Interest; comment?: string }; diff --git a/apps/landing/src/content/site.ts b/apps/landing/src/content/site.ts new file mode 100644 index 0000000..f489f58 --- /dev/null +++ b/apps/landing/src/content/site.ts @@ -0,0 +1,158 @@ +// Все тексты и факты лендинга по блокам — для вычитки. Факты только из «Фактов из ТЗ» (docs/plan.md). +// Тексты формы — в ./form.ts. +import type { Interest } from '@kvarta/shared/lead'; +import { CONTACT_PHONE } from './form'; + +type Cta = { label: string; interest: Interest; comment?: string }; + +export const site = { + meta: { + title: 'Кварта: кофе свежей обжарки с доставкой по Минску', + description: + 'Обжариваем кофе по четвергам, в пятницу привозим по Минску. Эфиопия, Колумбия, Бразилия, дрип-пакеты и подписка на 2 пачки в месяц.', + ogTitle: 'Кварта. Кофе, обжаренный в четверг', + ogDescription: 'Обжарка по четвергам, доставка по Минску в пятницу.', + }, + + hero: { + stamp: 'ЧТ · обжарка', + eyebrow: 'Обжарка кофе в Минске', + title: 'Кофе, обжаренный в четверг', + subtitle: + 'В пятницу привозим по Минску, и пачка попадает к вам на 1–3 день после обжарки.', + ctaPrimary: { label: 'Оформить подписку', interest: 'subscription' } satisfies Cta, + ctaSecondary: { label: 'Заказать пачку', interest: 'one_time' } satisfies Cta, + }, + + freshness: { + title: 'Как устроена наша неделя', + days: [ + { day: 'ЧТ', label: 'Обжарка', caption: 'Обжариваем зерно партиями по 5 кг.' }, + { day: 'ПТ', label: 'Доставка', caption: 'Развозим заказы по Минску.' }, + { day: '1–3 день', label: 'В чашке', caption: 'Открываете пачку и варите кофе.' }, + ], + why: 'Кофе вкуснее, пока обжарка свежая.', + }, + + catalog: { + title: 'Что обжариваем', + subtitle: 'Три сорта в пачках по 250 г и дрип-пакеты.', + items: [ + { + id: 'ethiopia', + name: 'Эфиопия Иргачеффе', + notes: ['цветочный', 'бергамот'], + roast: 'светлая обжарка', + brew: null, + size: '250 г', + price: 32, + priceDisplay: '32 BYN', + cta: { label: 'Заказать', interest: 'one_time', comment: 'Эфиопия Иргачеффе, 250 г' } satisfies Cta, + }, + { + id: 'colombia', + name: 'Колумбия Уила', + notes: ['карамель', 'красное яблоко'], + roast: null, + brew: null, + size: '250 г', + price: 29, + priceDisplay: '29 BYN', + cta: { label: 'Заказать', interest: 'one_time', comment: 'Колумбия Уила, 250 г' } satisfies Cta, + }, + { + id: 'brazil', + name: 'Бразилия Серрадо', + notes: ['орех', 'шоколад'], + roast: null, + brew: 'под эспрессо', + size: '250 г', + price: 26, + priceDisplay: '26 BYN', + cta: { label: 'Заказать', interest: 'one_time', comment: 'Бразилия Серрадо, 250 г' } satisfies Cta, + }, + { + id: 'drip', + name: 'Дрип-пакеты ассорти', + notes: [], + roast: null, + brew: 'заваривается прямо в чашке', + size: '10 шт', + price: 18, + priceDisplay: '18 BYN', + cta: { label: 'Заказать', interest: 'one_time', comment: 'Дрип-пакеты ассорти, 10 шт' } satisfies Cta, + }, + ], + }, + + subscription: { + title: 'Две пачки каждый месяц', + text: 'Раз в месяц привозим две пачки по 250 г. Доставка бесплатно.', + price: 54, + priceDisplay: '54 BYN в месяц', + note: 'Подробности менеджер расскажет по телефону.', + cta: { label: 'Оформить подписку', interest: 'subscription', comment: 'Подписка: 2 пачки в месяц' } satisfies Cta, + }, + + about: { + title: 'Кто обжаривает', + text: [ + 'Нас зовут Аня и Дмитрий. Раньше мы работали бариста, а в 2019 году открыли свою обжарку в Минске.', + 'Обжариваем небольшими партиями по 5 кг. «Кварта» значит «четвёртая»: четверг у нас день обжарки.', + ], + facts: [ + { value: '2019', label: 'открыли обжарку' }, + { value: '5 кг', label: 'одна партия' }, + { value: 'ЧТ', label: 'день обжарки' }, + ], + }, + + delivery: { + title: 'Доставка и самовывоз', + delivery: { + title: 'Доставка по Минску', + lines: [ + 'Привозим в пятницу.', + 'От 50 BYN бесплатно.', + 'Если заказ меньше, стоимость доставки уточнит менеджер.', + ], + }, + pickup: { + title: 'Самовывоз', + address: 'Минск, ул. Короля, 9', + hours: [ + { days: 'Пн–пт', time: '8:00–20:00' }, + { days: 'Сб–вс', time: '10:00–18:00' }, + ], + }, + cta: { label: 'Задать вопрос', interest: 'question' } satisfies Cta, + }, + + lead: { + title: 'Оставьте заявку', + subtitle: 'Менеджер перезвонит в рабочее время и всё уточнит.', + }, + + stickyCta: { + label: 'Заказать кофе', + note: 'Обжарка в четверг, доставка в пятницу', + interest: 'one_time' satisfies Interest, + }, + + footer: { + name: 'Кварта', + tagline: 'Обжарка кофе в Минске с 2019 года', + address: 'Минск, ул. Короля, 9', + hours: 'Пн–пт 8:00–20:00, сб–вс 10:00–18:00', + phone: CONTACT_PHONE, + phoneNote: 'Номер демонстрационный.', + photoCredit: 'Фото: Mona Jain, Tina Guina, Scott Soltys-Curry / Unsplash', + disclaimer: 'Учебный проект. Обжарка «Кварта» вымышленная.', + }, + + images: { + beans: { alt: 'Обжаренные кофейные зёрна крупным планом' }, + sack: { alt: 'Открытый мешок с обжаренным кофейным зерном' }, + cooler: { alt: 'Зерно остывает в охладителе ростера' }, + }, +} as const;