plans
2026-05-08
2026 05 08 Landing Page Restructuring

Landing Page Restructuring Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Fix broken/missing pages, resolve duplicate content, and create clear page differentiation for each audience.

Architecture: This is a content and routing fix, not an architecture change. We'll work within the existing apps/frontend/app/[locale]/(landing)/ structure.

Tech Stack: Next.js App Router, React, Tailwind CSS


Design Consistency Rule

All forms on landing pages are sections with:

  1. Background image - page-specific image that sets context
  2. Overlay - dark gradient overlay for readability
  3. Form card - consistent glassmorphic design inside
// Form section structure
<section className="relative py-20">
  {/* Background image */}
  <div className="absolute inset-0">
    <Image
      src="/images/page-specific.jpg"
      alt=""
      fill
      className="object-cover"
    />
    {/* Dark gradient overlay */}
    <div className="absolute inset-0 bg-gradient-to-b from-background/60 to-background/90" />
  </div>
 
  {/* Content with form */}
  <div className="relative z-10 container mx-auto">
    {/* Consistent form card */}
    <div className="max-w-[700px] mx-auto bg-[var(--color-surface)]/40 backdrop-blur-xl border border-[var(--color-border)] rounded-2xl p-8">
      <Heading level="h2">Form Title</Heading>
      <FormComponent />
    </div>
  </div>
</section>

This applies to: PrivateEventsForm, ArtistProposalForm, WorkshopProposalForm, VenueRentalForm, ContactForm.


Background

