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
24 changes: 24 additions & 0 deletions graffify/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# /graffify — Agent Context Hub

This folder exists so that **AI agents** (GitHub Copilot, Claude, GPT, etc.) can instantly understand the RideHub codebase **without scanning every source file**, saving tokens and reducing latency.

## Why this folder?

Reading an entire repository file-by-file is expensive in tokens. A full scan of RideHub (TypeScript source + config + lock files) costs thousands of tokens before any useful work begins. This folder provides a **pre-digested, structured summary** of the whole repo so agents can orient themselves in one or two reads.

## Files in this folder

| File | What it covers |
|---|---|
| [`context.md`](./context.md) | Repo overview, tech stack, env vars, project structure, scripts, and key file paths |
| [`architecture.md`](./architecture.md) | Pages, component tree, auth flow, API integration, and data flow |
| [`types.md`](./types.md) | All TypeScript interfaces and types used across the codebase |

## How agents should use this folder

1. **Start here** — read `context.md` first for a complete orientation.
2. **Drill into architecture** — read `architecture.md` to understand pages, components, and the request/response flow.
3. **Check types** — read `types.md` before writing or editing any TypeScript.
4. **Then** read specific source files only as needed for the exact change you are making.

> Keep these files up-to-date when adding new pages, components, types, or dependencies.
165 changes: 165 additions & 0 deletions graffify/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# RideHub — Architecture & Component Reference

## Page Map

| Route | File | Description |
|---|---|---|
| `/` | `app/page.tsx` | Home: hero, search bar, ride options, promotions, recent rides |
| `/login` | `app/login/page.tsx` | Auth: guest / Google / username+password |
| `/results` | `app/results/page.tsx` | Ride results with Leaflet map, filter tabs, ride cards |
| `/bookings` | `app/bookings/page.tsx` | Booking history (requires auth) |
| `/profile` | `app/profile/page.tsx` | Profile dashboard (real user or guest mock) |

---

## Component Tree

```
app/layout.tsx
└── ThemeProvider (next-themes)
└── Providers (QueryClientProvider + AuthProvider)
├── Navbar (components/layout/navbar.tsx)
│ ├── Desktop nav links
│ └── Mobile floating pill nav
└── <page children>

app/page.tsx (Home)
├── HeroSection
├── SearchBar ← useNominatim hook, geolocation, date picker
├── RideOptions
├── PromotionsSlider
└── RecentRides

app/results/page.tsx
├── Filter tabs (Fastest / Cheapest / Eco / Public)
├── Leaflet Map ← road polyline overlay
└── Ride Cards ← per provider (Uber, Ola, Rapido, Metro, Bus)

app/login/page.tsx
├── Guest login button
├── Google OAuth button
└── Username/Password form ← react-hook-form + zod

app/bookings/page.tsx
└── Booking list ← fetches GET /bookings/{uid}

app/profile/page.tsx
├── ProfileInfo
├── PreferencesForm
└── PaymentMethods
```

---

## Data Flow: Ride Search

```
SearchBar (app/page.tsx)
│ User enters From/To, optional schedule time
│ useNominatim → GET Nominatim API (browser, proximity-biased)
/results page (app/results/page.tsx)
├── POST /route/ (backend → OSRM)
│ → { distance_km, duration_min, polyline }
├── POST /rides/search (backend → fare engine)
│ → [ { service, type, price, eta, distance } ]
├── Leaflet map renders polyline
└── Ride cards rendered + filter tabs applied
```

---

## Data Flow: Booking

```
/results page
│ User clicks "Book" on a ride card
POST /bookings/ (backend → Supabase)
→ { booking_id }
/bookings page
GET /bookings/{uid}
→ [ Booking[] ]
```

---

## Auth Context API (`components/auth/auth-context.tsx`)

```ts
interface AuthContextValue {
user: User | null;
isGuest: boolean;
isLoading: boolean;
login(username: string, password: string): Promise<void>;
signup(username: string, password: string): Promise<void>;
loginWithGoogle(google_id: string): void;
loginAsGuest(): void;
logout(): void;
}
```

