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

Landing Devtool

Лендинг CLI-инструмента — инженерный архетип: установка одной командой сразу после hero (разработчик пришёл ставить, а не читать), спецификации цифрами, ролик с главами вместо длинного текста, честное сравнение с grep и IDE. Терминальная зелень на сетке лучей; две новые секции встали в страницу в день рождения.

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

Установка

npx shadcn@latest add https://motiva.pages.dev/r/landing-devtool.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 { NavSticky } from "@/components/nav-sticky";
import { HeroCentered } from "@/components/hero-centered";
import { GridBeams } from "@/components/grid-beams";
import { DownloadCli } from "@/components/download-cli";
import { SpecsGrid } from "@/components/specs-grid";
import { FeaturesColumns } from "@/components/features-columns";
import { VideoChapters } from "@/components/video-chapters";
import { ComparisonTable } from "@/components/comparison-table";
import { FaqAccordion } from "@/components/faq-accordion";
import { CtaSplit } from "@/components/cta-split";
import { FooterMinimal } from "@/components/footer-minimal";

/**
 * Лендинг CLI-инструмента — «инженерный» архетип: установка одной командой
 * СРАЗУ после hero (разработчик пришёл ставить, а не читать), спецификации
 * цифрами, ролик с главами вместо длинного текста. Две новые секции
 * (download-cli и video-chapters) встали в страницу в день рождения.
 *
 * Характер — терминальная зелень (--ds-accent-h: 150) на сетке лучей в hero:
 * дев-инструменту идёт машинная эстетика, а не маркетинговый глянец.
 */
export function LandingDevtool() {
  return (
    <div
      className="ldt ds-scope"
      style={{
        textAlign: "start",
        ["--ds-accent-h" as string]: "150",
        ["--ds-section-y" as string]: "clamp(44px, 6vw, 84px)",
        background: "var(--ds-bg, oklch(0.14 0.02 275))",
      }}
    >
      <NavSticky brand="grep2" links={["Установка", "Возможности", "Сравнение", "Доки"]} cta="Поставить" />

      <HeroCentered
        badge="поиск по коду · открытый код"
        title="Ищет по миллиону строк быстрее, чем вы моргаете"
        accentWords={4}
        sub="grep2 — поиск по коду с пониманием синтаксиса: находит символы, а не подстроки. Один бинарник, ноль конфигурации."
        primary="Поставить за минуту"
        secondary="Смотреть на деле"
        note="macOS · Linux · Windows"
        background={<GridBeams />}
        tone="dark"
      />

      <DownloadCli
        eyebrow="установка"
        title="Одна команда — и в деле"
        sub="Выберите свой менеджер. Обновления приедут тем же путём."
        managers={[
          { name: "brew", command: "brew install grep2" },
          { name: "winget", command: "winget install grep2" },
          { name: "apt", command: "sudo apt install grep2" },
          { name: "cargo", command: "cargo install grep2" },
        ]}
        altText="Не любите менеджеры?"
        altLabel="Бинарники и исходники"
      />

      <SpecsGrid
        eyebrow="цифры"
        title="Скорость — это спецификация"
        items={[
          { value: "38", unit: "мс", label: "поиск по монорепе на миллион строк" },
          { value: "1", unit: "файл", label: "бинарник без зависимостей" },
          { value: "9", unit: "МБ", label: "вес установки" },
          { value: "40", unit: "языков", label: "синтаксис из коробки" },
        ]}
      />

      <FeaturesColumns
        eyebrow="возможности"
        title="Три вещи, которые он делает лучше всех"
        numbered
        items={[
          { title: "Символы, не подстроки", text: "Ищет определения и использования: «где объявлена useCart» вместо тысячи совпадений по слову cart." },
          { title: "Понимает гит", text: "Игнорирует то же, что и репозиторий, ищет по правкам и веткам: «где это менялось за неделю»." },
          { title: "Отдаёт машине", text: "Вывод в JSON одной опцией — редакторы, скрипты и агенты читают без парсинга человеческого текста." },
        ]}
      />

      <VideoChapters
        eyebrow="на деле"
        title="Пятнадцать секунд работы"
        sub="Кликните главу — ролик перемотается к нужному приёму."
        chapters={[
          { at: "0:00", title: "Холодный старт", note: "Первый поиск сразу после установки" },
          { at: "0:04", title: "Поиск символа", note: "Определение против использований" },
          { at: "0:09", title: "Фильтр по гиту", note: "Только то, что менялось в ветке" },
          { at: "0:13", title: "JSON-вывод", note: "Отдаём результат скрипту" },
        ]}
      />

      <ComparisonTable
        eyebrow="сравнение"
        title="Против классики"
        sub="Классика прекрасна. Мы просто про другую задачу."
        columns={[
          { name: "grep", note: "эталон" },
          { name: "grep2", note: "этот инструмент", featured: true },
          { name: "IDE-поиск", note: "в редакторе" },
        ]}
        rows={[
          { label: "Понимает синтаксис", cells: [false, true, true] },
          { label: "Работает в пайпах", cells: [true, true, false] },
          { label: "Скорость на монорепе", cells: ["секунды", "38 мс", "после индексации"] },
          { label: "Вне своего редактора", cells: [true, true, false] },
          { label: "JSON для машин", cells: [false, true, false] },
        ]}
        note="Сравнивали на публичной монорепе в 1,1 млн строк; методика в доках."
      />

      <FaqAccordion
        eyebrow="вопросы"
        title="Спрашивают перед установкой"
        items={[
          { q: "Это замена grep?", a: "Нет, дополнение: для подстрок grep быстрее и везде есть. grep2 — когда нужен смысл: символы, области видимости, правки." },
          { q: "Нужна ли индексация?", a: "Нет. Разбор ленивый, кеш прогревается первым запросом и живёт рядом с репозиторием." },
          { q: "Что с приватностью?", a: "Инструмент офлайновый: ни телеметрии, ни сети. Проверяемо — код открыт." },
          { q: "Мой язык поддержан?", a: "Сорок языков из коробки; свой добавляется грамматикой tree-sitter за вечер." },
        ]}
      />

      <CtaSplit
        title="Поставьте — и попробуйте на своём коде"
        sub="Одна команда, девять мегабайт. Если не приживётся — удалить так же просто."
        primary="brew install grep2"
        secondary="Читать доки"
      />

      <FooterMinimal
        brand="grep2"
        tagline="Поиск по коду с пониманием синтаксиса"
        columns={[
          { title: "Продукт", links: ["Установка", "Возможности", "Изменения", "Дорожная карта"] },
          { title: "Разработчикам", links: ["Документация", "Грамматики", "JSON-схема", "GitHub"] },
          { title: "Сообщество", links: ["Обсуждения", "Багтрекер", "hello@grep2.dev"] },
        ]}
      />
    </div>
  );
}
лицензия: MITавтор: Motivaисточник: оригинал (Motiva)v1.0.0