Motiva
Мои коллекции
← каталог

Landing Magazine

Журнал — архетип «медиа»: страница продаёт привычку читать. Оба блоговых варианта в паре и в разных ролях (blog-index — свежий номер, blog-grid — архив), цифры издания, редакция и одна подписка в подвале; в сокете hero — flow-strands как издательская метафора строк.

cssoglloadscrollrevealbasic~14 КБreduced-motion ✓
↗
↕ демо длиннее кадра — прокрутите его

Установка

npx shadcn@latest add https://motiva.pages.dev/r/landing-magazine.json
Что нужно в проекте до установки
  1. Файл components.json в корне

    Из него CLI узнаёт, куда класть файлы. Алиасы — в такой форме:

    "aliases": { "components": "@/components", "lib": "@/lib" }

    Нет файла — установка не начнётся вовсе.

  2. Алиас @ объявлен дважды

    В корневом tsconfig.json и в конфиге сборщика. В Vite корневой tsconfig часто содержит только references — этого мало.

    "paths": { "@/*": ["./src/*"] }        // tsconfig.json
    resolve.alias = { "@": "/src" }        // vite.config.ts

    Без paths CLI молча создаёт папку с именем @.

  3. Токены подключены один раз на приложение

    Они приезжают вместе с записью — достаточно импортировать их в точке входа:

    import "@/styles/motiva-tokens.css";

    Без них блок потеряет цвета, ритм и тему.

  4. Своя типографика не спорит с блоком

    Наследуемые свойства протекают внутрь: text-align: center на обёртке отцентрует содержимое секции. То же касается font-familyи line-height.

  5. Проект без TypeScript? всё равно нужен tsconfig

    CLI грузит tsconfig.json безусловно, а при "tsx": false идёт за jsconfig.json и падает так же. Минимум — файл с pathsи "tsx": true в components.json.

    Приехавший рядом .tsx можно не трогать — вам нужен .vanilla.js.

Экспорт

↓ Скачать .zip

Код

import { NavBlend } from "@/components/nav-blend";
import { HeroCentered } from "@/components/hero-centered";
import { FlowStrands } from "@/components/flow-strands";
import { BlogIndex } from "@/components/blog-index";
import { BlogGrid } from "@/components/blog-grid";
import { StatsBand } from "@/components/stats-band";
import { TeamGrid } from "@/components/team-grid";
import { FooterCta } from "@/components/footer-cta";

/**
 * Журнал — архетип «медиа»: страница продаёт не продукт, а ПРИВЫЧКУ ЧИТАТЬ.
 * Оба блоговых варианта работают в паре и в разных ролях: blog-index — свежий
 * номер (редакционный указатель со снимком за курсором), blog-grid — читаемое
 * из архива. Подписка одна и в подвале (footer-cta): у издания CTA не должен
 * перебивать чтение по дороге.
 *
 * В сокете hero — flow-strands: тонкие нити и есть строки, издательская
 * метафора без буквальности. Акцент — красный кирпич (--ds-accent-h: 25),
 * классика журнальной вёрстки.
 */