Content audit revealed:

  • experiences/private-events/page.tsx is MISSING (data exists, route doesn't)
  • page.tsx exports OurEveningPage — it's a duplicate of /experiences/our-evening
  • "A Unique Evening Experience" gallery title appears on B2B pages (misleading)
  • Multiple pages overlap in audience and content

Task 1: Create Missing private-events/page.tsx

Files:

  • Create: apps/frontend/app/[locale]/(landing)/experiences/private-events/page.tsx

  • Reference: apps/frontend/lib/data/private-events.ts (data already exists)

  • Reference: apps/frontend/components/features/sections/private-events-form.tsx (form exists)

  • Step 1: Create the page file

Create the file with this content:

// ipsoc checked: 2026-05-08
// SoC: Static presentation page - imports data from lib/data/private-events.ts
 
/**
 * Private Events — migrated from WordPress private-event.php
 * Source: apps/frontend/raw/private-event.php
 * Source lines: 141-476 (main content sections)
 * Figma reference: node 1433:11459
 */
 
import type { Metadata } from "next";
import Image from "next/image";
import { PageHeroLayout } from "~/components/ui/page-hero-layout";
import { SectionDivider } from "~/components/ui/section-divider";
import { Heading } from "~/components/ui/typography";
import { CtaSectionLayout } from "~/components/ui/cta-section-layout";
import { PracticalInfoSection } from "~/components/features/sections/practical-info-section";
import { PrivateEventsForm } from "~/components/features/forms/private-events-form";
import { GalleryScroll } from "~/components/features/sections/gallery-scroll";
import { PartnerLogos } from "~/components/features/sections/partner-logos";
import { VisitCTASection } from "~/components/features/sections/visit-cta-section";
import { cn } from "~/lib/utils";
import {
  eventPackages,
  venueAmenities,
  eventExperiences,
  galleryImagesUp,
  galleryImagesDown,
  partners,
  recommendedBy,
  privateEventsPage,
} from "~/lib/data/private-events";
import {
  MapPin,
  Clock,
  Users,
  Check,
  Building2,
  Plane,
  Building,
} from "lucide-react";
 
export const metadata: Metadata = {
  title: privateEventsPage.metadata.title,
  description: privateEventsPage.metadata.description,
};
 
export default function PrivateEventsPage() {
  return (
    <main className="pt-[var(--header-height)]">
      {/* Hero Section */}
      <PageHeroLayout
        title={privateEventsPage.hero.title}
        subtitle={privateEventsPage.hero.subtitle}
        imageSrc="/images/private-event-hero-banner.jpg"
        imageAlt={privateEventsPage.hero.title}
        ctaText={privateEventsPage.hero.ctaText}
        ctaHref={privateEventsPage.hero.ctaHref}
        badge={
          <div className="flex items-center justify-center md:justify-start gap-6 flex-wrap">
            <div className="flex items-center gap-2 font-sans text-sm text-muted">
              <MapPin />
              <span>{privateEventsPage.hero.location}</span>
            </div>
            <div className="flex items-center gap-2 font-sans text-sm text-muted">
              <Clock />
              <span>{privateEventsPage.hero.duration}</span>
            </div>
            <div className="flex items-center gap-2 font-sans text-sm text-muted">
              <Users />
              <span>{privateEventsPage.hero.seats}</span>
            </div>
          </div>
        }
      />
 
      <SectionDivider />
 
      {/* Recommended by Hotels & Travel Professionals */}
      <section id="v5-recommended" className="bg-surface py-20 px-8">
        <div className="max-w-[1250px] mx-auto">
          <Heading level="h2" align="center" className="mb-10">
            Recommended by Hotels &amp; Travel Professionals
          </Heading>
          <div className="flex gap-10 justify-center flex-wrap">
            {recommendedBy.map((item, index) => {
              const iconMap = {
                hotel: Building2,
                tour: Plane,
                corporate: Building,
              };
              const Icon = iconMap[item.iconKey as keyof typeof iconMap];
              return (
                <div
                  key={index}
                  className={cn(
                    "flex flex-col items-center text-center transition-all duration-700 ease-out",
                    index > 0 && "delay-[" + index * 100 + "ms]",
                  )}
                >
                  <div className="w-12 h-12 text-gold">
                    <Icon />
                  </div>
                  <div className="flex flex-col gap-2">
                    <Heading
                      level="h3"
                      color="foreground"
                      className="font-serif"
                    >
                      {item.title}
                    </Heading>
                    <p className="font-sans text-base text-muted">
                      {item.description}
                    </p>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      </section>
 
      <SectionDivider />
 
      {/* Partner logos section */}
      <PartnerLogos partners={partners} />
 
      <SectionDivider />
 
      {/* Event Experience */}
      <section id="pe-event-xp" className="py-20 px-4">
        <div className="container mx-auto">
          <Heading level="h2" className="mb-10">
            Event Experience
          </Heading>
          <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
            {eventExperiences.map((exp, index) => (
              <article
                key={index}
                className="bg-surface border border-[var(--color-border)] rounded-2xl overflow-hidden"
              >
                <div className="relative aspect-[16/10] overflow-hidden">
                  <Image
                    src={exp.image}
                    alt={exp.title}
                    fill
                    className="object-cover"
                  />
                </div>
                <div className="p-6">
                  <Heading level="h3" color="gold" className="font-serif mb-3">
                    {exp.title}
                  </Heading>
                  <p className="font-sans text-sm text-muted-foreground leading-relaxed">
                    {exp.description}
                  </p>
                </div>
              </article>
            ))}
          </div>
        </div>
      </section>
 
      <SectionDivider />
 
      {/* Venue Section */}
      <section id="pe-venue" className="py-20 px-4 bg-surface">
        <div className="container mx-auto">
          <div className="grid md:grid-cols-2 gap-12 items-center">
            {/* Text Content */}
            <div>
              <Heading level="h2" className="mb-6">
                What the Venue Offers
              </Heading>
              <div className="grid grid-cols-[repeat(auto-fit,minmax(200px,1fr))] gap-3 mb-6">
                {venueAmenities.map((amenity, index) => (
                  <div
                    key={index}
                    className="flex items-center gap-2 font-sans text-sm text-foreground"
                  >
                    <Check />
                    <span>{amenity}</span>
                  </div>
                ))}
              </div>
              <p className="font-sans text-base font-semibold text-gold">
                Capacity: up to 32 guests
              </p>
            </div>
            {/* Framed Image */}
            <div className="relative aspect-[4/3] rounded-2xl overflow-hidden border border-[var(--color-border)]">
              <Image
                src="/images/private-event-1.jpg"
                alt="House of Legends venue"
                fill
                className="object-cover"
              />
            </div>
          </div>
        </div>
      </section>
 
      <SectionDivider />
 
      {/* Event Packages */}
      <section id="pe-packages" className="py-20 px-4">
        <div className="max-w-[1200px] mx-auto">
          <Heading level="h2" align="center" className="mb-10">
            Event Packages
          </Heading>
          <div className="grid grid-cols-[repeat(auto-fit,minmax(280px,1fr))] gap-6 max-w-[900px] mx-auto">
            {eventPackages.map((pkg, index) => (
              <div
                key={index}
                className={cn(
                  "bg-surface rounded-xl p-6 border border-border",
                  pkg.featured && "border-[var(--color-gold)] border-2",
                )}
              >
                <Heading
                  level="h3"
                  color="foreground"
                  className="font-serif mb-4"
                >
                  {pkg.title}
                </Heading>
                <ul className="list-none p-0 m-0 space-y-2">
                  {pkg.features.map((feature, fIndex) => (
                    <li
                      key={fIndex}
                      className="flex items-start gap-2 font-sans text-sm text-muted"
                    >
                      <Check />
                      <span>{feature}</span>
                    </li>
                  ))}
                </ul>
              </div>
            ))}
          </div>
        </div>
      </section>
 
      <SectionDivider />
 
      {/* Gallery Scroll Section */}
      <GalleryScroll
        imagesUp={galleryImagesUp}
        imagesDown={galleryImagesDown}
      />
 
      <SectionDivider />
 
      {/* Practical Info */}
      <PracticalInfoSection
        image={privateEventsPage.practicalInfo.image}
        ctaText={privateEventsPage.practicalInfo.ctaText}
        ctaHref={privateEventsPage.practicalInfo.ctaHref}
      />
 
      <SectionDivider />
 
      {/* CTA Section */}
      <CtaSectionLayout
        title="Don't Miss the Show"
        description="Experience the magic of House of Legends. Book your private event today."
        imageSrc="/images/landing-page/artist-carousel-1.jpg"
        imageAlt="House of Legends performance"
        ctaText="Enquire Now"
        ctaHref="#pe-inquiry"
      />
 
      <SectionDivider />
 
      {/* Event Inquiry Form */}
      <section id="pe-inquiry" className="py-20 px-4">
        <div className="container mx-auto">
          <div className="max-w-[700px] mx-auto bg-[var(--color-surface)]/40 backdrop-blur-xl border border-[var(--color-border)] rounded-2xl p-8">
            <div className="text-center mb-8">
              <Heading level="h2" className="mb-2">
                Event Inquiry
              </Heading>
              <p className="font-sans text-sm text-muted">
                Tell us about your event and our team will contact you with a
                tailored proposal.
              </p>
            </div>
            <PrivateEventsForm />
          </div>
        </div>
      </section>
    </main>
  );
}
  • Step 2: Verify the route works

Run: pnpm dev and navigate to /en/experiences/private-events Expected: Page renders with all sections and SectionDivider components between sections

  • Step 3: Commit
git add apps/frontend/app/\[locale\]/\(landing\)/experiences/private-events/page.tsx
git commit -m "feat(landing): create missing private-events page"

Task 2: Resolve Homepage vs Our Evening Confusion

Files:

  • Modify: apps/frontend/app/[locale]/(landing)/page.tsx (make it a proper homepage)
  • Reference: apps/frontend/components/home/hero-section.tsx
  • Reference: apps/frontend/components/home/journey-section.tsx

Context: page.tsx currently exports OurEveningPage which is identical to /experiences/our-evening. We need to make page.tsx a proper homepage with overview content, and /experiences/our-evening should be a differentiated "Our Evening" experience page.

  • Step 1: Read current homepage structure

Read apps/frontend/app/[locale]/(landing)/page.tsx to understand current composition.

  • Step 2: Create a proper HomepageClient component

Create: apps/frontend/components/home/homepage-client.tsx

// ipsoc checked: 2026-05-08
// SoC: Page composition - manages curtain and calendar modal state
 
"use client";
 
import { CurtainOverlay } from "~/components/layout/curtain-overlay";
import { CalendarModalProvider } from "~/lib/hooks/use-calendar-modal";
import { HeroSection } from "~/components/home/hero-section";
import { UpcomingShowsSection } from "~/components/home/upcoming-shows-section";
import { JourneySection } from "~/components/home/journey-section";
import { GallerySection } from "~/components/home/gallery-section";
import { ReviewsSection } from "~/components/home/reviews-section";
import { PartnersSection } from "~/components/home/partners-section";
import { ContactFormSection } from "~/components/home/contact-form-section";
import { CtaSection } from "~/components/home/cta-section";
import { CalendarModal } from "~/components/home/calendar-modal";
import { SectionDivider } from "~/components/ui/section-divider";
 
export function HomepageClient() {
  return (
    <CalendarModalProvider>
      <CurtainOverlay />
      <HeroSection />
      <SectionDivider />
      <UpcomingShowsSection />
      <SectionDivider />
      <JourneySection />
      <SectionDivider />
      <GallerySection />
      <SectionDivider />
      <ReviewsSection />
      <SectionDivider />
      <PartnersSection />
      <SectionDivider />
      <ContactFormSection />
      <SectionDivider />
      <CtaSection />
      <CalendarModal />
    </CalendarModalProvider>
  );
}
  • Step 3: Update page.tsx to export HomepageClient

Modify apps/frontend/app/[locale]/(landing)/page.tsx to import and export HomepageClient instead of the current content:

// ipsoc checked: 2026-05-08
// SoC: Homepage - delegates to client component
 
import { HomepageClient } from "~/components/home/homepage-client";
 
export default function HomePage() {
  return <HomepageClient />;
}
  • Step 4: Verify homepage renders correctly

Run: pnpm dev and navigate to /en/ Expected: Homepage with curtain overlay, all sections separated by SectionDivider

  • Step 5: Commit
git add apps/frontend/app/\[locale\]/\(landing\)/page.tsx apps/frontend/components/home/homepage-client.tsx
git commit -m "refactor(landing): make page.tsx a proper homepage"

Task 3: Differentiate Our Evening Page

Files:

  • Modify: apps/frontend/app/[locale]/(landing)/experiences/our-evening/page.tsx
  • Goal: Make this page explain WHAT "Our Evening" is (the evening experience concept), not duplicate homepage

Context: After homepage becomes homepage, /experiences/our-evening should explain the evening experience concept clearly. It should NOT repeat content from homepage.

  • Step 1: Read current our-evening page

Read apps/frontend/app/[locale]/(landing)/experiences/our-evening/page.tsx

  • Step 2: Rewrite the page with focused content

Update the page to be a clean "Our Evening" concept page:

// ipsoc checked: 2026-05-08
// SoC: Static presentation page
 
/**
 * Our Evening — Concept page explaining the evening experience
 * This page should clarify what "Our Evening" means and what to expect
 */
 
import type { Metadata } from "next";
import { PageHero } from "~/components/features/sections/page-hero";
import { SectionDivider } from "~/components/ui/section-divider";
import { Heading } from "~/components/ui/typography";
import { timelineItems, timelineBoxes } from "~/lib/data/our-experience";
import { Clock, Mic, Sparkles } from "lucide-react";
import { VisitCTASection } from "~/components/features/sections/visit-cta-section";
 
const EXPERIENCE_ICONS = [Clock, Mic, Sparkles] as const;
 
export const metadata: Metadata = {
  title: "Our Evening | House of Legends",
  description:
    "Discover what makes an evening at House of Legends — immersive theatre, cultural storytelling, and unforgettable experiences.",
};
 
export default function OurEveningPage() {
  return (
    <main className="pt-[var(--header-height)]">
      <PageHero
        title="Where the theater meets Vietnam culture"
        subtitle="An evening journey through immersive theatre, cultural storytelling, and unforgettable experiences"
        backgroundImage="/images/landing-page/artist-carousel-1.jpg"
      />
 
      {/* Timeline Details Section */}
      <section className="py-20 px-4">
        <div className="container mx-auto">
          <Heading level="h2" className="mb-8 text-center">
            An Evening at House of Legends
          </Heading>
          <div className="max-w-3xl mx-auto">
            {timelineItems.map((item, index) => (
              <article key={index} className="flex gap-6 mb-8 last:mb-0">
                <div className="shrink-0">
                  <div className="w-12 h-12 rounded-full bg-surface flex items-center justify-center">
                    <Clock className="w-5 h-5 text-gold" />
                  </div>
                </div>
                <div className="flex-1">
                  <span className="text-gold font-semibold">{item.time}</span>
                  <Heading level="h3" color="foreground" className="mb-2">
                    {item.title}
                  </Heading>
                  <p className="text-muted-foreground">{item.description}</p>
                </div>
              </article>
            ))}
          </div>
        </div>
      </section>
 
      <SectionDivider />
 
      {/* Three Experiences */}
      <section className="py-20 px-4 bg-surface">
        <div className="container mx-auto">
          <Heading level="h2" className="mb-12 text-center">
            Three Ways to Experience House of Legends
          </Heading>
          <div className="grid md:grid-cols-3 gap-8 max-w-5xl mx-auto">
            {timelineBoxes.map((box, index) => {
              const IconComponent = EXPERIENCE_ICONS[index] ?? Clock;
              return (
                <article key={index} className="text-center">
                  <div className="w-16 h-16 mx-auto mb-4 rounded-full bg-primary/10 flex items-center justify-center">
                    {IconComponent && (
                      <IconComponent className="w-8 h-8 text-primary" />
                    )}
                  </div>
                  <Heading level="h3" color="foreground" className="mb-3">
                    {box.title}
                  </Heading>
                  <p className="text-muted-foreground text-sm">
                    {box.description}
                  </p>
                </article>
              );
            })}
          </div>
        </div>
      </section>
 
      <SectionDivider />
 
      {/* Social Proof */}
      <section className="py-20 px-4">
        <div className="container mx-auto max-w-3xl text-center">
          <Heading level="h3" className="mb-6">
            What Guests Say
          </Heading>
          <p className="text-lg text-muted-foreground leading-relaxed mb-8">
            House of Legends welcomes visitors from around the world who come to
            experience our intimate theatre performances, Vietnamese fusion
            cuisine and signature cocktails.
          </p>
          <a
            href="https://www.google.com/maps/search/?api=1&query=The+House+of+Legends+Da+Nang"
            target="_blank"
            rel="noopener noreferrer"
            className="inline-flex items-center gap-2 text-gold hover:underline"
          >
            Read All Reviews on Google
            <svg
              width="24"
              height="24"
              viewBox="0 0 24 24"
              fill="none"
              aria-hidden="true"
            >
              <path
                d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"
                fill="currentColor"
              />
            </svg>
          </a>
        </div>
      </section>
 
      <SectionDivider />
 
      {/* CTA */}
      <VisitCTASection />
    </main>
  );
}
  • Step 3: Verify our-evening page renders correctly

Run: pnpm dev and navigate to /en/experiences/our-evening Expected: Clean concept page with timeline, three experiences, social proof, and CTA

  • Step 4: Commit
git add apps/frontend/app/\[locale\]/\(landing\)/experiences/our-evening/page.tsx
git commit -m "refactor(landing): differentiate our-evening as concept page"

Task 4: Fix Gallery Titles on B2B Pages

Files:

  • Modify: apps/frontend/app/[locale]/(landing)/experiences/artist-performances/page.tsx
  • Modify: apps/frontend/app/[locale]/(landing)/experiences/creative-workshop/page.tsx

Context: Both pages have a gallery section with title "A Unique Evening Experience" which is wrong context for B2B pages.

  • Step 1: Fix artist-performances gallery title

Modify the gallery section title in artist-performances/page.tsx:

Change:

<SectionTitle title="A Unique Evening Experience" />

To:

<SectionTitle title="The Venue" />
  • Step 2: Fix creative-workshop gallery title

Modify the gallery section title in creative-workshop/page.tsx:

Change:

<SectionTitle title="A Unique Evening Experience" />

To:

<SectionTitle title="Our Space" />
  • Step 3: Verify changes

Run: pnpm dev and check both pages have correct gallery titles

  • Step 4: Commit
git add apps/frontend/app/\[locale\]/\(landing\)/experiences/artist-performances/page.tsx apps/frontend/app/\[locale\]/\(landing\)/experiences/creative-workshop/page.tsx
git commit -m "fix(landing): correct gallery titles on B2B pages"

Task 5: Update Navigation Links

Files:

  • Modify: apps/frontend/components/layout/header.tsx (or wherever nav links are defined)

  • Goal: Verify all nav links point to correct pages

  • Step 1: Find and read navigation component

grep -rn "private-event" apps/frontend/components --include="*.tsx" | head -20
  • Step 2: Fix any broken links

Ensure links point to correct routes:

  • Private events → /experiences/private-events

  • Workshops → /experiences/creative-workshop

  • Artist performances → /experiences/artist-performances

  • Step 3: Commit

git add <updated-nav-files>
git commit -m "fix(nav): correct landing page links"

Task 6: Ensure Form Sections Have Consistent Structure with Page-Specific Backgrounds

Files:

  • Modify: apps/frontend/app/[locale]/(landing)/experiences/private-events/page.tsx
  • Modify: apps/frontend/app/[locale]/(landing)/experiences/artist-performances/page.tsx
  • Modify: apps/frontend/app/[locale]/(landing)/experiences/creative-workshop/page.tsx
  • Modify: apps/frontend/app/[locale]/(landing)/venue-rental/page.tsx
  • Modify: apps/frontend/components/home/contact-form-section.tsx

Design Pattern:

  • Each form is a <section> with a page-specific background image
  • Dark gradient overlay for readability
  • Consistent glassmorphic form card inside

Per-page background images:

PageBackground Image
Private Events/images/landing-page/artist-carousel-1.jpg
Artist Performances/images/landing-page/practical-info-stage.jpg
Creative Workshop/images/landing-page/workshop-hero.jpg
Venue Rental/images/landing-page/venue-rental-bg.jpg
Contact (Homepage)/images/landing-page/artist-carousel-1.jpg
  • Step 1: Create shared FormSection component

Create: apps/frontend/components/ui/form-section.tsx

// ipsoc checked: 2026-05-08
// SoC: Reusable form section with background image and consistent form card
 
"use client";
 
import Image from "next/image";
import { Heading } from "~/components/ui/typography";
import { cn } from "~/lib/utils";
import { ReactNode } from "react";
 
interface FormSectionProps {
  title: string;
  subtitle?: string;
  backgroundImage: string;
  children: ReactNode;
  className?: string;
}
 
export function FormSection({
  title,
  subtitle,
  backgroundImage,
  children,
  className,
}: FormSectionProps) {
  return (
    <section className={cn("relative py-20", className)}>
      {/* Background image */}
      <div className="absolute inset-0">
        <Image
          src={backgroundImage}
          alt=""
          fill
          className="object-cover"
          aria-hidden="true"
        />
        {/* Dark gradient overlay */}
        <div className="absolute inset-0 bg-gradient-to-b from-background/60 to-background/90" />
      </div>
 
      {/* Content */}
      <div className="relative z-10 container mx-auto">
        <div className="max-w-[700px] mx-auto bg-[var(--color-surface)]/40 backdrop-blur-xl border border-[var(--color-border)] rounded-2xl p-8">
          <div className="text-center mb-8">
            <Heading level="h2" className="mb-2">
              {title}
            </Heading>
            {subtitle && <p className="text-muted text-sm">{subtitle}</p>}
          </div>
          {children}
        </div>
      </div>
    </section>
  );
}
  • Step 2: Update private-events page to use FormSection

Modify the inquiry form section in experiences/private-events/page.tsx:

Change the form section from:

<section id="pe-inquiry" className="py-20 px-4">
  <div className="container mx-auto">
    <div className="max-w-[700px] mx-auto bg-[var(--color-surface)]/40 backdrop-blur-xl border border-[var(--color-border)] rounded-2xl p-8">
      ...
    </div>
  </div>
</section>

To:

<FormSection
  title="Event Inquiry"
  subtitle="Tell us about your event and our team will contact you with a tailored proposal."
  backgroundImage="/images/landing-page/artist-carousel-1.jpg"
>
  <PrivateEventsForm />
</FormSection>
  • Step 3: Update artist-performances page

Change the form section to use FormSection with background "/images/landing-page/practical-info-stage.jpg".

  • Step 4: Update creative-workshop page

Change the form section to use FormSection with background "/images/workshop-hero-banner.jpg".

  • Step 5: Update venue-rental page

Change the form section to use FormSection with background "/images/landing-page/artist-carousel-1.jpg".

  • Step 6: Update contact-form-section.tsx

Modify ContactFormSection to use the same pattern with background image.

  • Step 7: Verify all forms render correctly

Run: pnpm dev and check each page with a form. All should have:

  • Page-specific background image

  • Dark overlay

  • Consistent glassmorphic form card

  • Step 8: Commit

git add apps/frontend/components/ui/form-section.tsx
git add apps/frontend/app/\[locale\]/\(landing\)/experiences/private-events/page.tsx
git add apps/frontend/app/\[locale\]/\(landing\)/experiences/artist-performances/page.tsx
git add apps/frontend/app/\[locale\]/\(landing\)/experiences/creative-workshop/page.tsx
git add apps/frontend/app/\[locale\]/\(landing\)/venue-rental/page.tsx
git add apps/frontend/components/home/contact-form-section.tsx
git commit -m "style(forms): consistent form sections with page-specific backgrounds"

Verification Checklist

After all tasks complete, verify:

  • /en/ renders homepage with curtain overlay and all sections
  • /en/experiences/our-evening renders concept page (not duplicate homepage)
  • /en/experiences/private-events renders (was missing, now created)
  • /en/experiences/artist-performances gallery title says "The Venue"
  • /en/experiences/creative-workshop gallery title says "Our Space"
  • All navigation links work correctly