TuBrief
구독 채널
비디오
커뮤니티

Почему созданные ИИ лендинги выглядят одинаково и как это исправить

TuBrief 편집팀
2026년 8월 22일
0
Computing/Software

원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.

Русский한국어EspañolالعربيةDeutschPortuguêsBahasa IndonesiaEnglish中文हिन्दीFrançais日本語

관련 영상

Impeccable помогает Claude создавать сайты, которые не выглядят как ИИ-поделки7:58

Impeccable помогает Claude создавать сайты, которые не выглядят как ИИ-поделки

Better Stack

커뮤니티의 다른 글

사내 시스템에 llm api 붙일 때 마주하는 현실적인 한계와 대응법

2026년 9월 13일

레거시 백엔드에 GPT-6 Astra 붙일 때 예산 승인과 보안 통과를 먼저 끝내는 법이 있습니다

2026년 9월 13일

에이전트끼리 대화하다 6천만 원 청구서가 나오는 이유

2026년 9월 13일

사내 RAG 벡터 검색에 Okta 권한 필터를 직접 거는 방법

2026년 9월 13일

브라우저 에이전트에게 내 구글 계정을 통째로 넘기면 안 되는 이유

2026년 9월 12일

Apple Won the AI Race

2026년 9월 12일

댓글 (0)

Log in to leave a comment

아직 작성된 글이 없습니다

© 2026 . All rights reserved.

TuBrief
구독 채널
비디오
커뮤니티
로그인

Почему созданные ИИ лендинги выглядят одинаково и как это исправить

Для инди-разработчика, который в одиночку справляется со всем от проектирования до деплоя, Cursor или Claude Code кажутся настоящими спасителями. Пара строчек промта — и приличная веб-страница готова всего за 10 минут.

Проблема начинается дальше. Нажимаете кнопку деплоя, смотрите на экран — и появляется чувство дежавю. Фиолетовые градиентные кнопки, шрифт Inter, трехколоночный макет по центру. От этого веет шаблоном, который где-то уже видели. Внешне все аккуратно, но конверсии в оплаты или регистрации нет. Пользователи прекрасно замечают штампованные страницы и просто закрывают вкладку.

LLM работают на основе статистического усреднения. Если не задать правила, модель скатывается к самым распространенным в сети дефолтным пресетам Tailwind и значениям Shadcn UI. Как только вы забрасываете промт вроде “сделай чистый и стильный лендинг”, ИИ начинает сыпать непонятными инлайн-значениями пикселей вроде w-[320px], top-[117px], полностью ломая верстку.

Пытаться исправить это правкой промтов быстро надоедает. Нужно выстроить пайплайн, который при каждом создании кода будет жестко навязывать правила бренда, а нарушающий их код — физически блокировать на этапе коммита.

Создание файла правил, связывающего руки ИИ-агентам

Cursor читает .cursor/rules/*.mdc, Claude Code — CLAUDE.md, а открытые инструменты — AGENTS.md. Если прописать в таком файле дизайнерские токены бренда, ИИ не сможет произвольно использовать стили прямо с этапа генерации кода.

Если файл правил переваливает за 500 строк, растут затраты на контекст для чтения на каждой сессии, а модель начинает хуже следовать инструкциям. Правила должны быть четкими, в пределах 200–300 строк.

Создадим в корне проекта .cursor/rules/design-system.mdc и добавим в него следующее содержимое:

`yaml

description: Design System Rules and Custom Token Enforcement
globs: ["src/app//*.tsx", "src/components//.tsx", "src/styles/**/.css"]
alwaysApply: false

Brand Design System Constraints

