const heroStats = [ { value: "1 key", label: "быстрое исправление" }, { value: "Smart", label: "обучение словам" }, { value: "Per app", label: "исключения для приложений" }, ]; const featureNotes = [ { issue: "01", title: "Автоматически переключает раскладку", text: "Исправляет слова на лету по одному сочетанию клавиш и постепенно учит ваши привычные замены.", tone: "blue", }, { issue: "02", title: "Запоминает ваши слова", text: "После нескольких конвертаций Langy начинает подставлять нужный вариант автоматически.", tone: "peach", }, { issue: "03", title: "Исключения для приложений", text: "Можно отключить работу Langy в отдельных программах, где автозамена только мешает.", tone: "lavender", }, ]; const appRows = [ "Автозапуск", "Автоматическое переключение", "Звук после переключения", "Сочетание клавиш — Control", "Left Shift + Right Shift — изменить регистр выделенного слова", "Command + Shift + V — вставить текст без форматирования", ]; const learnedRows = [ { left: "rjulf → когда", right: "4 раз", tone: "green" }, { left: "drec → вкус", right: "4 раз", tone: "green" }, { left: "rjulr → когда", right: "1 раз", tone: "orange" }, ]; const excludedApps = ["Cursor", "Safari", "Google Chrome", "Figma", "Telegram", "Session"]; function runSanityChecks() { if (!Array.isArray(featureNotes) || featureNotes.length < 3) { throw new Error("featureNotes must contain at least 3 items"); } if (!Array.isArray(heroStats) || heroStats.length !== 3) { throw new Error("heroStats must contain exactly 3 items"); } if (!Array.isArray(appRows) || appRows.length === 0) { throw new Error("appRows must not be empty"); } } runSanityChecks(); function toneClass(tone) { switch (tone) { case "blue": return "note note-blue"; case "peach": return "note note-peach"; case "lavender": return "note note-lavender"; default: return "note"; } } function rowToneClass(tone) { switch (tone) { case "green": return "word-row word-green"; case "orange": return "word-row word-orange"; default: return "word-row"; } } function MacDots() { return ( ); } function MetricCard({ value, label }) { return (
{value}
{label}
); } function FeatureCard({ issue, title, text, tone }) { return (
Issue {issue}

{title}

{text}

); } function MockSettingsWindow() { return (
Langy
{appRows.map((item, index) => (
{item} {index < 3 ? : null}
))}
); } function MockLearnedWordsWindow() { return (
Langy

Langy будет запоминать слова которые вы конвертируете через Control.

Изученные слова 19
{learnedRows.slice(0, 2).map((item, index) => (
{item.left} {item.right}
))}
Слова в процессе изучения 58
{learnedRows[2].left} {learnedRows[2].right}
); } function MockAppsWindow() { return (
Langy
Добавленные программы в исключения
Cursor
Запущенные программы
{excludedApps.slice(1).map((app) => (
{app} +
))}
); } function MockSupportWindow() { return (
Langy
Игорь А. Юлия Х. Александр Д.
QR

Поддержи разработку Langy

Привет! Я Виктор, автор Langy. Это полностью бесплатное приложение, и даже небольшой донат помогает развивать продукт дальше.

); } export default function App() { return ( <>
Langy
macOS utility for bilingual typing

Переключает раскладку так, будто macOS наконец поняла вас.

Langy — минималистичное приложение для тех, кто постоянно печатает на двух языках и устал исправлять слова вручную.

{heroStats.map((item) => ( ))}
Dia-inspired layout

Feature notes

Большие заголовки, спокойные пастельные поверхности, карточки как заметки о релизах и крупные product shots.

{featureNotes.map((item) => ( ))}
Words memory

Не просто исправляет. Запоминает.

Langy замечает повторяющиеся ручные конвертации и помогает перейти от механики к привычке. Через время приложение само подставляет нужное слово.

Step 01
Нажали Control
Step 02
Повторили несколько раз
Step 03
Langy меняет слово автоматически
App exceptions

Контроль по приложениям

Добавляйте программы в исключения и включайте Langy только там, где он реально нужен — в мессенджерах, браузере, редакторе кода или документах.

Support project

Небольшой, живой продукт

На лендинге можно показать человеческую сторону продукта: автор, open support и аккуратный донат-блок вместо безликой корпоративности.

Final block

Typing in two languages should feel invisible.

Концепт лендинга собран как редакционный product page: крупная типографика, мягкие фоны, секции-фичи и демонстрация реальных сценариев продукта в духе Dia release notes.

); }