TuBrief
Subscribed Channels
Videos
Community

Alasan Mengapa Semua Landing Page Buatan AI Terlihat Sama dan Solusinya

TuBrief Editorial
August 22, 2026
0
Computing/Software

Written with AI assistance from the source video. The video is the authority.

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

Related Video

Impeccable Membuat Claude Mampu Membangun Situs yang Tidak Terlihat Seperti Buatan AI7:58

Impeccable Membuat Claude Mampu Membangun Situs yang Tidak Terlihat Seperti Buatan AI

Better Stack

More from the community

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

September 13, 2026

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

September 13, 2026

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

September 13, 2026

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

September 13, 2026

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

September 12, 2026

Apple Won the AI Race

September 12, 2026

Comments (0)

Log in to leave a comment

No posts yet

© 2026 . All rights reserved.

TuBrief
Subscribed Channels
Videos
Community
Log in

Alasan Mengapa Semua Landing Page Buatan AI Terlihat Sama dan Solusinya

Bagi pengembang solo yang menangani semuanya sendiri mulai dari perencanaan hingga penerapan, Cursor atau Claude Code terasa seperti penyelamat. Hanya dengan beberapa baris prompt, halaman web yang layak langsung jadi dalam waktu 10 menit.

Masalahnya ada setelah itu. Saat Anda menekan tombol deploy dan melihat layar, muncul perasaan déjà vu. Tombol gradasi ungu, font Inter, tata letak 3 kartu yang terpatri pas di tengah. Bau templat yang entah di mana pernah terlihat tercium kuat. Sekilas terlihat rapi, tetapi tidak berujung pada pembayaran atau pendaftaran pengguna. Orang-orang dengan sangat mahir dapat mengenali halaman yang tampak seperti buatan pabrik dan langsung menutup tab.

LLM bekerja berdasarkan rata-rata statistik. Jika Anda tidak memberikan aturan, mereka akan kembali ke preset bawaan Tailwind dan nilai bawaan Shadcn UI yang paling sering digunakan di web. Begitu Anda melontarkan prompt seperti "Buatlah landing page yang rapi dan elegan", AI akan memuntahkan nilai piksel inline yang tidak jelas seperti w-[320px], top-[117px], dan merusak tata letak.

M mencoba mengatasi masalah ini dengan modifikasi prompt saja akan membuat Anda kelelahan. Anda harus membangun sebuah pipa (pipeline) yang memaksa aturan merek setiap kali kode dihasilkan, dan secara fisik memblokir kode yang melanggar pada tahap commit.

Menulis File Aturan untuk Mengikat Tangan dan Kaki Agen AI

Cursor membaca .cursor/rules/*.mdc, Claude Code membaca CLAUDE.md, dan alat sumber terbuka membaca AGENTS.md. Jika Anda mendefinisikan token desain merek di file ini, AI tidak akan bisa menggunakan gaya sembarangan sejak tahap pembuatan kode.

Jika file aturan melebihi 500 baris, biaya konteks untuk membaca setiap sesi akan meningkat dan tingkat kepatuhan model juga akan menurun. Anda harus menulisnya dengan jelas sekitar 200–300 baris.

Buat .cursor/rules/design-system.mdc di root proyek dan masukkan konten berikut.

`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

`

Dengan memasukkan aturan ini, frekuensi AI menyuntikkan nilai arbitrase tanda kurung siku atau kode Hex secara langsung akan berkurang secara drastis.

Memblokir Commit Gaya Hardcode dengan Stylelint dan Husky

Prompt saja tidak cukup. AI sering kali mengabaikan aturan dan diam-diam mencampur nilai piksel inline. Kita menggabungkan Stylelint dan Git Pre-commit hook untuk memblokir jalur masuk gaya yang di-hardcode ke dalam repositori.

Instal alat-alatnya dan inisialisasi Husky.

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

`

Buat stylelint.config.mjs di root proyek. Ini adalah pengaturan untuk memunculkan error build jika kode warna atau nilai piksel arbitrer dimasukkan.

`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;

`

Tambahkan konfigurasi lint-staged ke package.json.

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

`

Daftarkan satu baris berikut ke dalam file .husky/pre-commit.

`bash
npx lint-staged

`

Sekarang setiap kali Anda mengetik git commit, kode yang di-staging akan dianalisis secara statis. Jika ada kode seperti margin: 17px yang dimasukkan sesuka hati oleh AI, proses commit itu sendiri akan gagal. Anda dapat menghemat sekitar 5 jam waktu per minggu yang biasa dihabiskan untuk perbaikan gaya.

Otomatisasi Uji Regresi Visual Menggunakan Playwright

Analisis statis hanya memeriksa aturan teks. Masalah seperti elemen yang saling tumpang tindih atau menu seluler yang rusak di layar ponsel baru bisa diketahui jika browser benar-benar dijalankan. Kita tidak mungkin memperkecil dan memperbesar viewport secara manual setiap saat, jadi kita mengotomatiskan perbandingan snapshot dengan Playwright.

Buat file 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'] } },
],
});

`

Tulis skrip pengujian (tests/visual/landing-page.spec.ts) yang memverifikasi 5 titik UI utama.

`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: Rendering Bagian Hero Desktop', 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: Rendering Viewport Menu Navigasi Seluler', 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: Penyelarasan Grid Kartu Harga', 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: Status Hover Tombol CTA Utama', async ({ page }) => {
const ctaButton = page.locator('button#primary-cta');
await ctaButton.hover();
await expect(ctaButton).toHaveScreenshot('cta-button-hover.png');
});

test('TC5: Tata Letak Modal Masuk', 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');
});
});

`

Daftarkan perintah ke package.json.

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

`

Hanya dengan menjalankan satu baris pnpm test:visual di terminal, tata letak yang rusak pada viewport desktop dan seluler dapat dideteksi dalam waktu 1 menit. Pekerjaan melelahkan yang mengharuskan Anda menyesuaikan ukuran layar satu per satu dengan mata telanjang dapat disingkirkan.

Jika Anda memiliki struktur di mana input AI dikendalikan oleh file aturan, masuknya gaya yang salah dicegah oleh Git hook, dan kerusakan layar diperiksa menggunakan Playwright, Anda dapat mempertahankan konsistensi desain bahkan dalam proyek pengembangan solo.