Usage in any component:
```ts
import { useAuth } from '@/components/auth/auth-context';
const { user, login, logout } = useAuth();
```

---

## Hooks

### `use-nominatim.ts`
Debounced location search using the OpenStreetMap Nominatim API.
- Accepts a query string and optional user coordinates for proximity bias.
- Returns `{ results, isLoading }` where results are sorted by distance to the user.

### `use-toast.ts`
Wrapper around the shadcn/ui toast system. Returns `{ toast }`.

---

## Key Library Utilities

### `lib/utils.ts`
```ts
cn(...inputs): string // clsx + tailwind-merge — use for all conditional class strings
```

### `lib/api.ts`
```ts
const API: string // = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:8000"
```

### `lib/animations.ts`
Shared Framer Motion animation variants (fadeIn, slideUp, stagger, etc.) — import and apply via `variants` prop.

### `lib/mock-data.tsx`
Fallback ride options used in guest mode or when the backend is unavailable.

---

## Mobile (Capacitor)

- `capacitor.config.ts` — app ID `com.ridehub.app`, webDir `out`.
- `BUILD_TARGET=mobile` triggers static export in `next.config.js`.
- Google OAuth does **not** work in the Capacitor in-app browser — use username/password or guest mode on Android.

---

## Configuration Files

| File | Purpose |
|---|---|
| `next.config.js` | Next.js config; static export when `BUILD_TARGET=mobile` |
| `tailwind.config.ts` | Theme tokens, dark mode class, shadcn/ui content paths |
| `tsconfig.json` | `@/` alias → repo root |
| `capacitor.config.ts` | Capacitor app settings |
| `.eslintrc.json` | ESLint rules (extends next/core-web-vitals) |
| `components.json` | shadcn/ui component configuration |
145 changes: 145 additions & 0 deletions graffify/context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# RideHub — Repository Context

## What is RideHub?

RideHub is a **ride aggregation platform** (frontend only in this repo). Users can search, compare, and book rides across Uber, Ola, Rapido, Metro, and Bus — all from one interface. The backend is a separate **private** FastAPI + Supabase repository.

---

## Tech Stack

| Layer | Technology |
|---|---|
| Framework | Next.js 15 (App Router) |
| Language | TypeScript |
| Styling | Tailwind CSS + shadcn/ui (Radix UI primitives) |
| Animations | Framer Motion |
| Icons | Lucide React |
| Maps | Leaflet + react-leaflet |
| Location Search | Nominatim (OpenStreetMap) |
| Road Routing | OSRM (via backend proxy) |
| Auth | Custom username/password + Google OAuth + Guest mode |
| Auth State | React Context (`AuthContext`) with hydration guard |
| Theme | next-themes with View Transition API ripple |
| Mobile | Capacitor (Android APK) |
| Forms | react-hook-form + zod |
| Data fetching | @tanstack/react-query |

---

## Environment Variables

| Variable | Description |
|---|---|
| `NEXT_PUBLIC_API_URL` | Base URL of the RideHub FastAPI backend (default: `http://localhost:8000`) |

Set in `.env.local` (copy from `.env.example`).

---

## NPM Scripts

| Script | Purpose |
|---|---|
| `npm run dev` | Start Next.js dev server with Turbopack |
| `npm run build` | Production build |
| `npm run build:mobile` | Mobile build (`BUILD_TARGET=mobile`) |
| `npm run start` | Start production server |
| `npm run lint` | ESLint |
| `npm run cap:sync` | Build + sync to Capacitor |
| `npm run cap:android` | Build + open in Android Studio |

---

## Project Structure