export function LandingMagazine() {
  return (
    <div
      className="lmg ds-scope"
      style={{
        textAlign: "start",
        ["--ds-accent-h" as string]: "25",
        ["--ds-section-y" as string]: "clamp(48px, 7vw, 96px)",
        background: "var(--ds-bg, oklch(0.14 0.02 275))",
      }}
    >
      <NavBlend brand="тираж" links={["Свежий номер", "Архив", "Редакция"]} cta="Подписаться" />

      <HeroCentered
        badge="независимый журнал о городе"
        title="Читаем город как текст"
        accentWords={2}
        sub="Раз в месяц — восемь длинных историй о том, как устроено место, где вы живёте: дворы, рынки, трамваи, люди и деньги за всем этим."
        primary="Свежий номер"
        secondary="Подписаться"
        note="без ленты и алгоритмов — только номер"
        background={
          // backdrop задан явно: дефолтная подложка эффекта берёт фон ТЕМЫ, и в
          // светлой теме hero с tone="dark" превращался в серую кашу. hue — НАЧАЛО
          // веера (нити расходятся на ~+0.3 по кругу): 0.93 идёт через красный в охру.
          <FlowStrands hue={0.93} count={5} speed={0.5} backdrop="oklch(0.13 0.02 275)" />
        }
        tone="dark"
        scrim={0.6}
      />

      <BlogIndex
        eyebrow="номер 48 · сентябрь"
        title="В свежем номере"
        items={[
          { title: "Кому принадлежит рынок: пять семей и один прилавок", tag: "деньги", date: "№48", image: "https://motiva.pages.dev/img/1016-900x675.jpg" },
          { title: "Трамвай № 3 глазами вагоновожатой", tag: "люди", date: "№48", image: "https://motiva.pages.dev/img/1057-900x675.jpg" },
          { title: "Дворы-колодцы: почему их перестали строить", tag: "город", date: "№48", image: "https://motiva.pages.dev/img/221-900x700.jpg" },
          { title: "Ночная смена хлебозавода — репортаж до рассвета", tag: "репортаж", date: "№48", image: "https://motiva.pages.dev/img/1021-600x750.jpg" },
        ]}
      />

      <BlogGrid
        eyebrow="архив"
        title="Читаемое за все номера"
        sub="Истории, которые продолжают присылать друг другу спустя годы."
        posts={[
          { title: "Карта запахов: чем пахнет каждый район", excerpt: "Полгода ходили с блокнотом и нюхали город — от коптилен до типографии.", date: "№31", rubric: "город", author: "Вера Штерн", readTime: "18 мин" },
          { title: "Последний часовщик на главной улице", excerpt: "Мастерской 62 года, очередь расписана на месяц. Поговорили о времени.", date: "№27", rubric: "люди", author: "Даниил Ром", readTime: "12 мин" },
          { title: "Куда уходит вода из фонтанов", excerpt: "Проследили весь путь: от насосной до легенды про подземное озеро.", date: "№40", rubric: "устройство", author: "Кира Мель", readTime: "15 мин" },
          { title: "Сколько стоит вывеска: экономика неона", excerpt: "Почему старые буквы гаснут и кто платит, когда они загораются снова.", date: "№44", rubric: "деньги", author: "Вера Штерн", readTime: "14 мин" },
          { title: "Гаражи как институция", excerpt: "Мастерские, сыроварня и репетиционная точка — экспедиция в кооператив «Луч».", date: "№36", rubric: "репортаж", author: "Даниил Ром", readTime: "20 мин" },
          { title: "Азбука подъездов: лепнина, кафель, почтовые ящики", excerpt: "Разбираем подъезд как жанр — с фотографиями и словарём.", date: "№22", rubric: "город", author: "Кира Мель", readTime: "10 мин" },
        ]}
      />

      <StatsBand
        items={[
          { value: 6, label: "лет выходим" },
          { value: 48, label: "номеров вышло" },
          { value: 120, suffix: " тыс.", label: "читателей в месяц" },
          { value: 8, label: "историй в номере" },
        ]}
      />

      <TeamGrid
        eyebrow="редакция"
        title="Четыре человека и город"
        sub="Пишем сами, снимаем сами, вычитываем друг друга."
        items={[
          { name: "Вера Штерн", role: "главный редактор", photo: "https://motiva.pages.dev/img/1015-600x750.jpg", about: "Придумала журнал в трамвае № 3. Пишет про деньги и запахи." },
          { name: "Даниил Ром", role: "репортёр", photo: "https://motiva.pages.dev/img/1018-600x750.jpg", about: "Умеет разговорить часовщика и вагоновожатую. Ночные смены — его." },
          { name: "Кира Мель", role: "редактор и картограф", photo: "https://motiva.pages.dev/img/1022-600x750.jpg", about: "Рисует карты и словари. Знает, куда уходит вода." },
          { name: "Стёпа Гран", role: "фотограф", photo: "https://motiva.pages.dev/img/1019-600x750.jpg", about: "Снимает на плёнку, потому что город того стоит." },
        ]}
      />

      <FooterCta
        title="Номер раз в месяц — в почту"
        sub="Подписка бесплатная. Печатную версию собираем дважды в год для подписчиков."
        action="Подписаться"
        brand="тираж"
        columns={[
          { title: "Журнал", links: ["Свежий номер", "Архив", "Печатные выпуски"] },
          { title: "Редакция", links: ["Кто мы", "Предложить историю", "post@tirazh.city"] },
        ]}
        note="Пишем раз в месяц, отписка одной кнопкой"
      />
    </div>
  );
}
лицензия: MITавтор: Motivaисточник: оригинал (Motiva)v1.0.0