Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

**Don't just book a trip. Design the experience.**

**[Live demo →](https://wandr-tawny.vercel.app)**

Planning a trip today means ten open tabs: destination research, flights, trains, buses,
cabs, hotels, places to visit, activities, restaurants, and finally stitching it all into an
itinerary. Every one of those surfaces optimises for _bookings_. Travellers care about the
Expand Down
Binary file modified docs/screenshots/hero-planner.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 8 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@
<title>Wandr — Don't just book a trip. Design the experience.</title>
<meta
name="description"
content="Wandr is an AI-powered travel experience platform. Tell us your vibe, who you're traveling with, and your budget — we'll design and book the entire journey."
content="Wandr is an intent-first travel experience platform. Tell us your vibe, who you're traveling with, and your budget — we'll design the entire journey."
/>
<meta property="og:title" content="Wandr — AI-Powered Travel Experience Platform" />
<meta property="og:title" content="Wandr — Intent-First Travel Experience Platform" />
<meta property="og:description" content="Tell us your vibe. We'll design the journey." />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://wandr-tawny.vercel.app/" />
<meta property="og:image" content="https://wandr-tawny.vercel.app/og-image.jpg" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Wandr — Don't just book a trip. Design the experience." />
<meta name="twitter:description" content="Tell us your vibe. We'll design the journey." />
<meta name="twitter:image" content="https://wandr-tawny.vercel.app/og-image.jpg" />
<link
rel="icon"
type="image/svg+xml"
Expand Down
Binary file added public/og-image.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export default function App() {
});
};