```
RideHub/
├── graffify/ ← Agent context hub (this folder)
├── app/
│ ├── layout.tsx # Root layout: Navbar, ThemeProvider, Providers
│ ├── page.tsx # Home page (HeroSection, SearchBar, RideOptions, Promotions, RecentRides)
│ ├── providers.tsx # Wraps children with QueryClientProvider + AuthProvider
│ ├── globals.css # Global Tailwind CSS
│ ├── login/
│ │ └── page.tsx # Auth page: guest / Google OAuth / username+password
│ ├── results/
│ │ └── page.tsx # Ride results: map, filter tabs, ride cards
│ ├── bookings/
│ │ └── page.tsx # Booking history list
│ └── profile/
│ └── page.tsx # Profile dashboard (real user or guest mock)
├── components/
│ ├── auth/
│ │ └── auth-context.tsx # AuthContext: login, signup, loginWithGoogle, loginAsGuest, logout
│ ├── home/
│ │ ├── hero-section.tsx
│ │ ├── search-bar.tsx # From/To inputs, date picker, Nominatim suggestions
│ │ ├── ride-options.tsx
│ │ ├── promotions-slider.tsx
│ │ └── recent-rides.tsx
│ ├── layout/
│ │ └── navbar.tsx # Top nav (desktop) + floating bottom pill nav (mobile)
│ ├── results/ # Ride result cards, Leaflet map, filter tabs
│ ├── bookings/ # Booking list UI components
│ ├── profile/ # ProfileInfo, PreferencesForm, PaymentMethods
│ └── ui/ # shadcn/ui primitives (button, card, dialog, etc.)
├── hooks/
│ ├── use-nominatim.ts # Debounced Nominatim location search with proximity bias
│ └── use-toast.ts # Toast notification hook
├── lib/
│ ├── api.ts # Exports `API` base URL from NEXT_PUBLIC_API_URL
│ ├── mock-data.tsx # Fallback/mock ride recommendations for guest mode
│ ├── animations.ts # Shared Framer Motion variants
│ └── utils.ts # cn() (clsx + tailwind-merge) and misc helpers
├── types/
│ ├── location.ts # Location, RideOption, RideRecommendation
│ └── booking.ts # Booking, RideStatus, BookingType
├── public/ # Static assets
├── android/ # Capacitor Android project
├── .env.example
├── next.config.js
├── tailwind.config.ts
├── tsconfig.json
├── capacitor.config.ts
└── package.json
```

---

## Key Conventions

- **Path alias**: `@/` maps to the repo root (configured in `tsconfig.json`).
- **Styling**: Always use Tailwind utility classes. Use `cn()` from `lib/utils.ts` for conditional classes.
- **Components**: Use shadcn/ui primitives from `components/ui/`. New components go in `components/<feature>/`.
- **Auth**: Use `useAuth()` hook (from `AuthContext`) to access user state and auth methods.
- **API calls**: Import base URL from `lib/api.ts` (`import API from '@/lib/api'`).
- **Types**: Always import types from `types/` — never inline type definitions in component files.
- **Animations**: Use shared variants from `lib/animations.ts` with Framer Motion.
- **Routing**: Next.js App Router — all routes are `app/<route>/page.tsx`.

---

## Backend API Endpoints (called from frontend)

| Method | Path | Purpose |
|---|---|---|
| GET | `/health` | Wake/ping backend |
| POST | `/auth/login` | Username+password login |
| POST | `/auth/signup` | Username+password signup |
| GET | `/auth/google` | Start Google OAuth flow |
| GET | `/auth/google/callback` | Google OAuth callback |
| POST | `/route/` | Real road routing (OSRM) → distance, duration, polyline |
| POST | `/rides/search` | Fare calculation for all providers |
| POST | `/bookings/` | Create a booking (saved to Supabase) |
| GET | `/bookings/{uid}` | Fetch user's booking history |

---

## Auth Flow Summary

- **Guest**: instant access, mock profile, no backend calls, stored as `ridehub_guest` in localStorage.
- **Username/Password**: POST `/auth/login` or `/auth/signup` → JWT-free session stored in `ridehub_user` in localStorage. Parsed in `try/catch` to guard against corrupt JSON (resets auth state on parse error).
- **Google OAuth**: redirect to `/auth/google` (backend) → Google consent → callback → redirect to `/login?google_id=...` → `loginWithGoogle()` → stored in context → redirect to `/profile`.
- **Cross-tab sync**: `storage` event listener keeps auth state consistent across tabs.
- **Hydration guard**: profile page waits for localStorage hydration before deciding to redirect.
Loading
Loading