Landing App
Лендинг настольного приложения — самая длинная готовая страница: тринадцать секций, из них восемь впервые на странице (баннер, минимальная шапка, кольца в сокете hero, схема интеграций с импульсами, сравнение, тумблер цен, FAQ колонками, панель загрузки с определением системы, строчная подписка). Характер — прохладная бирюза одним числом --ds-accent-h.
Установка
npx shadcn@latest add https://motiva.pages.dev/r/landing-app.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 { BannerSticky } from "@/components/banner-sticky";
import { NavMinimal } from "@/components/nav-minimal";
import { HeroCentered } from "@/components/hero-centered";
import { RippleRings } from "@/components/ripple-rings";
import { LogosGrid } from "@/components/logos-grid";
import { IntegrationsBeam } from "@/components/integrations-beam";
import { VideoFacade } from "@/components/video-facade";
import { ComparisonTable } from "@/components/comparison-table";
import { PricingToggle } from "@/components/pricing-toggle";
import { FaqColumns } from "@/components/faq-columns";
import { DownloadPanel } from "@/components/download-panel";
import { NewsletterInline } from "@/components/newsletter-inline";
import { FooterMinimal } from "@/components/footer-minimal";
/**
* Лендинг настольного приложения — пятая страница каталога и самая ДЛИННАЯ: тринадцать
* секций, среди них восемь, которых не было ни на одной готовой странице (баннер,
* минимальная шапка, кольца в сокете, схема интеграций, сравнение, тумблер цен,
* FAQ колонками, панель загрузки, строчная подписка).
*
* Характер — прохладная бирюза (`--ds-accent-h: 190`), ритм плотнее агентского:
* утилитарная страница читается списком, ей не нужен воздух витрины. Сокет hero
* держит `ripple-rings` — тихий фон, который не спорит с текстом; панель загрузки
* сама определяет систему посетителя и подсвечивает «его» сборку.
*/
export function LandingApp() {
return (
<div
className="lap ds-scope"
style={{
textAlign: "start",
["--ds-accent-h" as string]: "190",
["--ds-section-y" as string]: "clamp(40px, 6vw, 76px)",
background: "var(--ds-bg, oklch(0.14 0.02 275))",
}}
>
<BannerSticky
label="v3.2"
text="Вышла версия с офлайн-режимом — синхронизация догоняет сама."
ctaLabel="Что нового"
remember={false}
/>
<NavMinimal brand="pulse" links={["Возможности", "Интеграции", "Цены", "Скачать"]} cta="Скачать" />
<HeroCentered
badge="трекер времени без таймеров"
title="Учёт времени, который ведёт себя сам"
accentWords={3}
sub="Pulse смотрит, в каких окнах идёт работа, и раскладывает день по проектам. Вы только подтверждаете итог вечером — одним взглядом."
primary="Скачать бесплатно"
secondary="Как это работает"
note="macOS · Windows · Linux"
// кольца оставляют СВОЮ тёмную подложку: hero — тёмная вставка в любой теме,
// и tone="dark" со скримом честен и на светлой странице
background={<RippleRings hue={190} />}
tone="dark"
/>
<LogosGrid
eyebrow="о нас пишут"
title="Заметили те, кого читаете сами"
items={["TECHWEEK", "PRODUCTLY", "DEVCAST", "MAKERLOG", "SHIPIT", "OSSDAILY"]}
/>
<IntegrationsBeam
eyebrow="интеграции"
title="Pulse стоит в середине вашего дня"
sub="Слева — то, где идёт работа. Справа — куда уезжают отчёты. Всё само, по открытому API."
hub="P"
items={["VS Code", "Figma", "Браузер", "Jira", "Notion", "Google Календарь"]}
/>
<VideoFacade
eyebrow="одна минута"
title="Весь продукт — в одном ролике"
sub="День работы, свёрнутый в шестьдесят секунд: от первого запуска до вечернего отчёта."
caption="Понедельник глазами Pulse"
duration="1:02"
/>
<ComparisonTable
eyebrow="сравнение"
title="Чем Pulse отличается от таймера"
sub="Таймер честен, пока про него помнят. Pulse помнит сам."
columns={[
{ name: "Таймер", note: "любой" },
{ name: "Pulse", note: "$5/мес", featured: true },
{ name: "Таблица", note: "руками" },
]}
rows={[
{ label: "Учёт без кнопки «старт»", cells: [false, true, false] },
{ label: "Раскладка по проектам", cells: ["теги руками", "сама", "руками"] },
{ label: "Работает офлайн", cells: [true, true, true] },
{ label: "Отчёт заказчику", cells: [false, "одной ссылкой", "собирать час"] },
{ label: "Замечает переработки", cells: [false, true, false] },
]}
note="Сравниваем честно: таймер бесплатен, но помнит про него человек."
/>
<PricingToggle
eyebrow="цены"
title="Один тариф, две цены"
currency="$"
saveLabel="−20% за год"
plans={[
{
name: "Соло",
monthly: 0,
yearly: 0,
note: "для личного учёта",
features: ["Авто-учёт на одном устройстве", "История 3 месяца", "Экспорт CSV"],
cta: "Скачать",
},
{
name: "Про",
monthly: 5,
yearly: 4,
note: "для фрилансеров",
features: ["Все устройства, синхронизация", "История без предела", "Отчёты заказчику ссылкой", "Правила и вебхуки"],
cta: "Попробовать 30 дней",
featured: true,
},
{
name: "Команда",
monthly: 9,
yearly: 7,
note: "за человека",
features: ["Всё из «Про»", "Сводка по команде", "SSO", "Приоритетная поддержка"],
cta: "Собрать команду",
},
]}
/>
<FaqColumns
eyebrow="частые вопросы"
title="Про приватность спрашивают первым делом"
sub="И правильно делают."
contact="Не нашли ответа — спросите нас"
items={[
{ q: "Pulse видит, что я делаю?", a: "Он видит названия окон и приложений — не содержимое. Список исключений редактируется, инкогнито-режим есть." },
{ q: "Куда уходят данные?", a: "По умолчанию — никуда: всё лежит локально. Синхронизация в «Про» шифруется на устройстве, ключ только у вас." },
{ q: "Что с батареей?", a: "Наблюдатель событийный, а не опрашивающий: меньше процента за рабочий день на ноутбуке." },
{ q: "Есть ли API?", a: "Да, локальный REST и вебхуки. Отчёт можно забирать своим скриптом." },
{ q: "А если я за станком, не за экраном?", a: "Ручные блоки времени никуда не делись: два клика в меню-баре." },
{ q: "Можно уйти со всеми данными?", a: "Экспорт CSV и JSON в один клик, включая бесплатный тариф." },
]}
/>
<DownloadPanel
eyebrow="скачать"
title="Поставьте — и забудьте про таймер"
sub="Подсветили сборку под вашу систему. Подпись и нотаризация — как положено."
version="3.2.1"
released="сентябрь 2026"
builds={[
{ label: "macOS", note: "Apple Silicon и Intel · 13+", size: "38 МБ", match: "mac" },
{ label: "Windows", note: "10 и 11 · x64", size: "34 МБ", match: "win" },
{ label: "Linux", note: "AppImage · x64 и ARM", size: "41 МБ", match: "linux" },
]}
/>
<NewsletterInline
eyebrow="дневник сборки"
title="Раз в месяц — что изменилось и почему"
sub="Без маркетинга: список изменений и пара цифр из телеметрии, на которую вы согласились."
placeholder="you@work.dev"
buttonLabel="Подписаться"
note="Отписка — одной ссылкой в каждом письме"
/>
<FooterMinimal
brand="pulse"
tagline="Учёт времени, который ведёт себя сам"
columns={[
{ title: "Продукт", links: ["Возможности", "Интеграции", "Цены", "Изменения"] },
{ title: "Поддержка", links: ["Справка", "API", "Статус", "hello@pulse.app"] },
{ title: "Компания", links: ["Манифест", "Приватность", "Пресс-кит"] },
]}
/>
</div>
);
}