Production Platform: weddinginvietnam.com & vietnamweddingguide.com
Headless CMS Studio: studio.weddinginvietnam.com
Framework Stack: Next.js 16 (App Router, React 19) + Sanity Studio v3 + Tailwind CSS v4 (CSS-first)
Vietnam Wedding Guide is designed as a hybrid luxury editorial publication and private advisory platform. It combines the strict aesthetic fidelity of bespoke editorial layouts with the flexibility of a headless CMS.
flowchart TD
subgraph Client["Users & Stakeholders"]
Couples["International Destination Couples"]
B2B["Resorts & Hospitality Partners"]
Editors["Content & Advisory Team"]
end
subgraph NextJS["Frontend Layer (Next.js 16 App Router)"]
Router["App Router Engine"]
subgraph RenderingStrategy["Dual-Rendering Pattern"]
direction TB
CheckBlocks{"page.blocks > 0?"}
BespokeViews["Bespoke Editorial Views<br/>(components/templates/*)"]
PageBuilder["Page Builder Blocks<br/>(components/blocks/*)"]
end
subgraph SharedSystems["Shared UI & Logic"]
FounderBio["FounderBioSection (4 variants)"]
CTABanner["LuxuryCTABanner"]
SiteConstants["site.ts & partnership.ts"]
WALib["whatsapp.ts (Concierge Deep-Links)"]
end
end
subgraph SanityCMS["Data & Content Layer (Sanity v3)"]
Studio["Sanity Studio (studio.weddinginvietnam.com)"]
Docs["Documents: author, post, service, venue, faq, testimonial, settings"]
GROQ["Type-safe GROQ Queries + sanity-typegen"]
end
Editors -->|Manage Content & Orders| Studio
Studio --> Docs
Docs -->|Live Cache / Draft Mode| GROQ
GROQ --> Router
Router --> CheckBlocks
CheckBlocks -->|Yes: Custom Page Override| PageBuilder
CheckBlocks -->|No: Default Luxury View| BespokeViews
BespokeViews --> SharedSystems
PageBuilder --> SharedSystems
SharedSystems --> Couples
SharedSystems --> B2B
To ensure 100% Luxury Editorial visual fidelity while retaining CMS autonomy for marketing campaigns, the platform employs a Hybrid Dual-Rendering Pattern:
| Mode | Trigger | Target Component | Purpose |
|---|---|---|---|
| Default Mode (Bespoke Editorial View) | !page?.blocks \|\| page.blocks.length === 0 |
components/templates/*-view.tsx |
Handcrafted, high-conversion luxury pages (/, /about, /services, /contact, /partnership, /blog). Receives structured, typed data from Sanity documents. |
| Override Mode (Page Builder Blocks) | page?.blocks && page.blocks.length > 0 |
components/blocks/index.tsx |
Marketing and editorial team can build custom landing pages or completely override core page sections via Sanity Studio without modifying code. |
| Catch-all Fallback | Any slug without a dedicated route file | app/(main)/[...slug]/page.tsx |
Dynamically renders arbitrary new CMS pages created by editors. |
frontend/app/(main)/
├── page.tsx → page.blocks ? <Blocks /> : <HomepageView />
├── about/page.tsx → page.blocks ? <Blocks /> : <AboutView />
├── services/page.tsx → page.blocks ? <Blocks /> : <ServicesView />
├── services/[slug]/page.tsx → Dynamic route for individual service: <ServiceDetailView />
├── contact/page.tsx → page.blocks ? <Blocks /> : <ContactView />
├── partnership/page.tsx → page.blocks ? <Blocks /> : <PartnershipView />
├── blog/page.tsx → Editorial index: <BlogIndexView />
├── blog/[slug]/page.tsx → Individual article: <BlogArticleView />
└── [...slug]/page.tsx → Universal CMS fallback: <Blocks />
All documents in Sanity Studio are strongly typed and generate TypeScript definitions into frontend/sanity.types.ts via ./node_modules/.bin/sanity typegen generate.
classDiagram
class Settings {
siteName: string
tagline: string
contactEmail: string
whatsapp: string
socialLinks: array
logo: object
copyright: string
}
class Author {
name: string
slug: slug
role: string
bio: text
image: image
socialLinks: array
}
class Category {
title: string
slug: slug
description: text
}
class Venue {
name: string
region: string
logo: image
logoUrl: string
url: url
width: number
height: number
orderRank: string
}
class Service {
title: string
slug: slug
targetAudience: string
tagline: string
shortDescription: text
pricing: string
features: array
packages: array
processSteps: array
faqs: array[reference:faq]
coverImage: image
ctaText: string
ctaUrl: string
}
class Post {
title: string
slug: slug
excerpt: text
image: image
body: block-content
author: reference[Author]
categories: array[reference:Category]
publishedAt: datetime
}
class FAQ {
title: string
body: block-content
orderRank: string
}
class Testimonial {
name: string
title: string
rating: number
image: image
body: block-content
orderRank: string
}
Post --> Author : written by
Post --> Category : classified under
Service --> FAQ : includes faqs
To maintain strict DRY (Don't Repeat Yourself) compliance and avoid scattered hardcoded values:
- frontend/lib/constants/site.ts:
- SITE_DOMAINS: Dual-domain pairing (weddinginvietnam.com and vietnamweddingguide.com).
- FOUNDER_CREDENTIALS: Founder Nhi Võ credentials ("9+ Years Hospitality", InterContinental background, ex-Commercial Head at Je t'aime Art, portfolio https://nhivo.io.vn).
- CONTACT_INFO: Official contact email (info@weddinginvietnam.com) and on-site operational regions.
- frontend/lib/constants/partnership.ts:
- PARTNERSHIP_TIERS: Pricing ($222/mo Standard, $444/mo Pro), initial 6-month fit review commitments ($1,332 / $2,664 USD), and deliverable checklists.
- UHNW_ADVISORY_CONFIG: Hourly advisory rate ($111/hour), founder advisory scope, and deliverables.
FounderBioSection (frontend/components/sections/founder-bio-section.tsx):variant="editorial": Homepage Section 6 layout with credentials and signature.variant="about": Comprehensive platform vision about-view bio.variant="card": Service detail compact fiduciary guarantee.variant="compact": Blog article author footer card.LuxuryCTABanner (frontend/components/sections/luxury-cta-banner.tsx):PartnershipView Sub-modules (frontend/components/partnership/):Hero, StrategicEdge, MarketContext, Monetization, Tiers, Governance, Lifecycle, and InquiryForm.When updating code, schemas, or templates, the following constraints are mandatory:
✨ Private Advisory, 💍 Wedding GuidePrivate Advisory (uppercase, tracking [0.25em], bordered by luxury gold lines <span className="w-8 h-px bg-brand-gold/60" />).weddinginvietnam.com) and secondary (vietnamweddingguide.com) domains in brand/partnership contexts.studio.weddinginvietnam.com).Venue Name: Official resort/hotel name.Region: "Da Nang", "Phu Quoc", "Saigon", or "Nha Trang".Logo Image: Upload transparent PNG/WebP logo.Website URL: Direct link to property's destination wedding page.Title, Slug, Target Audience (couples vs professionals), Tagline, Pricing, and Included Deliverables.Packages, Process Steps, and link relevant FAQs./services grid and /services/[slug] detail page.Title, Slug, Excerpt, Cover Image, Author (select Nhi Võ), Categories, and Published Date./blog and be indexed for Google & AI search engines.