Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion client/src/__tests__/HomePage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,36 @@ describe('Home Page', () => {
it('contains RSVP button', () => {
render(<HomePage />)

expect(screen.getByRole('link', { name: /rsvp now/i })).toBeInTheDocument()
expect(screen.getByRole('link', { name: /RSVP for Incia and Arvin's wedding/i })).toBeInTheDocument()
})

it('has proper accessibility features', () => {
render(<HomePage />)

// Check for skip link
expect(screen.getByRole('link', { name: /Skip to main content/i })).toBeInTheDocument()

// Check for main landmark
expect(screen.getByRole('main')).toBeInTheDocument()

// Check for proper heading hierarchy
expect(screen.getByRole('heading', { level: 1 })).toBeInTheDocument() // I & A logo
expect(screen.getByRole('heading', { level: 2, name: /Incia & Arvin/i })).toBeInTheDocument()
})

it('has descriptive alt texts for images', () => {
render(<HomePage />)

// Check for more descriptive alt texts in story section
expect(screen.getByAltText(/Incia and Arvin as students at American International School/i)).toBeInTheDocument()
expect(screen.getByAltText(/Arvin proposing to Incia in the scenic countryside of Tuscany/i)).toBeInTheDocument()
})

it('includes structured timing information', () => {
render(<HomePage />)

// Check for enhanced timing information in the Save the Date section
expect(screen.getByText(/6:00 PM Bangladesh Standard Time/i)).toBeInTheDocument()
expect(screen.getAllByText(/πŸ“ Dhaka, Bangladesh/i)).toHaveLength(2) // One in hero, one in footer
})
})
51 changes: 51 additions & 0 deletions client/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,57 @@ html {
font-family: var(--font-serif);
}

/* Accessibility improvements */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}

.focus\:not-sr-only:focus {
position: static;
width: auto;
height: auto;
padding: 0.5rem 1rem;
margin: 0;
overflow: visible;
clip: auto;
white-space: normal;
}

/* Enhanced focus indicators */
.focus\:ring-2:focus {
box-shadow: 0 0 0 2px var(--color-primary);
}

.focus\:ring-offset-2:focus {
box-shadow: 0 0 0 2px var(--background), 0 0 0 4px var(--color-primary);
}

/* Improved touch targets for mobile - WCAG 2.1 compliance */
@media (max-width: 640px) {
button, a, [role="button"], input, select, textarea {
min-height: 44px;
min-width: 44px;
}
}

/* Reduce motion for users who prefer it - Accessibility best practice */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}

/* Utilities */
.touch-pan-zoom {
touch-action: pan-x pan-y pinch-zoom;
Expand Down
115 changes: 107 additions & 8 deletions client/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,36 @@ const playfair = Playfair_Display({
});

export const metadata: Metadata = {
title: "Incia & Arvin's Wedding",
description: "Join us in celebrating the love story of Incia & Arvin - from childhood friends to forever partners. Dhaka, Bangladesh with celebrations continuing in Phu Quoc, Vietnam.",
keywords: ["wedding", "Incia", "Arvin", "Dhaka", "Vietnam", "celebration"],
authors: [{ name: "CodeStorm Hub" }],
creator: "CodeStorm Hub",
title: "Incia & Arvin's Wedding - December 16, 2025",
description: "Join us in celebrating the love story of Incia & Arvin - from childhood friends at AISD to forever partners. Wedding ceremony in Dhaka, Bangladesh on December 16, 2025, with celebrations continuing in Phu Quoc, Vietnam.",
keywords: ["wedding", "Incia", "Arvin", "Dhaka", "Vietnam", "celebration", "AISD", "love story", "December 2025"],
authors: [{ name: "Incia & Arvin" }],
creator: "Incia & Arvin",
openGraph: {
title: "Incia & Arvin's Wedding",
description: "Join us in celebrating the love story of Incia & Arvin",
title: "Incia & Arvin's Wedding - December 16, 2025",
description: "Join us in celebrating the love story of Incia & Arvin - from childhood friends to forever partners",
type: "website",
locale: "en_US",
siteName: "Incia & Arvin's Wedding",
images: [
{
url: "/images/og-wedding-image.jpg",
width: 1200,
height: 630,
alt: "Incia & Arvin's Wedding",
},
],
},
twitter: {
card: "summary_large_image",
title: "Incia & Arvin's Wedding",
title: "Incia & Arvin's Wedding - December 16, 2025",
description: "Join us in celebrating the love story of Incia & Arvin",
images: ["/images/og-wedding-image.jpg"],
},
robots: "index, follow",
alternates: {
canonical: "https://arvinwedsincia.com",
},
};

// Separate viewport export as required by Next.js 13+
Expand All @@ -52,8 +64,95 @@ export default function RootLayout({
}: Readonly<{
children: React.ReactNode;
}>) {
const structuredData = {
"@context": "https://schema.org",
"@type": "Event",
"name": "Incia & Arvin's Wedding Ceremony",
"description": "Join us in celebrating the love story of Incia & Arvin - from childhood friends at American International School of Dhaka to forever partners.",
"startDate": "2025-12-16T18:00:00+06:00",
"endDate": "2025-12-16T23:00:00+06:00",
"eventStatus": "https://schema.org/EventScheduled",
"eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode",
"location": {
"@type": "Place",
"name": "Wedding Venue Dhaka",
"address": {
"@type": "PostalAddress",
"addressLocality": "Dhaka",
"addressCountry": "Bangladesh",
"addressRegion": "Dhaka Division"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": "23.8103",
"longitude": "90.4125"
}
},
"organizer": [
{
"@type": "Person",
"name": "Incia",
"givenName": "Incia"
},
{
"@type": "Person",
"name": "Arvin",
"givenName": "Arvin"
}
],
"performer": {
"@type": "Person",
"name": "Incia & Arvin"
},
"offers": {
"@type": "Offer",
"availability": "https://schema.org/InviteOnly",
"price": "0",
"priceCurrency": "USD"
},
"image": [
"https://arvinwedsincia.com/images/og-wedding-image.jpg"
],
"url": "https://arvinwedsincia.com",
"subEvent": [
{
"@type": "Event",
"name": "After-party in Phu Quoc, Vietnam",
"location": {
"@type": "Place",
"name": "Phu Quoc, Vietnam",
"address": {
"@type": "PostalAddress",
"addressLocality": "Phu Quoc",
"addressCountry": "Vietnam"
}
}
}
]
};

return (
<html lang="en" className={`${inter.variable} ${playfair.variable} scroll-smooth`}>
<head>
{/* Enhanced structured data for wedding event */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }}
/>

{/* Additional meta tags for better SEO and accessibility */}
<meta name="theme-color" content="#d4a574" />
<meta name="color-scheme" content="light" />
<meta name="format-detection" content="telephone=no" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />

{/* Favicon and app icons */}
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/site.webmanifest" />
</head>
Comment on lines +136 to +155
Copy link

Copilot AI Aug 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Manually adding a tag in layout.tsx is unnecessary and potentially problematic with Next.js App Router. The metadata export already handles head elements automatically. This could cause duplicate head tags or override issues.

Suggested change
<head>
{/* Enhanced structured data for wedding event */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }}
/>
{/* Additional meta tags for better SEO and accessibility */}
<meta name="theme-color" content="#d4a574" />
<meta name="color-scheme" content="light" />
<meta name="format-detection" content="telephone=no" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
{/* Favicon and app icons */}
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/site.webmanifest" />
</head>

Copilot uses AI. Check for mistakes.
<body className="font-sans antialiased bg-cream-50 text-gray-800">
<Providers>
<ErrorBoundary>
Expand Down
63 changes: 41 additions & 22 deletions client/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,77 +9,94 @@ import { ArrowRightIcon, HeartIcon, CalendarDaysIcon, PhotoIcon, MapPinIcon, Env
export default function HomePage() {
return (
<div className="min-h-screen overflow-x-hidden">
{/* Skip Links for Accessibility - Best Practice for screen readers */}
<a
href="#main-content"
className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 bg-primary text-white px-4 py-2 rounded-md z-50 focus:z-50 transition-all duration-300"
aria-label="Skip to main content of the page"
>
Skip to main content
</a>
<Navigation />

{/* Hero Section */}
<section id="home" className="min-h-screen flex items-center justify-center gradient-hero pt-16">
<main id="main-content">
<section
id="home"
className="min-h-screen flex items-center justify-center gradient-hero pt-16"
aria-label="Wedding announcement and save the date"
>
<div className="text-center px-4 sm:px-6 lg:px-8 w-full max-w-6xl">
<div className="animate-fadeInUp">
<h2 className="pt-2 sm:pt-3 text-4xl sm:text-6xl md:text-7xl lg:text-8xl font-serif font-light text-secondary mb-4 sm:mb-6 leading-tight">
<h1 className="pt-2 sm:pt-3 text-4xl sm:text-6xl md:text-7xl lg:text-8xl font-serif font-light text-secondary mb-4 sm:mb-6 leading-tight">
Incia & Arvin
</h2>
</h1>
<div className="w-16 sm:w-20 md:w-24 h-1 bg-primary mx-auto mb-6 sm:mb-8"></div>
<p className="text-lg sm:text-xl md:text-2xl text-muted mb-6 sm:mb-8 max-w-2xl mx-auto leading-relaxed">
From childhood friends at AISD to forever partners
</p>

{/* Heart Collage Component with enhanced presentation */}
<div className="my-6 sm:my-8 relative overflow-hidden">
{/* Heart Collage Component with enhanced presentation and accessibility */}
<div className="my-6 sm:my-8 relative overflow-hidden" role="img" aria-label="Romantic collage of Incia and Arvin's memorable moments together">
{/* Subtle background glow for the collage - no scaling to prevent overflow */}
<div className="absolute inset-0 bg-gradient-radial from-primary/8 via-primary/3 to-transparent rounded-full blur-xl opacity-50"></div>
<div className="absolute inset-0 bg-gradient-radial from-primary/8 via-primary/3 to-transparent rounded-full blur-xl opacity-50" aria-hidden="true"></div>
<HeartCollage />
</div>

<p className="text-base sm:text-lg text-muted mb-8 sm:mb-12">
Join us as we celebrate our love story across continents
</p>

{/* Wedding Date */}
<div className="bg-white rounded-2xl p-6 sm:p-8 max-w-sm sm:max-w-md mx-auto mb-8 sm:mb-12 shadow-xl border border-cream-200">
{/* Wedding Date - Enhanced with better accessibility */}
<div className="bg-white rounded-2xl p-6 sm:p-8 max-w-sm sm:max-w-md mx-auto mb-8 sm:mb-12 shadow-xl border border-cream-200" role="region" aria-labelledby="wedding-date-heading">
<div className="flex items-center justify-center gap-2 mb-3">
<CalendarDaysIcon className="h-6 w-6 text-primary" />
<h3 className="text-xl sm:text-2xl font-serif font-semibold text-secondary">
<CalendarDaysIcon className="h-6 w-6 text-primary" aria-hidden="true" />
<h2 id="wedding-date-heading" className="text-xl sm:text-2xl font-serif font-semibold text-secondary">
Save the Date
</h3>
</h2>
Comment on lines +54 to +56
Copy link

Copilot AI Aug 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This heading level creates an incorrect heading hierarchy. Since the main title 'Incia & Arvin' is h1, this should be h3 as it's a subsection within the hero section, not a primary section heading.

Copilot uses AI. Check for mistakes.
</div>
<p className="text-2xl sm:text-3xl font-light text-secondary mb-3">
December 16, 2025
</p>
<p className="text-sm text-muted mb-4">Tuesday β€’ Starts at 6:00 PM</p>
{/* Countdown Timer */}
<p className="text-sm text-muted mb-4">Tuesday β€’ 6:00 PM Bangladesh Standard Time (GMT+6)</p>
{/* Countdown Timer with accessibility */}
<Countdown
targetDate="2025-12-16T00:00:00+06:00"
className="mb-4"
aria-label="Time remaining until the wedding ceremony"
/>
<p className="text-muted font-medium">
Dhaka, Bangladesh
πŸ“ Dhaka, Bangladesh
</p>
<p className="text-sm text-muted mt-1">
After-party in Phu Quoc, Vietnam
</p>
</div>

{/* CTA Buttons */}
{/* CTA Buttons - Enhanced with better accessibility and micro-animations */}
<div className="flex flex-col sm:flex-row gap-3 sm:gap-4 justify-center items-center max-w-md mx-auto mb-10 sm:mb-12">
<Link
href="/rsvp"
className="w-full sm:w-auto bg-primary hover:bg-primary-dark text-white px-6 sm:px-8 py-3 rounded-full font-medium transition-all duration-300 shadow-lg hover:shadow-xl"
className="w-full sm:w-auto bg-primary hover:bg-primary-dark text-white px-6 sm:px-8 py-3 rounded-full font-medium transition-all duration-300 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2"
aria-label="RSVP for Incia and Arvin's wedding ceremony"
>
RSVP Now
</Link>
<Link
href="#story"
className="w-full sm:w-auto border-2 border-primary text-primary hover:bg-primary hover:text-white px-6 sm:px-8 py-3 rounded-full font-medium transition-all duration-300"
className="w-full sm:w-auto border-2 border-primary text-primary hover:bg-primary hover:text-white px-6 sm:px-8 py-3 rounded-full font-medium transition-all duration-300 transform hover:-translate-y-0.5 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2"
aria-label="Read about our love story journey"
>
Our Story
</Link>
</div>
</div>
</div>
</section>
</main>

{/* Our Story Section */}
<section id="story" className="py-20 bg-white relative overflow-hidden">
{/* Our Story Section - Enhanced design with accessibility */}
<section id="story" className="py-20 bg-white relative overflow-hidden" aria-label="Our love story timeline">
{/* Decorative Background Elements */}
<div className="absolute top-0 left-0 w-full h-full" aria-hidden="true">
<div className="absolute top-20 left-10 w-32 h-32 bg-primary/5 rounded-full blur-3xl"></div>
Expand Down Expand Up @@ -133,7 +150,7 @@ export default function HomePage() {
<div className="relative h-80 lg:h-96 rounded-2xl overflow-hidden shadow-2xl mb-4">
<Image
src="/images/story/Where It All Began 1.jpeg"
alt="AISD memories - Where it all began"
alt="Incia and Arvin as students at American International School of Dhaka, sharing happy moments during their school years"
fill
className="object-cover object-[50%_24%] sm:object-[50%_28%] lg:object-[50%_32%] scale-[1.06] hover:scale-[1.1] transition-transform duration-700 brightness-110 contrast-105 saturate-105 motion-reduce:transform-none motion-reduce:transition-none"
sizes="(max-width: 768px) 100vw, 60vw"
Expand All @@ -149,8 +166,9 @@ export default function HomePage() {
<div className="relative h-40 sm:h-36 lg:h-36 rounded-xl overflow-hidden shadow-lg md:transform md:-rotate-1 md:hover:rotate-0 transition-transform duration-500 motion-reduce:transform-none motion-reduce:transition-none">
<Image
src="/images/story/Where It All Began 2.jpeg"
alt="AISD school days together"
alt="Incia and Arvin during their early friendship at AISD, showcasing their close bond during school activities"
fill
loading="lazy"
className="object-cover scale-[1.1] hover:scale-[1.15] transition-transform duration-700 brightness-125 contrast-110 saturate-110 motion-reduce:transform-none motion-reduce:transition-none"
sizes="(max-width: 640px) 100vw, (max-width: 768px) 50vw, 30vw"
style={{ objectPosition: '48% 32%' }}
Expand All @@ -160,8 +178,9 @@ export default function HomePage() {
<div className="relative h-40 sm:h-36 lg:h-36 rounded-xl overflow-hidden shadow-lg md:transform md:rotate-1 md:hover:rotate-0 transition-transform duration-500 motion-reduce:transform-none motion-reduce:transition-none">
<Image
src="/images/story/Where It All Began 3.jpeg"
alt="Early friendship moments"
alt="Heartwarming moments of Incia and Arvin's blossoming friendship during their teenage years at school"
fill
loading="lazy"
className="object-cover scale-[1.1] hover:scale-[1.15] transition-transform duration-700 brightness-105 saturate-105 motion-reduce:transform-none motion-reduce:transition-none"
sizes="(max-width: 640px) 100vw, (max-width: 768px) 50vw, 30vw"
style={{ objectPosition: '50% 28%' }}
Expand Down
Loading