Universal Rules

  • MUST NOT use arbitrary Tailwind utility classes such as bg-[#123456] or h-[117px].
  • MUST use predefined semantic Design Tokens for colors, spacing, and typography.
  • MUST run pnpm lint:style to verify token compliance before completing tasks.

Design Token Reference Map

Color Tokens

  • Surface Background: var(--color-bg-primary) (Tailwind: bg-brand-primary)
  • Surface Secondary: var(--color-bg-secondary) (Tailwind: bg-brand-secondary)
  • Text Main: var(--color-text-main) (Tailwind: text-brand-main)
  • Text Muted: var(--color-text-muted) (Tailwind: text-brand-muted)
  • Accent Primary: var(--color-accent-default) (Tailwind: bg-brand-accent)

Spacing Scale (8pt Grid Standard)

  • var(--space-1): 0.25rem (4px)
  • var(--space-2): 0.5rem (8px)
  • var(--space-4): 1.0rem (16px)
  • var(--space-6): 1.5rem (24px)
  • var(--space-8): 2.0rem (32px)

Typography Rules

  • Main Heading (H1): Class text-brand-h1 -> Font: Inter, Weight: 700, Size: 2.5rem, Tracking: -0.02em
  • Body Text: Class text-brand-body -> Font: Inter, Weight: 400, Size: 1.0rem, Leading: 1.5

`

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

Блокировка жестко закодированных стилей при коммите с помощью Stylelint и Husky

Одних промтов мало. ИИ то и дело игнорирует правила и тайком подмешивает инлайн-пиксели. Связка Stylelint и Git Pre-commit хуков перекрывает путь жестко закодированным стилям в репозиторий.

Установим инструменты и инициализируем Husky:

`bash
pnpm add -D husky lint-staged stylelint stylelint-declaration-strict-value
npx husky init

`

Создадим в корне проекта stylelint.config.mjs. Эта конфигурация вызывает ошибку сборки при появлении произвольных цветовых кодов или пиксельных значений:

`javascript
import type { Config } from "stylelint";

export default {
plugins: ["stylelint-declaration-strict-value"],
rules: {
"scale-unlimited/declaration-strict-value": [
["/color/", "font-size", "/margin/", "/padding/"], { ignoreVariables: false, ignoreFunctions: false, ignoreKeywords: { "": ["transparent", "inherit", "currentColor", "auto", "0"] }, message: "Design System Violation: Hardcoded value for '{property}' is forbidden. Use CSS Design Tokens instead."
}
]
}
} satisfies Config;

`

Добавим настройки lint-staged в файл package.json:

`json
{
"lint-staged": {
"*.{css,scss,tsx,jsx}": [
"stylelint --fix",
"eslint --max-warnings=0"
]
}
}

`

Зарегистрируем одну строчку в файле .husky/pre-commit:

`bash
npx lint-staged

`

Теперь при каждом выполнении git commit запускается статический анализ проиндексированного кода. Если там обнаружится добавленный ИИ по собственной воле код вроде margin: 17px, сам коммит завершится ошибкой. Это позволяет экономить около 5 часов в неделю, которые раньше уходили на правку стилей.

Автоматизация визуального регрессионного тестирования с помощью Playwright

Статический анализ проверяет только текстовые правила. Проблемы с наложением элементов или поломанным меню на мобильных экранах можно выявить, только запустив браузер. Вручную сужать и расширять вьюпорт каждый раз утомительно, поэтому сравнение снимков экрана автоматизируется через Playwright.

Создадим файл playwright.config.ts:

`typescript
import { defineConfig, devices } from '@playwright/test';
.export default defineConfig({
testDir: './tests/visual',
snapshotPixelRatioTemplate: '{snapshotDir}/{testFileDir}/{testFileName}-snapshots/{arg}{ext}',
expect: {
toHaveScreenshot: {
maxDiffPixelRatio: 0.01,
threshold: 0.2,
animations: 'disabled',
},
},
webServer: {
command: 'pnpm dev',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
timeout: 120 * 1000,
},
projects: [
{ name: 'Desktop Chrome', use: { ...devices['Desktop Chrome'] } },
{ name: 'Mobile Safari', use: { ...devices['iPhone 13'] } },
],
});

`

Напишем тестовый скрипт для проверки 5 ключевых элементов интерфейса (tests/visual/landing-page.spec.ts):

`typescript
import { test, expect } from '@playwright/test';

test.describe('Visual Regression Guardrails', () => {
test.beforeEach(async ({ page }) => {
await page.goto('http://localhost:3000');
await page.evaluate(() => document.fonts.ready);
});

test('TC1: Десктопная отрисовка хиро-секции', async ({ page }) => {
await page.setViewportSize({ width: 1440, height: 900 });
const heroSection = page.locator('section#hero');
await expect(heroSection).toBeVisible();
await expect(heroSection).toHaveScreenshot('hero-desktop.png', { maxDiffPixelRatio: 0.01 });
});

test('TC2: Отрисовка мобильного меню навигации во вьюпорте', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 812 });
const navBar = page.locator('header#main-nav');
await expect(navBar).toHaveScreenshot('nav-mobile.png');
});

test('TC3: Выравнивание сетки карточек цен', async ({ page }) => {
await page.setViewportSize({ width: 1280, height: 800 });
const pricingGrid = page.locator('div#pricing-cards');
await expect(pricingGrid).toHaveScreenshot('pricing-grid.png', {
mask: [page.locator('.dynamic-price-timestamp')]
});
});

test('TC4: Состояние наведения на главную кнопку CTA', async ({ page }) => {
const ctaButton = page.locator('button#primary-cta');
await ctaButton.hover();
await expect(ctaButton).toHaveScreenshot('cta-button-hover.png');
});

test('TC5: Макет модального окна входа', async ({ page }) => {
await page.click('button#open-login-modal');
const modalDialog = page.locator('div[role="dialog"]');
await expect(modalDialog).toBeVisible();
await expect(modalDialog).toHaveScreenshot('login-modal.png');
});
});

`

Зарегистрируем команды в package.json:

`json
{
"scripts": {
"test:visual": "playwright test",
"test:visual:update": "playwright test --update-snapshots"
}
}

`

Всего одна команда pnpm test:visual в терминале позволяет за минуту находить сломанные макеты на десктопных и мобильных экранах. Это избавляет от необходимости вручную двигать размеры окон и вглядываться в детали.

Если выстроить структуру, где вводные данные ИИ контролируются файлом правил, неверные стили отсекаются Git-хуками, а повреждения верстки проверяются Playwright, вы сможете поддерживать дизайн-консистентность даже в проектах для одного разработчика.