// Handle AI Planner Submit
// Handle trip planner submit
const handleDesignTrip = (data: {
companion: CompanionType;
vibes: VibeType[];
Expand Down Expand Up @@ -447,7 +447,7 @@ export default function App() {
/>
) : (
<>
{/* 2. Hero + Floating AI Trip Planner */}
{/* 2. Hero + floating trip planner */}
<HeroPlanner
onDesignTrip={handleDesignTrip}
onExploreClick={() => {
Expand Down
8 changes: 4 additions & 4 deletions src/components/FloatingTripSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ export const FloatingTripSummary: React.FC<FloatingTripSummaryProps> = ({
savingsVsBudget: 0,
};

// AI Optimization Savings Calculation vs Standard Retail Prices
// Optimization savings calculation vs standard retail prices
const retailFlightCost = Math.round(costs.flightCost * 1.15) + 650;
const retailStayCost = Math.round(costs.stayCost * 1.22);
const retailActivitiesCost = Math.round(costs.activitiesCost * 1.18);
Expand Down Expand Up @@ -640,15 +640,15 @@ export const FloatingTripSummary: React.FC<FloatingTripSummaryProps> = ({
</div>
</div>

{/* AI Optimization Savings Card */}
{/* Optimization savings card */}
<div className="bg-gradient-to-br from-emerald-50/90 to-teal-50/60 rounded-2xl p-3 border border-emerald-200/80 text-emerald-950">
<div className="flex items-center justify-between mb-1.5">
<div className="flex items-center gap-1.5">
<div className="w-5 h-5 rounded-full bg-emerald-600 text-white flex items-center justify-center">
<TrendingDown className="w-3 h-3" />
</div>
<span className="font-semibold text-xs text-emerald-900">
Wandr AI Savings Summary
Wandr Savings Summary
</span>
</div>
<span className="text-[10px] font-bold px-2 py-0.5 rounded-full bg-emerald-200/80 text-emerald-900 border border-emerald-300">
Expand All @@ -669,7 +669,7 @@ export const FloatingTripSummary: React.FC<FloatingTripSummaryProps> = ({
<span>
You Save{' '}
{formatWithCurrency(totalSavings, selectedCurrencyCode, liveRates)} with
AI Bundling
Smart Bundling
</span>
</div>
</div>
Expand Down
8 changes: 4 additions & 4 deletions src/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export const Footer: React.FC<FooterProps> = ({ onPlanTripClick, onNavigateTab }
</h2>

<p className="text-base sm:text-lg text-stone-400 font-light mb-8">
Your next adventure is closer than you think. Tell us your vibe and let our AI engine
orchestrate the flights, villas, and memory-making.
Your next adventure is closer than you think. Tell us your vibe and let our planning
engine orchestrate the flights, villas, and memory-making.
</p>

<button
Expand All @@ -49,8 +49,8 @@ export const Footer: React.FC<FooterProps> = ({ onPlanTripClick, onNavigateTab }
<WandrLogo size="md" variant="horizontal" theme="white" withTagline={true} />
<p className="text-stone-400 max-w-sm font-light leading-relaxed">
“Don’t just book a trip. Design the experience.” <br />
Wandr is the AI-powered travel platform uniting bespoke discovery, flights, and vetted
sanctuaries under one unified journey.
Wandr is the intent-first travel platform uniting bespoke discovery, flights, and
vetted sanctuaries under one unified journey.
</p>
<div className="flex items-center gap-2 text-stone-500 text-[11px] font-light">
<span>Curated globally with craft & passion</span>
Expand Down
10 changes: 5 additions & 5 deletions src/components/HeroPlanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ interface HeroPlannerProps {
}

export const HeroPlanner: React.FC<HeroPlannerProps> = ({ onDesignTrip, onExploreClick }) => {
// State for AI Planner
// State for the trip planner
const [selectedCompanion, setSelectedCompanion] = useState<CompanionType>('couple');
const [selectedVibes, setSelectedVibes] = useState<VibeType[]>(['Romantic', 'Adventure']);
const [selectedBudget, setSelectedBudget] = useState<BudgetTier>('100k');
Expand Down Expand Up @@ -123,7 +123,7 @@ export const HeroPlanner: React.FC<HeroPlannerProps> = ({ onDesignTrip, onExplor
<div className="inline-flex items-center gap-2.5 px-4 py-1.5 rounded-full bg-[#181E24]/80 backdrop-blur-md border border-white/20 text-stone-200 text-[11px] font-medium uppercase tracking-[0.2em] mb-6 shadow-md">
<WandrLogo size="xs" variant="icon-only" />
<span className="w-1.5 h-1.5 rounded-full bg-[#FF5722] animate-pulse"></span>
<span>wandr AI Travel Experience Platform</span>
<span>wandr Travel Experience Platform</span>
</div>

<h1 className="text-4xl sm:text-5xl lg:text-6xl font-serif font-normal tracking-tight text-white leading-[1.12] mb-6">
Expand Down Expand Up @@ -158,7 +158,7 @@ export const HeroPlanner: React.FC<HeroPlannerProps> = ({ onDesignTrip, onExplor
</div>
</div>

{/* Floating AI Trip Planner Card */}
{/* Floating trip planner card */}
<div
id="ai-planner-card"
className="mt-4 bg-white/95 backdrop-blur-xl rounded-3xl p-6 sm:p-8 border border-stone-200/90 shadow-[0_8px_32px_-8px_rgba(28,25,23,0.08)] transition-all"
Expand Down Expand Up @@ -215,7 +215,7 @@ export const HeroPlanner: React.FC<HeroPlannerProps> = ({ onDesignTrip, onExplor
</div>
</div>

{/* 4 Interactive AI Planner Steps Grid */}
{/* 4 interactive planner steps grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 py-6 border-b border-stone-200/70">
{/* Step 1: Who are you travelling with? */}
<div className="flex flex-col">
Expand Down Expand Up @@ -364,7 +364,7 @@ export const HeroPlanner: React.FC<HeroPlannerProps> = ({ onDesignTrip, onExplor
</div>
</div>

{/* AI Match Preview & Final CTA */}
{/* Match preview & final CTA */}
<div className="pt-6 flex flex-col sm:flex-row items-center justify-between gap-4">
<div className="flex items-center gap-3 w-full sm:w-auto">
<div className="w-12 h-12 rounded-xl overflow-hidden shrink-0 border border-stone-200/80">
Expand Down
4 changes: 2 additions & 2 deletions src/components/HowItWorks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const HowItWorks: React.FC = () => {
num: '04',
title: 'DESTINATION',
icon: '🗺️',
desc: 'AI scores matching world locations with 95%+ compatibility.',
desc: 'We score matching world locations with 95%+ compatibility.',
},
{
num: '05',
Expand All @@ -37,7 +37,7 @@ export const HowItWorks: React.FC = () => {
num: '06',
title: 'CUSTOMIZE',
icon: '🎛️',
desc: 'Swap stays, add private shoots, or prompt AI to shift vibe.',
desc: 'Swap stays, add private shoots, or shift the vibe anytime.',
},
{
num: '07',
Expand Down
6 changes: 3 additions & 3 deletions src/components/LiveTripMode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ export const LiveTripMode: React.FC<LiveTripModeProps> = ({ tripPlan, onOpenFeed
<div>
<div className="flex items-center gap-2">
<span className="text-xs uppercase font-bold text-amber-400 tracking-wider">
AI WEATHER REROUTE ADVICE
WEATHER REROUTE ADVICE
</span>
<span className="text-xs text-stone-400">Rain forecast: 03:45 PM – 05:15 PM</span>
</div>
Expand Down Expand Up @@ -356,7 +356,7 @@ export const LiveTripMode: React.FC<LiveTripModeProps> = ({ tripPlan, onOpenFeed
Completed Your Journey?
</h4>
<p className="text-xs text-stone-400 font-light mt-1 mb-4">
Share your feedback on the AI itinerary & villa stays to earn{' '}
Share your feedback on your itinerary & villa stays to earn{' '}
<span className="text-amber-400 font-semibold">₹1,000 Travel Credit</span>.
</p>
<button
Expand All @@ -377,7 +377,7 @@ export const LiveTripMode: React.FC<LiveTripModeProps> = ({ tripPlan, onOpenFeed
className="w-full py-3 rounded-full bg-gradient-to-r from-amber-500 to-orange-500 hover:from-amber-600 hover:to-orange-600 text-stone-950 font-bold text-xs shadow-md transition-all flex items-center justify-center gap-1.5 cursor-pointer active:scale-98"
>
<Sparkles className="w-3.5 h-3.5" />
<span>Rate AI Journey & Unlock Credit</span>
<span>Rate Your Journey & Unlock Credit</span>
</button>
</div>

Expand Down
8 changes: 4 additions & 4 deletions src/components/PersonalizedTripResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const PersonalizedTripResult: React.FC<PersonalizedTripResultProps> = ({
const [isAiModifying, setIsAiModifying] = useState<boolean>(false);
const [showAddExperienceTray, setShowAddExperienceTray] = useState<boolean>(false);

// AI Prompt Modifiers quick triggers
// Prompt modifier quick triggers
const handleApplyAiModifier = (promptType: string) => {
setIsAiModifying(true);
setTimeout(() => {
Expand Down Expand Up @@ -141,7 +141,7 @@ export const PersonalizedTripResult: React.FC<PersonalizedTripResultProps> = ({
<div className="text-center max-w-3xl mx-auto mb-12">
<div className="inline-flex items-center gap-2 px-3.5 py-1.5 rounded-full bg-[#E05A47]/10 text-[#E05A47] text-[11px] font-semibold uppercase tracking-[0.18em] mb-4">
<Sparkles className="w-3.5 h-3.5" />
AI Dynamic Synthesis Complete
Dynamic Synthesis Complete
</div>
<h2 className="text-3xl sm:text-5xl font-serif font-bold text-stone-900 tracking-tight mb-4">
Your trip,{' '}
Expand Down Expand Up @@ -182,7 +182,7 @@ export const PersonalizedTripResult: React.FC<PersonalizedTripResultProps> = ({
</div>
</div>

{/* AI Itinerary Quick-Action Bar */}
{/* Itinerary quick-action bar */}
<div className="bg-white rounded-3xl p-4 sm:p-6 border border-stone-200/90 mb-10 shadow-2xs">
<div className="flex flex-col lg:flex-row lg:items-center justify-between gap-4">
{/* Quick Prompt Pill Buttons */}
Expand Down Expand Up @@ -215,7 +215,7 @@ export const PersonalizedTripResult: React.FC<PersonalizedTripResultProps> = ({
</button>
</div>

{/* Custom AI Prompt Input */}
{/* Custom prompt input */}
<div className="flex items-center gap-2 max-w-md w-full">
<div className="relative w-full">
<input
Expand Down
4 changes: 2 additions & 2 deletions src/components/PreTripChecklist.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
}

setChecklistData(baseData);
}, [

Check warning on line 99 in src/components/PreTripChecklist.tsx

View workflow job for this annotation

GitHub Actions / build

React Hook useEffect has missing dependencies: 'storageKey' and 'tripPlan'. Either include them or remove the dependency array
tripPlan.destination?.id,
tripPlan.durationDays,
tripPlan.companion,
Expand Down Expand Up @@ -203,7 +203,7 @@
});
});

lines.push(`\nGenerated with Wandr AI Travel Assistant`);
lines.push(`\nGenerated with Wandr`);

navigator.clipboard.writeText(lines.join('\n'));
setCopiedToast(true);
Expand Down Expand Up @@ -423,7 +423,7 @@
<div className="bg-white p-3.5 rounded-xl border border-stone-200/70 shadow-2xs">
<div className="flex items-center gap-1.5 font-semibold text-stone-900 mb-1">
<Sparkles className="w-4 h-4 text-emerald-600" />
<span>AI Smart Packing Hacks</span>
<span>Smart Packing Hacks</span>
</div>
<ul className="space-y-1 text-stone-600 font-light">
{checklistData.luggageAdvice.packingHacks.slice(0, 3).map((hack, idx) => (
Expand Down
14 changes: 7 additions & 7 deletions src/components/TripFeedbackModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export const TripFeedbackModal: React.FC<TripFeedbackModalProps> = ({
{/* 1. Overall Star Rating */}
<div className="text-center bg-[#FAF8F5] p-5 rounded-3xl border border-stone-200/80">
<label className="text-xs font-semibold text-stone-500 uppercase tracking-wider block mb-1">
Overall AI Experience Rating
Overall Experience Rating
</label>

{/* Stars Row */}
Expand Down Expand Up @@ -211,11 +211,11 @@ export const TripFeedbackModal: React.FC<TripFeedbackModalProps> = ({
</label>

<div className="grid grid-cols-1 sm:grid-cols-2 gap-2.5 text-xs">
{/* AI Planning */}
{/* Planning */}
<div className="bg-stone-50 p-3 rounded-2xl border border-stone-200/80 flex items-center justify-between">
<span className="font-medium text-stone-800 flex items-center gap-1.5">
<Sparkles className="w-3.5 h-3.5 text-[#E05A47]" />
AI Route & Timing
Route & Timing
</span>
<div className="flex items-center gap-1">
{[1, 2, 3, 4, 5].map((s) => (
Expand Down Expand Up @@ -348,7 +348,7 @@ export const TripFeedbackModal: React.FC<TripFeedbackModalProps> = ({
<MessageSquare className="w-3.5 h-3.5 text-stone-500" />
Share Your Thoughts & Comments
</label>
<span className="text-[10px] text-stone-400">Helps refine future AI trips</span>
<span className="text-[10px] text-stone-400">Helps refine future trips</span>
</div>
<textarea
value={comments}
Expand Down Expand Up @@ -376,7 +376,7 @@ export const TripFeedbackModal: React.FC<TripFeedbackModalProps> = ({
{/* 6. Recommendation Question */}
<div className="pt-2 border-t border-stone-100 flex flex-col sm:flex-row sm:items-center justify-between gap-2">
<span className="text-xs font-medium text-stone-700">
Would you recommend Wandr AI to friends?
Would you recommend Wandr to friends?
</span>
<div className="flex items-center gap-1.5">
{[
Expand Down Expand Up @@ -451,8 +451,8 @@ export const TripFeedbackModal: React.FC<TripFeedbackModalProps> = ({
Thank You for Your Feedback!
</h4>
<p className="text-xs sm:text-sm text-stone-500 font-light max-w-sm mx-auto">
Your insights help Wandr AI refine future personalized itineraries, route
algorithms, and luxury partner curation.
Your insights help Wandr refine future personalized itineraries, route algorithms,
and luxury partner curation.
</p>
</div>

Expand Down
4 changes: 2 additions & 2 deletions src/components/WeatherForecastCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ export const WeatherForecastCard: React.FC<WeatherForecastCardProps> = ({
</div>
</div>

{/* Right Column: AI Packing & Destination Advisory */}
{/* Right column: packing & destination advisory */}
<div className="lg:col-span-5 bg-white p-5 rounded-2xl border border-stone-200/90 shadow-2xs space-y-3.5">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
Expand All @@ -394,7 +394,7 @@ export const WeatherForecastCard: React.FC<WeatherForecastCardProps> = ({
</div>

<p className="text-[11px] text-stone-500 font-light">
AI recommendations based on predicted humidity and temperature ranges for{' '}
Recommendations based on predicted humidity and temperature ranges for{' '}
<span className="font-medium text-stone-700">{report.destinationName}</span>:
</p>

Expand Down
2 changes: 1 addition & 1 deletion src/utils/shareableTripLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ export function generateTripIcsCalendar(tripPlan: TripPlan): string {
const icsContent = [
'BEGIN:VCALENDAR',
'VERSION:2.0',
'PRODID:-//Wandr//AI Travel Curator//EN',
'PRODID:-//Wandr//Trip Curator//EN',
'CALSCALE:GREGORIAN',
'METHOD:PUBLISH',
`X-WR-CALNAME:Wandr Trip: ${tripPlan.destination.name} (${tripPlan.durationDays}D)`,
Expand Down
4 changes: 2 additions & 2 deletions src/utils/tripExportService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export function generateUpcomingTripIcs(trip: UpcomingTripItem, userProfile?: Us
const icsContent = [
'BEGIN:VCALENDAR',
'VERSION:2.0',
'PRODID:-//Wandr//AI Travel Curator//EN',
'PRODID:-//Wandr//Trip Curator//EN',
'CALSCALE:GREGORIAN',
'METHOD:PUBLISH',
`X-WR-CALNAME:Wandr Trip: ${trip.destinationName} (${trip.days} Days)`,
Expand Down Expand Up @@ -194,7 +194,7 @@ export async function downloadUpcomingTripPdf(
doc.setFontSize(8);
doc.setFont('helvetica', 'normal');
doc.setTextColor(200, 200, 200);
doc.text('AI TRAVEL CURATOR & LUXURY CONCIERGE', margin + 8, y + 18);
doc.text('CURATED TRAVEL & LUXURY CONCIERGE', margin + 8, y + 18);

doc.setFontSize(12);
doc.setFont('helvetica', 'bold');
Expand Down
2 changes: 1 addition & 1 deletion src/utils/weatherForecastService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ export function generateDestinationWeatherForecast(
daysForecast,
aiWeatherSuitabilityScore: 95,
aiSuitabilityVerdict: 'Optimal Climate Window • Ideal for Outdoor Itineraries',
lastUpdated: 'Live AI Climate Sync',
lastUpdated: 'Live Climate Sync',
};
}

Expand Down
Loading