tourvisto

🧭 Tourvisto

React Router Vite Tailwind CSS Appwrite Stripe

AI-assisted travel itinerary planner with a public trips catalog and an admin dashboard.

Generates multi-day trip plans with Gemini, stores them in Appwrite, and sells trips via Stripe payment links.


🖼️ Preview / Screenshot

Preview


📌 What This Project Is


🧱 Tech Stack

Core Framework

UI / Rendering

Data / Services

AI / ML

External APIs

Tooling

Infrastructure


🗺️ Architecture Overview

The app is a React Router SSR application with public and admin route layouts. It uses Appwrite for authentication and data storage, generates itineraries on the server via Gemini, enriches trips with Unsplash images, and creates Stripe payment links for checkout.

graph TD
  User[User or Admin] --> UI[React Router UI]
  UI -->|Appwrite SDK| Appwrite[(Appwrite Auth + Database)]
  UI -->|OAuth redirect| GoogleOAuth[Google OAuth]
  UI -->|POST /api/create-trip| CreateTrip[Server Action]
  CreateTrip --> Gemini[Gemini API]
  CreateTrip --> Unsplash[Unsplash API]
  CreateTrip --> Appwrite
  CreateTrip --> Stripe[Stripe API]

🗂️ Project Structure

.
├─ app/
│  ├─ routes/
│  ├─ app.css
│  └─ root.tsx
├─ assets/
├─ components/
├─ constants/
├─ lib/
│  ├─ appwrite/
│  └─ stripe/
├─ public/
├─ types/
├─ utils/
├─ react-router.config.ts
├─ vite.config.ts
├─ package.json
└─ Dockerfile

🧩 Core Modules

app/routes.ts Purpose: defines all public, admin, and API routes. Interactions: maps route paths to UI and server action modules. Design decisions: central route config for layout composition.

app/routes/api/create-trip.ts Purpose: server action that generates and stores a trip. Interactions: calls Gemini, Unsplash, Appwrite, and Stripe. Design decisions: stores trip details as JSON and adds a payment link.

lib/appwrite/client.ts Purpose: Appwrite SDK client setup and configuration. Interactions: used by auth, trips, and dashboard queries. Design decisions: reads Appwrite configuration from import.meta.env.

lib/appwrite/auth.ts Purpose: Google OAuth login, session handling, and user persistence. Interactions: Appwrite Account, Users collection, and Google People API for profile images. Design decisions: creates a user document on first sign-in.

lib/stripe/index.ts Purpose: Stripe product, price, and payment link creation. Interactions: invoked by the create-trip action. Design decisions: redirect URL built from VITE_BASE_URL.

app/routes/admin/index.tsx Purpose: admin dashboard with stats, charts, and recent trips. Interactions: pulls stats and lists from Appwrite and renders Syncfusion charts. Design decisions: aggregates stats in lib/appwrite/dashboard.ts.

utils/parse-markdown-to-json.ts Purpose: converts AI responses into JSON when formatting varies. Interactions: used by the create-trip action before persistence. Design decisions: tolerates code fences and partial JSON strings.


🔄 Runtime Flow

Trip creation flow (admin):

sequenceDiagram
  actor Admin
  Admin->>UI: Fill trip form and submit
  UI->>API: POST /api/create-trip
  API->>Gemini: Generate itinerary JSON
  API->>Unsplash: Fetch destination images
  API->>Appwrite: Store trip details
  API->>Stripe: Create product and payment link
  API-->>UI: Return trip id
  UI-->>Admin: Redirect to trip detail page

⚙️ Setup & Installation

Prerequisites:

Install dependencies:

npm install

▶️ Running the Project

Development:

npm run dev

Production build and server:

npm run build
npm run start

Type checking:

npm run typecheck

Docker (optional):

docker build -t tourvisto .
docker run -p 3000:3000 tourvisto

🔐 Configuration

Environment variables are loaded from .env.local for Vite and from the runtime environment for server actions.

Variable Description Required
VITE_SYNCFUSION_LICENSE_KEY Syncfusion license key for UI components Yes
VITE_APPWRITE_API_ENDPOINT Appwrite endpoint URL Yes
VITE_APPWRITE_PROJECT_ID Appwrite project ID Yes
VITE_APPWRITE_DATABASE_ID Appwrite database ID Yes
VITE_APPWRITE_USERS_COLLECTION_ID Appwrite users collection ID Yes
VITE_APPWRITE_TRIPS_COLLECTION_ID Appwrite trips collection ID Yes
VITE_BASE_URL Base URL for Stripe redirect after payment Yes
GEMINI_API_KEY Google Gemini API key Yes
UNSPLASH_ACCESS_KEY Unsplash access key Yes
STRIPE_SECRET_KEY Stripe secret key for server-side calls Yes

Optional local OAuth credentials file: oauth.json.local for Google OAuth configuration in Appwrite.


🚀 Usage


⚠️ Limitations


🔮 Future Improvements (Optional)


📄 License

MIT License. See License: MIT.