Landing Waitlist
Вейтлист — страница до продукта: шесть секций, одна цель — почта. Hero на silk (обещание держится на ощущении, не на скриншотах), живой отсчёт первой волны, три обещания в bento, форма с лид-магнитом и вопросы.
Установка
npx shadcn@latest add https://motiva.pages.dev/r/landing-waitlist.jsonЧто нужно в проекте до установки
Файл
components.jsonв корнеИз него CLI узнаёт, куда класть файлы. Алиасы — в такой форме:
"aliases": { "components": "@/components", "lib": "@/lib" }Нет файла — установка не начнётся вовсе.
Алиас
@объявлен дваждыВ корневом
tsconfig.jsonи в конфиге сборщика. В Vite корневой tsconfig часто содержит толькоreferences— этого мало."paths": { "@/*": ["./src/*"] } // tsconfig.json resolve.alias = { "@": "/src" } // vite.config.tsБез
pathsCLI молча создаёт папку с именем@.Токены подключены один раз на приложение
Они приезжают вместе с записью — достаточно импортировать их в точке входа:
import "@/styles/motiva-tokens.css";Без них блок потеряет цвета, ритм и тему.
Своя типографика не спорит с блоком
Наследуемые свойства протекают внутрь:
text-align: centerна обёртке отцентрует содержимое секции. То же касаетсяfont-familyиline-height.Проект без TypeScript? всё равно нужен tsconfig
CLI грузит
tsconfig.jsonбезусловно, а при"tsx": falseидёт заjsconfig.jsonи падает так же. Минимум — файл сpathsи"tsx": trueвcomponents.json.Приехавший рядом
.tsxможно не трогать — вам нужен.vanilla.js.
Экспорт
Код
import { NavMinimal } from "@/components/nav-minimal";
import { HeroCentered } from "@/components/hero-centered";
import { Silk } from "@/components/silk";
import { BannerCountdown } from "@/components/banner-countdown";
import { FeaturesBento } from "@/components/features-bento";
import { NewsletterSplit } from "@/components/newsletter-split";
import { FaqColumns } from "@/components/faq-columns";
import { FooterMinimal } from "@/components/footer-minimal";
/**
* Вейтлист — одиннадцатый архетип, страница ДО продукта: продавать нечего, задача одна —
* забрать почту. Отсюда строение: шесть секций, одна цель, ноль расходящихся CTA
* (обе кнопки hero ведут к форме). Краткость — как у портфолио — сама по себе решение.
*
* В сокете hero — silk: ткань с моделью освещения, дорогая и спокойная — обещание
* продукта, которого ещё нет, держится на ощущении, а не на скриншотах. Отсчёт
* в banner-countdown идёт от демо-дедлайна самой секции (живой, не истёкший);
* в бою deadline заменяется реальной датой запуска.
*/
export function LandingWaitlist() {
return (
<div
className="lwl ds-scope"
style={{
textAlign: "start",
["--ds-accent-h" as string]: "200",
["--ds-section-y" as string]: "clamp(44px, 6.5vw, 88px)",
background: "var(--ds-bg, oklch(0.14 0.02 275))",
}}
>
<NavMinimal brand="прилив" links={["Что внутри", "Вопросы"]} cta="В список" />
<HeroCentered
badge="открываемся этой осенью"
title="Почта, которая заканчивается"
accentWords={2}
sub="Клиент, который сортирует входящие до нуля за вами: рассылки — в дайджест, счета — в папку, на письма от людей — черновик ответа к утру."
primary="Занять место в списке"
secondary="Что будет внутри"
note="в списке 2 184 человека"
background={<Silk hue={0.56} speed={0.22} />}
tone="dark"
scrim={0.58}
/>
<BannerCountdown
label="запуск"
text="Первая волна приглашений уйдёт через"
doneText="Рассылаем приглашения первой волне"
ctaLabel="Успеть в волну"
/>
<FeaturesBento
eyebrow="что внутри"
title="Три обещания вместо тура по продукту"
sub="Скриншоты покажем в письме. Здесь — то, что не изменится."
items={[
{ title: "Ноль за вечер", text: "Входящие сортируются до пустой папки сами; вы читаете дайджест, а не ленту", span: 2, rows: 2, accent: "200" },
{ title: "Черновики к утру", text: "На письма от людей — готовый черновик вашим тоном", accent: "260" },
{ title: "Свои правила", text: "Каждое действие можно посмотреть, поправить или запретить", accent: "150" },
{ title: "Почта остаётся вашей", text: "Работает поверх любого IMAP; ушли — всё осталось как было", span: 2, accent: "60" },
]}
/>
<NewsletterSplit
eyebrow="ранний доступ"
title="Место в первой волне"
sub="Приглашаем по порядку списка. Первой волне — пожизненная цена раннего доступа."
bullets={[
"Приглашение в первую волну — по порядку списка",
"Цена раннего доступа навсегда, что бы ни стало с тарифами",
"Раз в две недели — письмо о ходе разработки без воды",
]}
cardTitle="Записаться в список"
buttonLabel="Занять место"
note="Никакого спама: только приглашение и редкие письма о ходе дела"
/>
<FaqColumns
eyebrow="вопросы"
title="Что спрашивают до записи"
items={[
{ q: "Когда запуск?", a: "Первая волна приглашений — по отсчёту выше. Дальше волнами раз в пару недель, по порядку списка." },
{ q: "Это бесплатно?", a: "Ранний доступ — да. После запуска будет платный тариф; записавшимся сейчас его цена фиксируется навсегда." },
{ q: "Какая почта подойдёт?", a: "Любая с IMAP: Gmail, Яндекс, Fastmail, свой сервер. Ничего переносить не надо — работаем поверх." },
{ q: "Что с приватностью?", a: "Письма не покидают ваш ящик: правила выполняются у вас, модели не дообучаются на вашей переписке." },
]}
contact="Остальное спросите письмом"
contactHref="#"
/>
<FooterMinimal
brand="прилив"
tagline="Почта, которая заканчивается"
columns={[
{ title: "Сейчас", links: ["Список ожидания", "Ход разработки", "hello@priliv.app"] },
]}
/>
</div>
);
}