DOL Design System - Landing Page Patterns
Landing Page Patterns
Section titled “Landing Page Patterns”Extends CORE.md. Dành cho trang giới thiệu, showcase sản phẩm, guest pages. Đọc CORE.md trước - file này chỉ chứa patterns đặc thù cho landing.
§0 Named Composition Patterns - landing-context quick index
Section titled “§0 Named Composition Patterns - landing-context quick index”Mục đích: quick lookup khi đang đọc landing.md. Mỗi entry trỏ đến full recipe trong §6.X / §7.X.
Cross-product master registry:
design-guideline/pattern-registry.md- single-file index of ALL named patterns (mirror placement củaanti-pattern-registry.md). Đọc đó cho global view; đọc đây cho landing-specific quick.
| Name | When (1-line) | Recipe | Variants (item count) | Status |
|---|---|---|---|---|
| Constellation Block | Catalog of ≥4 items với cấu trúc thông tin tương đương (program/feature/methodology) - outputs “ecosystem statement” với 3-tier nested + star-effect gaps + optional bottom info row | §6.6 | 4 (2×2) · 6 (3×2 hoặc 2×3) · 8 (4×2 hoặc 2×4) | active |
Recall trigger phrases (AI auto-load recipe khi gặp)
Section titled “Recall trigger phrases (AI auto-load recipe khi gặp)”- “use Constellation Block cho [X]” / “apply Constellation Block pattern”
- “build catalog kiểu Constellation Block” / “Constellation Block với [N] items”
- “ecosystem block kiểu dol.vn” / “3-tier nested catalog với bottom row”
- Implicit: user mô tả “X+ programs/features/methodologies cùng family + (optional) summary row” → AI propose Constellation Block
Adapting to context (per pattern’s own decision matrix)
Section titled “Adapting to context (per pattern’s own decision matrix)”Recipe §6.6 có 2 decision tables AI dùng để adapt:
- Variants matrix - chọn layout theo item count (2×2 / 3×2 / 2×3 / 4×1) và mobile fallback
- Bottom info row by platform purpose - content layer adapt theo platform (self-study/sales/edu institution/none)
Future patterns added here khi
Section titled “Future patterns added here khi”- ≥2 surfaces actually use new pattern (rule of 3 to avoid premature codification)
- API + variants stable across ≥2 sessions
- Recipe codified với explicit when-to-use / when-not-to-use / anti-patterns
- User confirms naming uniqueness (per Constellation Block precedent - không generic)
§1 Hero Section status:done
Section titled “§1 Hero Section status:done”1.1 Canonical Structure
Section titled “1.1 Canonical Structure”EyebrowBadge ← badge nhỏ phía trên headlineh1 (with highlight) ← headline chính, phần nhấn dùng gradientp description ← mô tả ngắnCTA button pair ← primary + secondary1.2 Eyebrow Badge
Section titled “1.2 Eyebrow Badge”<div class="inline-flex items-center gap-2 bg-white border border-slate-200 rounded-full px-4 py-2 text-sm font-semibold text-slate-700 shadow-sm"> <IconName class="w-4 h-4 text-red-500" /> Badge text here</div>- Icon:
text-red-500(hoặc domain accent) - Text: neutral
text-slate-700 - KHÔNG
bg-blue-50 text-blue-600hoặctext-indigo-600cho eyebrow
1.3 Headline Highlight
Section titled “1.3 Headline Highlight”Phần text được nhấn mạnh trong h1 dùng gradient + underline decoration:
<h1 class="text-[40px] md:text-[56px] font-black text-slate-900 leading-tight"> Headline text <span class="relative inline-block"> <span class="relative z-10 text-transparent bg-clip-text bg-gradient-to-r from-red-600 to-red-400"> highlighted part </span> <span class="absolute bottom-1 left-0 w-full h-3 bg-red-100 -z-0 -rotate-1"></span> </span></h1>- Gradient:
from-red-600 to-red-400(brand) - Underline decoration:
bg-red-100, offsetbottom-1, slight rotation-rotate-1 - KHÔNG dùng blue/indigo/purple gradient cho headline
1.4 Hero Spacing Rhythm (Canonical)
Section titled “1.4 Hero Spacing Rhythm (Canonical)”EyebrowBadge (mb-6) ← 24px gaph1 (mb-6) ← 24px gapp description (mb-10) ← 40px gapbuttonsflex flex-collayout:mb-6trên EyebrowBadgespace-y-*layout: parent gap xử lý, không cần mb riêng
1.5 Description Typography
Section titled “1.5 Description Typography”| Property | Value | Lý do |
|---|---|---|
| Size | text-[17px] md:text-[19px] | Vừa đủ - KHÔNG text-xl hay text-2xl |
| Leading | leading-[1.6] | Consistent - KHÔNG leading-relaxed |
| Color | text-slate-500 font-medium | Dim nhưng readable |
1.6 CTA Button Pair
Section titled “1.6 CTA Button Pair”<!-- Primary --><button class="inline-flex items-center gap-2 group bg-blue-600 hover:bg-blue-700 text-white shadow-2xl shadow-blue-600/30 rounded-full px-8 py-4 text-[15px] font-bold hover:scale-105 active:scale-95 transition-all"> Start now <ArrowRight class="w-[18px] h-[18px] group-hover:translate-x-1 transition-transform" /></button>
<!-- Secondary --><button class="inline-flex items-center gap-2 bg-slate-50 hover:bg-slate-100 text-slate-700 border border-slate-200 rounded-full px-8 py-4 text-[15px] font-bold hover:scale-105 active:scale-95 transition-all"> Learn more</button>- Size:
px-8 py-4 text-[15px] font-bold rounded-full - Primary shadow:
shadow-2xl shadow-blue-600/30 - Hover:
hover:scale-105 active:scale-95- cả 2 button giống nhau - Icon (primary only):
ArrowRight+group-hover:translate-x-1
1.7 Anti-patterns
Section titled “1.7 Anti-patterns”🛑 Match-and-refuse (per DIRECTION §10): nếu bạn sắp generate code khớp một bullet dưới, STOP - rewrite approach từ đầu, không chỉ swap value lẻ.
<dol_anti_pattern scope=“landing-1.7-hero”>
| ID | ❌ PATTERN | ✅ REWRITE |
|---|---|---|
| 01 | Eyebrow dùng bg-blue-50 text-blue-600 hoặc text-indigo-600 | Brand-tinted eyebrow per §1.2 |
| 02 | Headline highlight dùng blue/indigo/purple gradient | Solid text-slate-900 + size/weight cho emphasis (anti slop-02) |
| 03 | Eyebrow text text-xs | Minimum text-sm |
| 04 | Description text-xl hoặc text-2xl | text-base / text-lg - không phá nhịp |
| 05 | Button font-black | font-bold only |
| 06 | Button py-5 text-lg (quá nặng) | py-4 text-[15px] |
| 07 | Primary/secondary button khác font-weight | Đồng bộ font-bold cho cả 2 |
</dol_anti_pattern>
§2 Feature Grid status:done
Section titled “§2 Feature Grid status:done”Extends CORE.md §4 Spacing + §5 Radius + §9.1 Card. Mid-page hero - balance visual interest với information density.
2.1 Canonical Structure
Section titled “2.1 Canonical Structure”3-column grid desktop, stack mobile. Each card: icon tile + heading + description + optional link.
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 max-w-6xl mx-auto"> {features.map(f => <FeatureCard key={f.id} {...f} />)}</div>- Breakpoint:
md:grid-cols-2 lg:grid-cols-3(1 → 2 → 3) - Gap:
gap-6(24px C-organism per CORE §4.1) - Container:
max-w-6xl mx-autopage-level alignment
2.2 Feature Card Recipe
Section titled “2.2 Feature Card Recipe”<div className="p-6 rounded-2xl bg-white border border-slate-200 hover:border-slate-300 transition-colors duration-200"> <div className="inline-flex items-center justify-center w-12 h-12 rounded-xl bg-blue-50 text-blue-600 mb-4"> <Icon className="w-6 h-6" /> </div> <h3 className="text-lg font-bold text-slate-900 mb-2">{title}</h3> <p className="text-sm text-slate-600">{description}</p> {link && ( <a className="inline-flex items-center gap-1 mt-4 text-sm font-semibold text-blue-600 hover:text-blue-700"> {link.label} <ArrowRight className="w-4 h-4" /> </a> )}</div>- Padding:
p-6(card-standard per CORE §4.2) - Radius:
rounded-2xl(16px feature card emphasis per DIRECTION §8) - Border:
border-slate-200default +border-slate-300hover (subtle, không flash) - matches CORE §8.1 canonical - Icon tile:
w-12 h-12 rounded-xl bg-{color}-50 text-{color}-600
2.3 Icon Tile Color by Category
Section titled “2.3 Icon Tile Color by Category”Feature categories map to skill/intent colors (CORE §2.4):
| Category | Icon bg | Icon text |
|---|---|---|
| Reading | bg-emerald-50 | text-emerald-600 |
| Listening | bg-blue-50 | text-blue-600 |
| Writing | bg-amber-50 | text-amber-600 |
| Speaking | bg-rose-50 | text-rose-600 |
| AI Features | bg-sky-50 | text-sky-600 |
| Generic / unspecified | bg-slate-50 | text-slate-600 |
2.4 Vertical Variant (2-column, fewer features)
Section titled “2.4 Vertical Variant (2-column, fewer features)”For 4-6 total features, use 2-column với larger cards:
<div className="grid grid-cols-1 md:grid-cols-2 gap-8"> {/* larger cards, more content per card */}</div>- Gap:
gap-8(32px - give breathing room) - Card padding:
p-8instead ofp-6 - Expandable: longer description, include bullet list of sub-features
2.5 Anti-patterns
Section titled “2.5 Anti-patterns”🛑 Match-and-refuse (per DIRECTION §10): nếu bạn sắp generate code khớp một row dưới, STOP - rewrite approach từ đầu, không chỉ swap value lẻ.
<dol_anti_pattern scope=“landing-2.5-feature-grid”>
| ID | ❌ PATTERN | Vì sao | ✅ REWRITE |
|---|---|---|---|
| 01 | Identical icon boxes across ALL cards (same color/size/shape) | R11 slop-06 icon-tile-above - screams AI-generated template | Vary color by category (§2.3); consider skip icon cho some cards |
| 02 | 4+ columns on desktop | Cards thin, text cramped, unreadable | Max 3 columns; 2 for emphasis |
| 03 | Heavy shadows (shadow-xl) on every card | Over-treatment competes với hero section | border-slate-100 base, shadow only on hover (subtle) |
| 04 | Centered text in every feature card | R11 slop-05 everything-centered | Left-align content; center icon tile only |
| 05 | Gradient card backgrounds | R11 slop-02 decoration without meaning | Solid white bg-white; accent via icon tile color |
| 06 | ”Learn more” link on every card (repeated) | Decision fatigue, không actionable | Skip link if all lead same place; else different labels per feature |
</dol_anti_pattern>
§3 Showcase Section status:done
Section titled “§3 Showcase Section status:done”Extends CORE.md §6 Surface + §7 Shadow + §9.1 Card. Showcase = visual proof - screenshot / video / interactive demo.
3.1 Single Screenshot (standard)
Section titled “3.1 Single Screenshot (standard)”Product screenshot với frame treatment:
<div className="relative mx-auto max-w-5xl"> <img src="/screenshot.png" alt="DOL English practice screen" className="w-full rounded-2xl border border-slate-200 shadow-[0_20px_60px_-15px_rgba(15,23,42,0.15)]" /></div>- Max width:
max-w-5xl(1024px) - strong visual presence, không fill screen - Border:
border-slate-200for definition on white bg - Shadow: custom
shadow-[0_20px_60px_-15px_rgba(15,23,42,0.15)]- ambient lift, không dramatic (neutral slate tone, không colored per R11 slop-07) - Radius:
rounded-2xl(16px - frame convention)
3.2 Before/After Comparison
Section titled “3.2 Before/After Comparison”Two-column với labels:
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <figure> <figcaption className="text-sm font-semibold text-slate-500 uppercase tracking-wide mb-3"> Trước </figcaption> <img src="/before.png" alt="..." className="w-full rounded-xl border border-slate-200" /> </figure> <figure> <figcaption className="text-sm font-semibold text-brand-600 uppercase tracking-wide mb-3"> Sau </figcaption> <img src="/after.png" alt="..." className="w-full rounded-xl border border-slate-200" /> </figure></div>- Label:
uppercase tracking-wide- small label tone (per DIRECTION §10, uppercase OK cho ≤3 words) - “Trước” neutral
text-slate-500, “Sau” accenttext-brand-600- narrative direction - Gap:
gap-4(16px - close enough để compare side-by-side) - Radius:
rounded-xl(12px - smaller than hero screenshot; part of comparison pair)
3.3 Interactive Demo Embed (browser-frame pattern)
Section titled “3.3 Interactive Demo Embed (browser-frame pattern)”Live demo hoặc iframe với browser chrome framing:
<div className="relative rounded-2xl overflow-hidden border border-slate-200 shadow-[0_20px_60px_-15px_rgba(15,23,42,0.15)] bg-slate-50 max-w-5xl mx-auto"> <div className="h-10 bg-slate-100 border-b border-slate-200 flex items-center gap-1.5 px-4"> <span className="w-3 h-3 rounded-full bg-slate-300" /> <span className="w-3 h-3 rounded-full bg-slate-300" /> <span className="w-3 h-3 rounded-full bg-slate-300" /> </div> <iframe src="/demo" className="w-full aspect-video" title="Product demo" /></div>- Chrome header:
h-10 bg-slate-100với 3 neutral dots (traffic lights) - familiar framing without platform confusion - Iframe:
aspect-video(16:9) default; custom aspect per demo type - Overflow:
overflow-hiddenclips content inside frame
3.4 Anti-patterns
Section titled “3.4 Anti-patterns”🛑 Match-and-refuse (per DIRECTION §10): nếu bạn sắp generate code khớp một row dưới, STOP - rewrite approach từ đầu, không chỉ swap value lẻ.
<dol_anti_pattern scope=“landing-3.4-showcase”>
| ID | ❌ PATTERN | Vì sao | ✅ REWRITE |
|---|---|---|---|
| 01 | Screenshot với rotate-3 / rotate-6 | Feels gimmicky, dated 2015 aesthetic | Flat, straight; use shadow for depth |
| 02 | Gradient overlay on product screenshot | Hides product details + R11 slop-02 territory | Clean image, let product speak |
| 03 | Multiple screenshots stacked tilted / overlapping | Over-design; screenshot should be focal | Single straight screenshot OR 2-column comparison |
| 04 | Colored glow behind screenshot | R11 slop-07 dark-glow; feels template | Neutral ambient shadow với rgba slate tone |
| 05 | Screenshot full-bleed (edge-to-edge) | Loses framing context, looks like bg | max-w-5xl mx-auto với border + shadow frame |
</dol_anti_pattern>
§4 Testimonials status:done
Section titled “§4 Testimonials status:done”Extends CORE.md §3 Typography + §9.1 Card. Social proof - credibility pattern via user quotes.
4.1 Quote Card Recipe
Section titled “4.1 Quote Card Recipe”<figure className="p-6 rounded-2xl bg-white border border-slate-200"> <blockquote className="text-base text-slate-700 leading-relaxed mb-4"> "{quote}" </blockquote> <figcaption className="flex items-center gap-3"> <img src={avatar} alt={name} className="w-10 h-10 rounded-full object-cover" /> <div> <div className="text-sm font-semibold text-slate-900">{name}</div> <div className="text-xs text-slate-500">{role}</div> </div> </figcaption></figure>- Use actual
<blockquote>+<figcaption>elements (a11y + SEO) - Quote:
text-base text-slate-700 leading-relaxed- readable, không oversized - Avatar:
w-10 h-10 rounded-full object-cover- small identity cue, không focal - Name:
text-sm font-semibold text-slate-900; role:text-xs text-slate-500
4.2 Star Rating Display
Section titled “4.2 Star Rating Display”Rating inline với quote hoặc near avatar:
<div className="flex items-center gap-0.5 text-amber-400 mb-2"> {Array.from({ length: 5 }).map((_, i) => ( <Star key={i} className={cn("w-4 h-4", i >= rating && "text-slate-200")} fill="currentColor" /> ))}</div>- Filled:
text-amber-400(warm tone for rating - không brand, không success) - Unfilled:
text-slate-200(muted but visible) - Size:
w-4 h-4- small, supports testimonial, không compete
4.3 Layout: Grid vs Carousel vs Masonry
Section titled “4.3 Layout: Grid vs Carousel vs Masonry”| Pattern | When | Layout |
|---|---|---|
| Grid (3-col) | Testimonials = peer-level, browse freely | grid grid-cols-1 md:grid-cols-3 gap-6 |
| Carousel | Space genuinely limited, testimonials rotate | Single card + manual prev/next |
| Masonry (varied heights) | Quotes vary in length, visual interest | columns-1 md:columns-3 gap-6 space-y-6 |
Default: grid (simpler, SEO-friendly, a11y-clean). Carousel only khi space thực sự limited. Avoid auto-play (reading time varies per user).
4.4 Anti-patterns
Section titled “4.4 Anti-patterns”🛑 Match-and-refuse (per DIRECTION §10): nếu bạn sắp generate code khớp một row dưới, STOP - rewrite approach từ đầu, không chỉ swap value lẻ.
<dol_anti_pattern scope=“landing-4.4-testimonials”>
| ID | ❌ PATTERN | Vì sao | ✅ REWRITE |
|---|---|---|---|
| 01 | Giant decorative quote marks " as text-6xl | Dated 2015 template; pulls weight from content | Skip OR small text-2xl text-slate-300 decorative |
| 02 | Avatar w-20 h-20 (huge) | Dominates quote content; signal inverted | w-10 h-10 - identity cue, không focal |
| 03 | Carousel auto-advance fast | Users can’t read before transition | Grid layout OR manual navigation; no auto-play |
| 04 | Testimonials without role / company | Lower credibility - could be fake | Always include role + company; anonymize only as “Học viên DOL” nếu cần |
| 05 | Star rating in different colors per testimonial | Inconsistent visual; feels random | Same text-amber-400 for all filled stars |
| 06 | ”★★★★★” emoji characters instead of icon | A11y poor, rendering inconsistent across platforms | Use Lucide/Heroicons Star component (scales, accessible) |
</dol_anti_pattern>
§5 CTA Sections status:done
Section titled “§5 CTA Sections status:done”Extends CORE.md §4 Spacing + §9.2-9.3 Button. Mid-page + bottom CTAs - conversion-critical placement.
5.1 Mid-page CTA Block
Section titled “5.1 Mid-page CTA Block”Standalone block với subtle visual distinction:
<section className="py-20 bg-blue-50"> <div className="max-w-3xl mx-auto text-center px-6"> <h2 className="text-3xl md:text-4xl font-bold text-slate-900 mb-4"> Sẵn sàng bắt đầu? </h2> <p className="text-lg text-slate-600 mb-8"> Short description - tại sao user nên act NOW. </p> <button className="bg-brand-600 text-on-inverse-primary rounded-full px-8 py-4 text-[15px] font-bold hover:bg-brand-700 hover:scale-105 active:scale-95 transition-all duration-200"> Đăng ký miễn phí </button> </div></section>- Section bg:
bg-blue-50(info dim) hoặcbg-slate-50(neutral tint). Khôngbg-brand-*- quá overwhelming cho mid-page - Padding:
py-20(80px vertical - generous breathing) - Container:
max-w-3xl mx-autocho text column - Center-aligned OK cho single focal block (exception to R11 slop-05; justified cho single CTA focal)
- Button uses brand color - this IS the brand moment
5.2 Bottom Conversion Section
Section titled “5.2 Bottom Conversion Section”Final page CTA trước footer:
<section className="py-24 bg-gradient-to-b from-slate-50 to-white"> <div className="max-w-4xl mx-auto text-center px-6"> <h2 className="text-4xl md:text-5xl font-bold text-slate-900 mb-6"> Bắt đầu hành trình học của bạn </h2> <p className="text-lg text-slate-600 mb-10 max-w-2xl mx-auto"> Supporting text dẫn đến action. </p> <div className="flex flex-col sm:flex-row gap-4 justify-center"> <button className="primary button recipe">Đăng ký miễn phí</button> <button className="secondary button recipe">Xem demo</button> </div> </div></section>- Larger visual weight than mid-page (final ask)
- Gradient bg acceptable:
bg-gradient-to-b from-slate-50 to-white(subtle, neutral tint, không flashy - contrast với mid-page solid tint) - Button pair: primary + secondary for “start” + “learn more”
5.3 Inline Signup Form
Section titled “5.3 Inline Signup Form”CTA với embedded email form (lower friction than full signup):
<form className="flex flex-col sm:flex-row gap-3 max-w-md mx-auto"> <input type="email" placeholder="email@example.com" aria-label="Email address" className="flex-1 border border-slate-200 rounded-full px-5 py-3 bg-white focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 outline-none" /> <button type="submit" className="bg-brand-600 text-on-inverse-primary rounded-full px-6 py-3 font-semibold hover:bg-brand-700 transition-colors"> Bắt đầu </button></form>- Input + button: matching
rounded-full(paired shape language per DIRECTION §8) - Inline on sm+, stack on xs (
flex-col sm:flex-row) - Submit button brand - this is the second legitimate brand moment on landing (first = hero primary CTA)
5.4 Anti-patterns
Section titled “5.4 Anti-patterns”🛑 Match-and-refuse (per
../ds-guideline/DIRECTION.md§10 +ai-memory/lessons/landing-tone-discipline.md- workspace-level): nếu bạn sắp generate copy khớp một row dưới, STOP - rewrite approach từ đầu, không chỉ swap word lẻ. Marketing-surface tone-discipline = orthogonal layer over universal slop.
<dol_anti_pattern scope=“landing-5.4-cta”>
| ID | ❌ PATTERN | Vì sao | ✅ REWRITE |
|---|---|---|---|
| 01 | Multiple CTAs per section (3+ buttons) | Decision paralysis - user không biết click gì | 1 primary + optional 1 secondary max |
| 02 | Full-width brand color section background | Overwhelming; brand saved for button emphasis | bg-blue-50 / bg-slate-50 section bg; brand only on button |
| 03 | ”Click here” / “Submit” generic copy | Low signal, low motivation, unclear action | Action-specific: “Đăng ký miễn phí”, “Bắt đầu học hôm nay” |
| 04 | CTA block immediately after hero | User chưa value-establish; conversion ask premature | Place after ≥2 feature/showcase sections |
| 05 | Multiple !!! in CTA copy | Desperate / sales-y tone | Calm confident: “Bắt đầu miễn phí” không “Đăng ký ngay hôm nay!!!“ |
| 06 | CTA form requires 5+ fields | High friction - form completion drops exponentially | Email-only inline form; full form behind “Đăng ký” button |
| 07 | CTA với countdown timer pressure | Manipulative; wrong DOL education tone | Value proposition, không scarcity pressure |
</dol_anti_pattern>
§6 Composition Foundation status:done
Section titled “§6 Composition Foundation status:done”Đây là chất riêng của landing DOL. Decoration (§7) tùy context có/không, nhưng spacing + content placement + box treatment luôn áp theo §6. Surface không follow §6 = không phải DOL landing dù dùng đúng token.
Decoded từ dol.vn V2 production (2026-04-25, R-future analysis). Lesson:
ai-memory/lessons/dol-vn-personality-decode.md.
6.1 Spacing rhythm 3-tier (page → section frame → content unit)
Section titled “6.1 Spacing rhythm 3-tier (page → section frame → content unit)”DOL landing có 3 tầng nhịp rõ ràng. Mỗi tầng có scale riêng - KHÔNG dùng 1 scale cho mọi cấp (slop-04 monotonous-spacing).
| Tier | Where | Scale | Class |
|---|---|---|---|
| Page rhythm | Section ↔ section | 96-128px | gap-24 đến gap-32 (giữa các <section>) |
| Section frame | Padding inside outer section card | 40-48px | p-10 đến p-12 |
| Content unit | Padding inside inner item card | 24-32px | p-6 đến p-8 |
Quy tắc chọn scale:
- Section quan trọng (hero, methodology, advantage) → cao end (128px / p-12 / p-8)
- Section list/grid (testimonials, teachers, students) → mid (96-112px / p-10 / p-6)
- Section CTA terminal → mid-low (96px / p-10 / p-6)
Bên trong section (eyebrow → heading → body → CTA):
| Step | Gap | Class | Note |
|---|---|---|---|
| Eyebrow → heading | 24-32px | gap-6 đến gap-8 | Eyebrow là intro, gap nhỏ giữ tight |
| Heading → body / grid | 48-64px | gap-12 đến gap-16 | Generous break, hero-tier rhythm |
| Body → CTA | 32-40px | gap-8 đến gap-10 | Mid break trước action |
| Inner grid items | 16-24px | gap-4 đến gap-6 | Atomic per spacing.md |
→ Tham chiếu philosophy: DIRECTION.md §7 Spacing philosophy (“breathing room is content”).
6.2 Content placement - asymmetric heading + accessory
Section titled “6.2 Content placement - asymmetric heading + accessory”Signature DOL move: heading section header KHÔNG center-aligned (trừ hero - slop-05 exception). Heading left-anchored + 1 accessory phía phải.
┌──────────────────────────────────────────────────────────────┐│ [Eyebrow Pill] ││ ││ Heading line 1 ┌────────────────────────┐ ││ Heading line 2 brand │ Accessory (optional) │ ││ └────────────────────────┘ ││ ││ [Body content / grid spans full width below] │└──────────────────────────────────────────────────────────────┘Accessory slot chứa 1 trong các options (dùng decoration-toolkit §7 chọn):
- Program toggle (IELTS / SAT / JUNIOR pills)
- Decorative connector (dotted arrow curve)
- Floating illustration / artifact stack
- Empty (heading đứng 1 mình - fallback minimal)
Heading line break rule: ngắt dòng theo nghĩa, không theo width. Mỗi dòng = 1 thought:
<h2 className="text-5xl md:text-6xl font-black tracking-tight text-slate-950"> Bảng vàng {/* dòng 1: chủ thể */} <br /> của <span className="text-brand-600">học viên DOL</span> {/* dòng 2: bổ ngữ + emphasis */}</h2>Eyebrow position: ABOVE heading (KHÔNG dùng floating bên cạnh). Eyebrow pill là intro card mini của section.
6.3 Box treatment 2-tier (section frame vs content unit)
Section titled “6.3 Box treatment 2-tier (section frame vs content unit)”DOL landing nesting 2 tầng card có roles distinct: outer = “section stage”, inner = “content units on stage”. Đây KHÔNG phải slop-03 nested-cards (slop-03 là 2 cards cùng treatment ôm nhau, role identical).
Tier 1 - Section frame (outer container):
<section className=" relative mx-auto max-w-[1200px] rounded-[40px] border border-slate-200 bg-white shadow-[0_8px_24px_rgba(15,23,42,0.06)] p-10 md:p-12"> {/* eyebrow + heading + content */}</section>| Property | Value | Why |
|---|---|---|
radius | rounded-[40px] | Signature DOL - generous radius, “pillowy confidence” per DIRECTION.md §8 |
border | border-slate-200 | Visible edge định nghĩa boundary trên trắng-trắng (per R25 finding) |
shadow | shadow-[0_8px_24px_rgba(15,23,42,0.06)] | Slate-900 tinted, alpha 0.06 - subtle depth, “paper on desk” DIRECTION.md §9 |
padding | p-10 to p-12 | Generous breathing room |
bg | bg-white (default) hoặc bg-slate-50/30 (alt nhịp) | Pure white default; alt cho section thay đổi |
Tier 2 - Content unit (inner item):
<article className=" rounded-2xl md:rounded-3xl border border-slate-200 bg-white p-6 md:p-8 hover:bg-slate-50/30 transition-colors"> {/* item content: photo + text + meta */}</article>| Property | Value | Why |
|---|---|---|
radius | rounded-2xl (16px) đến rounded-3xl (24px) | Smaller than outer - visual hierarchy by radius |
border | border-slate-100 | Subtle vì đã trên white frame (đủ contrast) |
shadow | optional, shadow-[0_2px_8px_rgba(15,23,42,0.04)] nếu cần | Lighter than outer - 2-tier shadow scale |
padding | p-6 to p-8 | Smaller than outer - content density appropriate |
Hierarchy bằng radius: outer 40px > inner 24px > nested-deep 16px. Mắt parse “container size” qua radius scale.
6.4 Quy tắc combine spacing + placement + box (the DOL signature)
Section titled “6.4 Quy tắc combine spacing + placement + box (the DOL signature)”3 layer trên hoạt động cùng nhau. Áp riêng từng layer KHÔNG đủ - phải combine có discipline:
- Section frame outer luôn
rounded-[40px]+p-10/12→ định nghĩa “stage” rõ - Heading left-anchored, line-break theo nghĩa, max 2-3 dòng → composition asymmetric editorial
- Inner items dùng
rounded-2xl+p-6/8→ hierarchy radius rõ ràng vs outer - Gap eyebrow→heading
gap-6/8, heading→bodygap-12/16→ nhịp 2-cấp distinct (intro vs body break) - Section gap
gap-24/32giữa các<section>→ page rhythm rõ ràng
→ Verify nhanh: nhìn surface từ xa 50%, có thấy được “section boundaries” rõ không? Nếu blur → §6 chưa đủ.
6.5 Anti-patterns composition
Section titled “6.5 Anti-patterns composition”<dol_anti_pattern scope=“landing-6-composition”>
| ID | ❌ Pattern | Why bad | ✅ Rewrite |
|---|---|---|---|
| 01 | Outer section card dùng rounded-2xl (cùng inner) | Mất hierarchy radius - outer + inner trông như cùng cấp | Outer rounded-[40px] / rounded-[32px], inner rounded-2xl/3xl |
| 02 | Section dùng p-4/p-6 thay p-10/p-12 | Generic SaaS card density, mất “stage frame” feel | Outer luôn p-10 đến p-12 |
| 03 | Heading center-aligned cho mọi section header | slop-05 everything-centered. DOL chỉ center hero, các section khác left-anchored + accessory | Heading left, accessory right (program toggle / connector / illustration / nothing) |
| 04 | Heading 1 dòng dài chiếm full width | Mất composition asymmetric, giảm visual rhythm | Break theo nghĩa thành 2-3 dòng; mỗi dòng 1 thought |
| 05 | Section ↔ section gap dùng gap-12/gap-16 | Section quá gần - page rhythm gãy | Page rhythm gap-24 đến gap-32 minimum |
| 06 | Inner items dùng cùng padding với outer (p-10) | Hierarchy padding mất, items không feel như “on stage” | Inner p-6 đến p-8, outer p-10 đến p-12 |
| 07 | Outer card không có border + shadow yếu (alpha ≤0.04) | Card trôi trên trắng-bg (R25 finding) | border-slate-200 + shadow-[0_8px_24px_rgba(15,23,42,0.06)] minimum trên pure white bg |
| 08 | Eyebrow dùng plain text thay pill | Mất “section identity card” treatment, intro nhạt | Eyebrow luôn pill style (per §7.2 recipe variants) |
</dol_anti_pattern>
6.6 Constellation Block - named composition pattern
Section titled “6.6 Constellation Block - named composition pattern”Constellation Block = 3-tier nested catalog container hiển thị N items có cấu trúc thông tin tương đương + (optional) bottom info row trong cùng visual frame. Tên gọi nhanh khi cần recall: “use Constellation Block cho program/feature/methodology catalog”.
Decoded từ dol.vn V2 production (Figma node
8796:77391“Listing Section”, session 2026-04-25 iter 5-8). First canonical impl:dol-edu-playground/components/Portal/DolLandingGuestV4.tsxhero section.Phân biệt với
slop-03 nested-cards(DIRECTION.md §10): slop-03 cấm cards CÙNG treatment chồng nhau (visual noise, excessive depth). Constellation Block dùng 3 tiers với DIFFERENT treatment per tier (outer white-frame-via-padding · middle gray-bg + visible border · cell rounded white block - radius 40/32/24 hierarchy) → intentional depth signal, KHÔNG violate slop-03. Match-and-refuse áp dụng khi tiers có cùng treatment, không khi tiers có roles distinct.
When to use
Section titled “When to use”- ≥4 items với content structure tương đương (brand wordmark + title + 1-line description)
- Cần “ecosystem statement” feel - items trong cùng family/catalog
- Optional bottom info row (proof points / methodology / community - ≤1 row trong cùng frame)
When NOT to use
Section titled “When NOT to use”- 1-3 items duy nhất → individual cards hoặc §2 Feature Grid
- Items có visual structure heterogeneous → heterogeneous grid
- Cần per-item complex CTA (form, multi-button) → §2 Feature Grid với card-level interaction
- Bottom row dài/phức tạp → tách thành section riêng
Anatomy - 3-tier nested + (optional) bottom row
Section titled “Anatomy - 3-tier nested + (optional) bottom row”{/* Tier 1: Outer "white frame" - 8px padding-as-frame (NO border-color), light shadow */}<div className="rounded-[40px] bg-white p-2 shadow-[0_8px_24px_rgba(15,23,42,0.04)] w-full">
{/* Tier 2: Middle "gray container" - visible border + bg-slate-100 + 1px inner padding + clip */} <div className="rounded-[32px] bg-slate-100 border border-slate-200 p-[1px] overflow-hidden">
{/* Tier 3: Grid - gap-[1px] reveals slate-100 → "star void" tại 4-cell intersections */} <div className="grid grid-cols-1 md:grid-cols-2 gap-[1px]">
{items.map((item) => ( <div className="bg-white rounded-[24px] flex flex-col items-center text-center justify-center p-8 md:p-12 cursor-pointer group hover:bg-slate-50/60 transition-colors duration-300">
{/* Brand pill - SVG logo preferred (no border); text wordmark fallback */} {/* Vite app: prefix asset path với import.meta.env.BASE_URL để resolve correctly khi base !== '/' */} <span className="inline-flex items-center justify-center px-8 py-2.5 rounded-full bg-white mb-6"> {item.logo ? ( <img src={`${import.meta.env.BASE_URL}${item.logo}`} alt={item.brand} className="h-7 md:h-8 w-auto" /> ) : ( <span className={`text-xl md:text-2xl font-black tracking-tight ${item.brandColor}`}> {item.brand} </span> )} </span>
{/* Title (slate-950 bold) */} <h3 className="text-xl md:text-2xl font-black text-slate-950 mb-2 leading-tight"> {item.title} </h3>
{/* Description (slate-500 small) */} <p className="text-sm md:text-base text-slate-500 max-w-[280px]"> {item.description} </p> </div> ))}
{/* Optional 5th cell: bottom info row - full-width */} <div className="bg-white rounded-[24px] md:col-span-2 px-6 md:px-8 py-5 flex flex-col md:flex-row md:items-center md:justify-between gap-4"> {/* Left: practice stats / proof / community - match platform purpose */} {/* Right: methodology chip (D logo + brand text) */} </div> </div> </div></div>Implementation contract - TypeScript + interactivity + complete bottom row
Section titled “Implementation contract - TypeScript + interactivity + complete bottom row”Item shape (TypeScript interface):
interface ConstellationItem { id: string; // unique key cho map brand: string; // wordmark text - always provide cho alt + fallback logo?: string; // SVG asset path (preferred when available, e.g., '/design-system/ds-assets/program-logo/style-1/<slug>.svg') brandColor: string; // Tailwind text class - used when logo absent (text wordmark fallback) title: string; // achievement headline (e.g., "Đạt band 6.5 - 8.0+") description: string; // audience/context, ≤2 lines path?: string; // navigation target - undefined → cell renders disabled (Coming soon UX)}Brand SVG logo asset paths (DS Asset Gallery - preferred when available):
Path format: data field stores path WITHOUT leading slash (relative form). Render-time prefix với base mechanism per app:
- Vite app (Playground/Studio):
${import.meta.env.BASE_URL}${path}→ resolves to/playground/design-system/...in dev + prod- Next.js (Wiki): use
assetPrefixconfig or absolute URL- HTML prototype: use full URL
https://dol-wiki.khoajak.design/design-system/...Asset deployment: in Playground dev, sync via
node scripts/sync-ds-assets.mjs(workspace-level - copies từ DS-Token Studio → Playground public/). Auto-runs khidev.mjs --prepare+--playground.
| Brand | Logo path (data field value) |
|---|---|
| IELTS | design-system/ds-assets/program-logo/style-1/ielts.svg |
| IELTS THCS | design-system/ds-assets/program-logo/style-1/ielts-thcs.svg |
| TOEIC | design-system/ds-assets/program-logo/style-1/toeic.svg |
| SAT (2017) | design-system/ds-assets/program-logo/style-1/sat-2017.svg |
| GMAT | design-system/ds-assets/program-logo/style-1/gmat.svg |
| ETS GRE | design-system/ds-assets/program-logo/style-1/ets-gre.svg |
| GMAT-ETS | design-system/ds-assets/program-logo/style-1/gmat-ets.svg |
| Junior | design-system/ds-assets/program-logo/style-1/junior.svg |
| THPT | design-system/ds-assets/program-logo/style-1/thpt.svg |
| ĐGNL | design-system/ds-assets/program-logo/style-1/dgnl.svg |
| K12 / K10 / K5 | design-system/ds-assets/program-logo/style-1/k{12,10,5}.svg |
| Phát âm | design-system/ds-assets/program-logo/style-1/phat-am.svg |
| Giao tiếp | design-system/ds-assets/program-logo/style-1/giao-tiep.svg |
| Tools | design-system/ds-assets/program-logo/style-1/tools.svg |
Browse complete catalog: DOL-DS-token/studio/public/ds-assets/_index.json - filter componentSlug=program-logo, axis=style-1.
Brand color fallback mapping (used khi logo absent - text wordmark mode):
| Brand | brandColor class | When |
|---|---|---|
| IELTS | text-brand-600 | Fallback nếu SVG asset chưa available |
| SAT | text-sky-500 (hoặc text-indigo-600) | Fallback |
| TOEIC | text-blue-700 | Fallback |
| Giao tiếp | text-emerald-600 | Fallback |
| Future/custom | DOL semantic palette per CORE.md §2 | KHÔNG dùng gray-*/zinc-*/neutral-* |
Cell interactivity - path-conditional disabled (built-in Coming-soon UX):
<div onClick={() => handleClick(item.path)} className={`bg-white rounded-[24px] flex flex-col items-center text-center justify-center p-8 md:p-12 group hover:bg-slate-50/60 transition-colors duration-300 ${item.path ? 'cursor-pointer' : 'cursor-default opacity-70'}`}>item.pathset → cell clickable (cursor-pointer + full opacity)item.pathundefined → cell auto-disabled (cursor-default + opacity-70). Use cho “Sắp ra mắt” / Coming-soon items.
Bottom row complete template - Self-study platform (Playground/Studio):
<div className="bg-white rounded-[24px] md:col-span-2 px-6 md:px-8 py-5 flex flex-col md:flex-row md:items-center md:justify-between gap-4"> {/* Left: practice stats với dot separators */} <div className="flex flex-wrap items-center gap-x-3 gap-y-2 md:gap-x-4 text-sm font-semibold text-slate-700"> <span className="flex items-center gap-2"> <BookOpen size={16} className="text-slate-500" /> <span>1.8K+ bài test</span> </span> <span className="h-1 w-1 rounded-full bg-slate-300" aria-hidden="true" /> <span className="flex items-center gap-2"> <Layers size={16} className="text-slate-500" /> <span>4 chương trình</span> </span> <span className="h-1 w-1 rounded-full bg-slate-300" aria-hidden="true" /> <span className="flex items-center gap-2"> <Sparkles size={16} className="text-sky-500" /> <span>AI cá nhân hoá</span> </span> </div> {/* Right: methodology chip - D logo trong brand-red circle + LINEARTHINKING label */} <div className="flex items-center gap-3"> <span className="hidden md:inline text-sm text-slate-500">Phương pháp độc quyền</span> <span className="inline-flex items-center gap-2 px-4 py-2 rounded-full border border-slate-200 bg-white"> <span className="w-5 h-5 rounded-full bg-brand-600 text-white flex items-center justify-center text-[10px] font-black">D</span> <span className="text-sm font-black tracking-wide text-brand-600">LINEARTHINKING</span> </span> </div></div>Other platforms (per “Bottom info row content theo platform purpose” decision matrix below):
- Sales/Funnel: Left = avatar stack + user count (e.g.,
<AvatarStack /> + "2.8M HV đang học"); Right = methodology chip (same as self-study) - Edu institution: Left = big-number proof points stack (e.g., “TOP 1 · 420+ courses · 84 teachers”); Right = methodology chip hoặc trust badge
- Catalog only: Skip bottom row entirely (use no-bottom variant)
Required imports (lucide icons cho Self-study Left side):
import { BookOpen, Layers, Sparkles } from 'lucide-react';Sales platform cần <AvatarStack /> component (Playground TBD - placeholder OK với 3 colored circles flex -space-x-2).
Optional outer animation (Tier 1 wrapper):
className="... animate-in fade-in slide-in-from-bottom-12 duration-700 delay-200"Apply trên Tier 1 outer cho whole-block fade-up entrance. Skip nếu Tailwind animate plugin chưa configured.
Radius hierarchy (signature DOL - 8px decrement per tier)
Section titled “Radius hierarchy (signature DOL - 8px decrement per tier)”| Tier | Radius | Step |
|---|---|---|
| Outer | rounded-[40px] | - |
| Middle | rounded-[32px] | 8px smaller |
| Cell | rounded-[24px] | 8px smaller again |
Mất hierarchy = wrong feel. Cùng radius 3 tiers = mất 3-tier visual depth.
Star-effect mechanics
Section titled “Star-effect mechanics”3 elements combined tạo “ngôi sao 4 cạnh” tại 4-cell intersections:
- Cell
bg-white rounded-[24px]- góc bo tròn individually - Grid
gap-[1px]- 1px khe giữa cells - Middle
bg-slate-100- gap reveal color
Khi 4 cells gặp nhau ở 1 điểm: 4 rounded corners + 1px gap = cross-shaped void reveal slate-100.
Variants
Section titled “Variants”| Variant | Items | Layout | When |
|---|---|---|---|
| 2×2 + bottom | 4 + 1 summary | grid-cols-1 md:grid-cols-2, 5th col-span-2 | Default cho 4-item catalog (DolLandingGuestV4) |
| 3×2 + bottom | 6 + 1 summary | grid-cols-1 md:grid-cols-3, 7th col-span-3 | dol.vn V2 reference (6-program catalog) |
| 2×3 no bottom | 6 only | grid-cols-1 md:grid-cols-2 | Catalog không cần summary row |
| 4×1 + bottom | 4 + 1 summary | grid-cols-1 lg:grid-cols-4, 5th col-span-4 | Wide layout (ít common) |
Mobile: mọi variants stack grid-cols-1 (1 col vertical).
Bottom info row content theo platform purpose
Section titled “Bottom info row content theo platform purpose”Critical: bottom row content phải match platform character - KHÔNG copy nội dung sales platform sang self-study, vice versa.
| Platform purpose | Left side | Right side |
|---|---|---|
| Self-study/Tool (Playground, Studio) | Practice stats + features (e.g., ”📖 1.8K+ bài test · 📚 4 chương trình · ✨ AI cá nhân hoá”) | Methodology chip (D + LINEARTHINKING) |
| Sales/Funnel (dol.vn course catalog) | Avatar stack + user count (e.g., ”👨👩🧑 2.8M HV đang học tại DOL”) | Methodology chip |
| Edu institution (academic landing) | Big-number proof points (e.g., “TOP 1 · 420+ courses · 84 teachers”) | Methodology chip hoặc trust badge |
| Catalog only (no platform brand) | Skip bottom row entirely | - (use no-bottom variant) |
Per-cell content rule - strict 3 elements
Section titled “Per-cell content rule - strict 3 elements”| Element | Source | Style |
|---|---|---|
| Brand wordmark pill | item.brand (short identifier - IELTS, SAT, etc.) | text-xl md:text-2xl font-black ${brandColor} trong white pill border-slate-200 |
| Title | item.title (achievement/headline) | text-xl md:text-2xl font-black text-slate-950 mb-2 |
| Description | item.description (audience/context, ≤2 lines) | text-sm md:text-base text-slate-500 max-w-[280px] |
KHÔNG add: body description dài, “Dành cho:” prefix, per-item CTA button, target uppercase tagline (target → goes into title).
Anti-patterns - Constellation Block
Section titled “Anti-patterns - Constellation Block”<dol_anti_pattern scope=“landing-6.6-constellation-block”>
| ID | ❌ | Why bad | ✅ |
|---|---|---|---|
| 01 | Outer dùng border-slate-100/200 (with border-color) | Frame 8px là padding-as-frame, không phải card với border | bg-white p-2 only - shadow đảm nhận visual edge |
| 02 | Quên overflow-hidden trên middle | Cells góc lòi ra ngoài middle’s rounded curve | Add overflow-hidden để clip at middle radius |
| 03 | Middle bg-slate-50 (quá nhạt) | Gap reveal invisible, mất star effect | bg-slate-100 minimum cho visible reveal |
| 04 | Cùng radius cho 3 tiers (e.g., outer + middle = rounded-[32px]) | Mất 3-tier hierarchy visual | Outer 40 > middle 32 > cell 24 (8px decrement) |
| 05 | Dùng divide-x divide-y thay gap-[1px] cho 2-col grid | Tailwind divide-x bug: cell 3 (col-1 row-2) có spurious left-border | gap-[1px] + per-cell rounded-[24px] |
| 06 | Bottom row OUTSIDE middle (sibling) | Mất unified ecosystem feel - bottom row tách rời | Bottom row INSIDE grid as md:col-span-2 cell |
| 07 | Per-cell border + shadow trên white | Visual noise, fights ecosystem unity | Cells chỉ bg-white rounded-[24px]; depth từ outer shadow only |
| 08 | Cell có >3 elements (icon-tile + title + target + body + audience + CTA) | Quá đậm content, mất minimal premium feel | Strict 3 elements: pill + title + description |
| 09 | Bottom row content sai platform purpose (sales tone trên self-study) | Tone mismatch - “X+ users bought” không relevant cho self-study tool | Match decision table §6.6 “Bottom info row by platform purpose” |
| 10 | Per-cell translate-y / scale lớn hover | Cells “jumps out” individually phá ecosystem unity | Subtle hover:bg-slate-50/60 (color shift only, no movement) |
</dol_anti_pattern>
Reference implementation
Section titled “Reference implementation”- First canonical:
dol-edu-playground/components/Portal/DolLandingGuestV4.tsx(hero section, line ~227-286) - Source design: dol.vn V2 Figma
91M0TpwuUd8dAkj7Yl6UyOnode8796:77391“Listing Section” - Iteration history + decisions:
ai-memory/lessons/constellation-block-pattern.md - Decoded patterns context:
ai-memory/lessons/dol-vn-personality-decode.md
Quick recall mnemonic
Section titled “Quick recall mnemonic”“Constellation Block” = 3-tier nested + 1px-gap star + col-span-2 bottom row Radius: outer 40 → middle 32 → cell 24 (signature 8px hierarchy) Frame: white-padding outer · slate-100 middle · white cells Per-cell: pill + title + description (3 elements, no more)
§7 Decoration Toolkit status:done
Section titled “§7 Decoration Toolkit status:done”Triết lý: decoration là tool theo context, không phải default. Có hoặc không tùy nội dung và mood section. Không bao giờ áp tất cả decorations cùng 1 surface - chọn 1-2 phù hợp tâm trạng section + page balance.
§6 fundamentals luôn áp; §7 decorations chọn lọc.
7.1 Decision matrix - USE WHEN / SKIP WHEN
Section titled “7.1 Decision matrix - USE WHEN / SKIP WHEN”| # | Decoration | USE WHEN | SKIP WHEN | Recipe |
|---|---|---|---|---|
| D1 | Eyebrow pill có icon/avatar/avatar-stack | Mọi section header (default - fundamentals) | Hero compact, modal, drawer | §7.2 |
| D2 | 2-color heading emphasis (slate + 1-word brand) | Hero, section quan trọng, advantage/methodology | Body section, dense list | §7.3 |
| D3 | Big-number proof-points (TOP 1 / 84 / 2.8M) | Stat row, social proof, achievement section | Feature grid, content cards | §7.4 |
| D4 | Type-pattern background (DOL DOL / IELTS SAT TOEIC repeating) | Brand-affirm sections (hero, methodology, advantage, teachers) | Content-heavy sections (testimonials, table, form) | §7.5 |
| D5 | Photo peek-edges (real photos peeking ngoài card edges) | Sections nhấn community/team/students | Abstract concept sections, methodology, settings UI | §7.6 |
| D6 | Ribbon badge (die-cut, color-coded) | Achievement display (band scores, certifications) | Status indicator (dùng Pill/Tag thay) | §7.7 |
| D7 | Certificate stack (3-card floating với flag badges) | IP / authority / trust artifact display | Generic feature cards | §7.7 |
| D8 | Dotted arrow connector | 2 visual elements cần narrative link (heading → toggle, item → meta) | Inside tight grids, between unrelated elements | §7.7 |
| D9 | Handwritten font accent | Personal/emotional section (testimonials, founder note, “tâm tình”) | Mọi UI khác (body, headings, labels, buttons) | §7.8 |
| D10 | Emoji sticker decoration (😊 😎 😩) | Playful tone section (teachers, achievement, “old way” pain) | Serious/financial/error contexts | §7.9 |
| D11 | Section accent color rotation (mỗi section accent khác) | Multi-section landing pages | Single-purpose pages (login, settings, app surface) | §7.10 |
| D12 | Asymmetric heading + accessory right | Default cho content sections (đã ở §6.2 - fundamentals) | Hero (centered allowed per slop-05 exception) | §6.2 |
Combine rule: max 2-3 decorations per section. Hero có thể nhiều hơn (D1+D2+D3+D4) vì là focal. Section nội dung dày chọn 1 D thôi (thường D1 eyebrow + nothing else).
7.2 Eyebrow pill variants
Section titled “7.2 Eyebrow pill variants”3 variant chính, chọn theo signal section cần:
{/* V1 - Icon + text (most common, generic intro) */}<span className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-slate-50 border border-slate-200 text-sm font-bold text-slate-700"> <Sparkles className="size-4 text-brand-600" /> Hệ sinh thái Luyện thi cá nhân hóa</span>
{/* V2 - Avatar stack + text (social proof intro) */}<span className="inline-flex items-center gap-3 px-3 py-2 rounded-full bg-slate-50 border border-slate-200 text-sm font-bold text-slate-700"> <AvatarStack avatars={[a1, a2, a3, a4]} size="xs" /> 3000+ Đánh giá học viên</span>
{/* V3 - Outline accent (section accent rotation D11) */}<span className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-white border-2 border-amber-200 text-sm font-bold text-amber-700"> <GraduationCap className="size-4" /> Giáo viên đứng lớp tại DOL</span>| Variant | When | Section accent color |
|---|---|---|
| V1 icon | Default | Neutral |
| V2 avatar-stack | Social proof signal (X+ reviews, Y+ users) | Neutral |
| V3 outline accent | Section có mood color đặc biệt (D11) | Match section accent |
7.3 2-color heading emphasis
Section titled “7.3 2-color heading emphasis”Rule: 1-2 từ key dùng text-brand-600 (hoặc accent color section), phần còn lại text-slate-950. KHÔNG cả heading đỏ.
<h2 className="text-5xl md:text-6xl font-black tracking-tight leading-tight text-slate-950"> Giá trị <span className="text-brand-600">khác biệt</span> tại DOL</h2>
{/* Hoặc với emphasis word ở dòng riêng */}<h2 className="text-5xl md:text-6xl font-black tracking-tight leading-tight text-slate-950"> Học viện Tiếng Anh Tư Duy <br /> <span className="text-brand-600">DOL English</span> <Sparkles className="inline-block size-8 text-brand-600 ml-2" /></h2>Emphasis word selection:
- Brand identity (“DOL English”, “DOL”)
- Adjective khác biệt key (“khác biệt”, “vượt trội”, “độc quyền”)
- Tên tính năng / phương pháp (“Linearthinking”, “IELTS Online”)
- KHÔNG nhấn động từ generic (“học”, “luyện”) trừ khi là focal verb
7.4 Big-number proof-points
Section titled “7.4 Big-number proof-points”<div className="flex items-start gap-12 md:gap-16"> <div className="text-center"> <div className="text-4xl md:text-5xl font-black text-slate-950">TOP 1</div> <div className="mt-2 text-xs font-bold uppercase tracking-wider text-slate-500"> Tiếng Anh Tư Duy </div> </div> <div className="text-center"> <div className="text-4xl md:text-5xl font-black text-slate-950">420+</div> <div className="mt-2 text-xs font-bold uppercase tracking-wider text-slate-500"> Khoá học tiếng Anh </div> </div> {/* ... */}</div>| Element | Class |
|---|---|
| Number | text-4xl md:text-5xl font-black text-slate-950 |
| Label | text-xs font-bold uppercase tracking-wider text-slate-500 |
| Gap number↔label | mt-2 |
| Gap stat↔stat | gap-12 đến gap-16 |
Reverse hierarchy: số TO + label nhỏ caps tracking. DOL nhấn số vì giáo dục = “kết quả đo được”. Đây là exception cho rule “uppercase tracking-wider chỉ cho label” - label dưới số CHÍNH LÀ label nhỏ (không phải body text), nên slop-10 không apply.
7.5 Type-pattern background (signature DOL)
Section titled “7.5 Type-pattern background (signature DOL)”Background SVG/CSS lặp brand vocabulary mờ < 5% opacity. KHÔNG dùng generic dot-grid (đã có Playground hiện tại).
<section className="relative"> {/* Type pattern bg */} <div aria-hidden="true" className="absolute inset-0 -z-10 opacity-[0.04] select-none pointer-events-none" style={{ backgroundImage: `url("data:image/svg+xml,${encodeURIComponent(` <svg xmlns="http://www.w3.org/2000/svg" width="600" height="200"> <text x="0" y="60" font-family="Plus Jakarta Sans" font-weight="900" font-size="64" fill="currentColor"> DOL TOEIC IELTS SAT JUNIOR </text> </svg> `)}")`, }} /> {/* Section content */}</section>Pattern vocabulary chọn:
- Generic landing →
DOL DOL DOL(brand affirm) - Methodology section →
LINEARTHINKING(IP affirm) - Program section →
IELTS TOEIC SAT JUNIOR(catalog affirm)
USE WHEN: section focal, ít content density, cần brand ambient texture. SKIP WHEN: testimonial grid (cards already busy), form, tables.
7.6 Photo peek-edges
Section titled “7.6 Photo peek-edges”Real photos positioned absolute peek từ left + right edges của outer section card. Slight rotation, varied size. Signal “we are real, alive”.
<section className="relative mx-auto max-w-[1200px]"> {/* Peek photos - left edge */} <img src="/students/student-1.jpg" aria-hidden="true" className="hidden lg:block absolute -left-12 top-1/4 w-32 h-40 rounded-2xl object-cover -rotate-6 shadow-lg" /> <img src="/students/student-2.jpg" aria-hidden="true" className="hidden lg:block absolute -left-8 bottom-1/4 w-28 h-36 rounded-2xl object-cover rotate-3 shadow-md" /> {/* Peek photos - right edge */} <img src="/students/student-3.jpg" aria-hidden="true" className="hidden lg:block absolute -right-12 top-1/3 w-32 h-40 rounded-2xl object-cover rotate-6 shadow-lg" />
{/* Main section card content */} <div className="relative z-10 rounded-[40px] border border-slate-200 bg-white p-10 md:p-12 ..."> {/* ... */} </div></section>Rules:
- 2-4 photos max (2 each side, balanced)
- Rotation
±3degđến±6deg(slight, không drama) - Varied size
w-28đếnw-36 aria-hidden="true"(decorative, không screen-reader)- Hidden < lg breakpoint (mobile crop edges)
- Real photos thật (không stock)
USE WHEN: hero, community/team/students sections, advantage section. SKIP WHEN: testimonials (nội dung đã dày), form, abstract concept.
7.7 Physical artifacts
Section titled “7.7 Physical artifacts”3 patterns mượn metaphor vật lý - anchor 1 trust dimension cụ thể. Treat as advanced patterns - chỉ build khi section thực sự cần affirmation đặc thù.
| Pattern | Metaphor | Anchor dimension |
|---|---|---|
| Ribbon badge (die-cut tail, color-coded by tier) | Huy chương / award | Achievement / tier |
| Certificate stack (3-card floating với rotation lệch + flag badges + dotted lines) | Chứng nhận thật | Authority / IP |
| Dotted arrow connector (curve SVG path, slate-300, dasharray) | Bút chì kẻ trên giấy | Narrative link / “from→to” |
→ Recipe detail: defer to landing-patterns/{ribbon-badge,certificate-stack,dotted-arrow}.md (R-future build khi cần).
7.8 Handwritten font accent
Section titled “7.8 Handwritten font accent”Personal/emotional section dùng handwritten script tương phản với heading sans-serif đậm. Tạo dual voice: corporate confident + personal warm.
<h2 className="text-5xl md:text-6xl font-black tracking-tight text-slate-950"> Lăng nghe <span className="text-brand-600">Dolbie</span> chia sẻ</h2><p className="font-script text-3xl text-brand-500 -rotate-3 inline-block"> Ngàn lời tâm tình ❤️</p>Font selection (cần add via DIRECTION.md §6 exception):
Caveat- friendly Vietnamese-compatible, casualPacifico- premium handwritten, formal personalDancing Script- elegant cursive
Rules:
- Chỉ dùng cho accent ngắn (≤8 từ) - không cho body, không cho heading chính
- Size
text-2xlđếntext-3xl - Rotation slight
-rotate-3đến-rotate-6 - Color:
text-brand-500hoặctext-slate-700(depending mood) - 1 lần mỗi page max - over-use phá premium feel
USE WHEN: testimonials section (“Ngàn lời tâm tình”), founder note, gratitude block, personal section. SKIP WHEN: technical section, dashboard, form, body anywhere.
→ Tham chiếu DIRECTION.md §6 Typography philosophy (accent font exception).
7.9 Emoji sticker decoration
Section titled “7.9 Emoji sticker decoration”<section className="relative"> <span aria-hidden="true" className="absolute -top-4 -left-4 text-5xl rotate-[-12deg] select-none"> 😊 </span> <span aria-hidden="true" className="absolute -bottom-4 -right-4 text-5xl rotate-[8deg] select-none"> 😎 </span> {/* section content */}</section>Rules:
- 1-2 stickers per section max
- Position absolute corners (-top/-left/-bottom/-right)
- Size
text-4xlđếntext-5xl - Slight rotation
-rotate-12đếnrotate-12 - Each sticker phải có role/meaning:
- 😊 / 😎 = warmth, friendliness (teacher section, community)
- 😩 = pain point (“old way” comparison)
- ❤️ = appreciation (testimonial header)
- 🎉 = achievement / milestone
- KHÔNG random emoji decoration
USE WHEN: section playful tone (teachers, achievement, pain comparison, gratitude). SKIP WHEN: financial/billing, error states, formal documentation, form.
7.10 Section accent color rotation
Section titled “7.10 Section accent color rotation”Multi-section landing chia thành “chapters” - mỗi chapter accent 1 color khác. Tạo navigation visual.
| Section type | Default accent | Eyebrow variant |
|---|---|---|
| Hero / brand intro | brand-600 | V1 icon hoặc V2 avatar-stack |
| Methodology / advantage / IP | brand-600 | V1 icon |
| Teachers / mentors | amber-600 | V3 outline amber |
| Students / showcase | Color-coded ribbons (red/purple/cyan/green/orange by tier) | V2 avatar-stack |
| Testimonials / community | brand-500 (lighter) + handwritten accent | V2 avatar-stack |
| AI / smart features | sky-600 | V1 icon Sparkles |
| Premium / special | purple-600 | V3 outline purple |
| CTA terminal | brand-600 | V1 icon |
Rule: max 3 distinct accent colors per landing - over-rotate phá unity. Brand red = anchor color luôn xuất hiện ≥30% sections.
7.11 Anti-patterns decoration
Section titled “7.11 Anti-patterns decoration”<dol_anti_pattern scope=“landing-7-decoration”>
| ID | ❌ Pattern | Why bad | ✅ Rewrite |
|---|---|---|---|
| 01 | Áp tất cả decorations vào 1 section (peek-photos + type-pattern bg + ribbon + emoji + handwritten) | Visual chaos, no focal point | Max 2-3 decorations / section; chọn theo mood |
| 02 | Type-pattern bg với generic dot/grid (không brand vocabulary) | Generic SaaS feel - mất “cá tính DOL” | Brand vocabulary (DOL / IELTS / TOEIC / LINEARTHINKING) |
| 03 | Emoji sticker random không meaning (🌟 ⭐ ✨ scattered) | Templated AI-tell, mất ý đồ | Mỗi sticker có role; max 2/section |
| 04 | Handwritten font cho body / labels / buttons | Phá premium feel; readability fail; over-use kill effect | Chỉ accent ngắn ≤8 từ, 1 lần/page max |
| 05 | Photo peek-edges dùng stock photo / illustration | Trust signal đảo ngược - “fake decoration” | Real photos của student/teacher/community thật |
| 06 | Ribbon badge cho status indicator (active/disabled/loading) | Misuse metaphor - ribbon = achievement, không phải status | Dùng Pill / Tag / Badge cho status |
| 07 | Certificate stack cho generic feature (“tính năng mới”) | Wasted authority signal | Chỉ dùng cho IP / authority / actual artifact |
| 08 | Dotted arrow connector trong tight grid | Visual noise, confuses parsing | Connector chỉ giữa 2 elements có narrative link rõ |
| 09 | Section accent color rotation >3 distinct colors / page | Mất unity, page như rainbow | Max 3 accent colors; brand red ≥30% sections |
| 10 | 2-color heading nhấn cả câu (text-brand-600 toàn heading) | Brand red flat, mất focal word | Chỉ 1-2 từ key đỏ, còn lại slate-950 |
| 11 | Big-number block dùng text-2xl (số nhỏ) + text-base label (label to) | Hierarchy đảo ngược proof-point treatment | Số text-4xl/5xl font-black, label text-xs uppercase tracking-wider |
</dol_anti_pattern>
§8 Quick reference - fundamentals checklist
Section titled “§8 Quick reference - fundamentals checklist”Trước khi merge landing PR, run mental checklist:
§6 Composition (REQUIRED):
- Section frame
rounded-[40px]+p-10/12+border-slate-200+shadow-[0_8px_24px_rgba(15,23,42,0.06)]? - Inner items
rounded-2xl/3xl+p-6/8+border-slate-100? - Heading left-anchored (trừ hero)? Multi-line break theo nghĩa?
- Eyebrow pill ABOVE heading?
- Section ↔ section gap
gap-24/32? - Eyebrow → heading
gap-6/8, heading → bodygap-12/16?
§7 Decoration (OPTIONAL - chọn 1-2):
- Đã chọn decoration phù hợp mood section qua
§7.1matrix? - Max 2-3 decorations / section (hero có thể nhiều hơn)?
- Mỗi decoration có role rõ, không random?
- Section accent color rotation ≤3 distinct / page?
Nếu mọi gạch đầu dòng §6 đều ✅ → đã có “chất riêng DOL” trong fundamentals. §7 quyết định mood, không quyết định identity.