Landing Shop
Магазин — десятый архетип и первая страница с товарной витриной (product-grid): промо-баннер с кодом, короткий hero без шейдера (картинки — сами товары), сразу каталог, три честных обещания, отзывы покупателей, вопросы и подписка на новинки.
Установка
npx shadcn@latest add https://motiva.pages.dev/r/landing-shop.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 { NavSticky } from "@/components/nav-sticky";
import { HeroCentered } from "@/components/hero-centered";
import { ProductGrid } from "@/components/product-grid";
import { FeaturesColumns } from "@/components/features-columns";
import { TestimonialsGrid } from "@/components/testimonials-grid";
import { FaqAccordion } from "@/components/faq-accordion";
import { NewsletterInline } from "@/components/newsletter-inline";
import { FooterMinimal } from "@/components/footer-minimal";
/**
* Магазин — десятый архетип и первая страница с ТОВАРНОЙ витриной (product-grid,
* новый вид секции). Порядок подчинён покупке: промо-баннер с кодом → короткий hero →
* сразу товары (за ними сюда и пришли) → снятие трёх страхов доставки → чужой опыт →
* вопросы → подписка на новинки.
*
* Hero здесь НАМЕРЕННО без фонового шейдера: в магазине картинки — сами товары,
* и живой фон спорил бы с витриной за внимание. Характер странице даёт тёплый
* терракотовый акцент (--ds-accent-h: 45) — один на баннер, плашки и цены.
*/
export function LandingShop() {
return (
<div
className="lsh ds-scope"
style={{
textAlign: "start",
["--ds-accent-h" as string]: "45",
["--ds-section-y" as string]: "clamp(44px, 6.5vw, 88px)",
background: "var(--ds-bg, oklch(0.14 0.02 275))",
}}
>
<BannerSticky
label="промо"
text="−15% на первый заказ по коду TUBUS15 — до конца месяца"
ctaLabel="В каталог"
storageKey="lsh-promo"
/>
<NavSticky brand="тубус" links={["Каталог", "Доставка", "Отзывы", "Вопросы"]} cta="Корзина" />
<HeroCentered
badge="печать под заказ"
title="Принты, которые доезжают в тубусе"
accentWords={2}
sub="Фотографии севера, напечатанные на плотной бумаге и холсте. Печатаем под заказ, отправляем за три дня, рамку подберём по размеру."
primary="Смотреть каталог"
secondary="Как выбрать размер"
note="доставка по всей стране"
/>
<ProductGrid />
<FeaturesColumns
eyebrow="как это работает"
title="Три вещи, за которые отвечаем"
sub="Магазин маленький, поэтому обещания короткие и проверяемые."
items={[
{ title: "Печать под заказ", text: "Не храним тиражей: ваш принт печатается после оплаты и уезжает в течение трёх дней" },
{ title: "Тубус, не конверт", text: "Жёсткий тубус переживает почту любой суровости — за четыре года ни одного замятого угла" },
{ title: "Возврат без вопросов", text: "Не легло на стену — вернём деньги в течение двух недель, принт можно оставить себе" },
]}
/>
<TestimonialsGrid
eyebrow="отзывы"
title="Что пишут после распаковки"
items={[
{ text: "Заказывала «Тихую воду» в спальню — цвет бумаги благородный, не глянец. Дошло за пять дней, тубус можно использовать вторично.", name: "Ольга К.", featured: true },
{ text: "Брал три принта А3 в офис. Упаковано так, что вскрывать было дольше, чем вешать.", name: "Дмитрий Р.", role: "покупает второй раз" },
{ text: "Просил напечатать свой кадр — помогли с цветокоррекцией и не взяли за это денег.", name: "Артём С." },
{ text: "Подарок уехал сразу получателю с открыткой. Сервис уровня «запомню и вернусь».", name: "Мария Л.", role: "заказ в подарок" },
]}
/>
<FaqAccordion
eyebrow="частые вопросы"
title="Что спрашивают до заказа"
items={[
{ q: "Какие размеры бывают?", a: "А3, А2 и А1. Кадры 4:5 — под эти пропорции подобраны все фотографии каталога. Нестандартный размер — напишите, посчитаем за день." },
{ q: "Можно напечатать свой кадр?", a: "Да. Пришлите файл — проверим разрешение под выбранный размер и честно скажем, если для А1 его не хватит." },
{ q: "Сколько идёт доставка?", a: "Печать — до трёх дней, дальше почта или курьер: по крупным городам обычно 2–4 дня, дальше — до недели. Номер отслеживания приходит сразу." },
{ q: "Что с рамками?", a: "Рамки не продаём, но к каждому принту прикладываем памятку с размерами и тремя проверенными вариантами — от багетной мастерской до массмаркета." },
]}
/>
<NewsletterInline
eyebrow="новинки"
title="Раз в месяц — письмо с новыми кадрами"
sub="Без распродажных воплей: пять новых принтов, одна история со съёмки."
buttonLabel="Подписаться"
note="Отписка одной кнопкой в любом письме"
/>
<FooterMinimal
brand="тубус"
tagline="Печатаем север под заказ с 2022 года"
columns={[
{ title: "Магазин", links: ["Каталог", "Доставка и оплата", "Возврат", "Подарочные карты"] },
{ title: "Помощь", links: ["Как выбрать размер", "Про бумагу и холст", "Свой кадр", "hello@tubus.store"] },
]}
/>
</div>
);
}