# BookWithNesto

A full-stack shortlet apartment booking platform for Nigeria, featuring premium property listings, WhatsApp price negotiation, in-app chat (AskNesto), Clerk auth, and a token-protected admin dashboard.

## Run & Operate

- `pnpm --filter @workspace/api-server run dev` — run the API server (port 8080, proxied at `/api`)
- `pnpm --filter @workspace/bookwithnesto run dev` — run the frontend (port 20521, proxied at `/`)
- `pnpm run typecheck` — full typecheck across all packages
- `pnpm run build` — typecheck + build all packages
- `pnpm --filter @workspace/api-spec run codegen` — regenerate API hooks and Zod schemas from the OpenAPI spec
- `pnpm --filter @workspace/db run push` — push DB schema changes (dev only); run `pnpm run typecheck:libs` after to refresh declarations

## Stack

- pnpm workspaces, Node.js 24, TypeScript 5.9
- Frontend: React 19 + Vite + Wouter + TanStack Query + shadcn/ui + Tailwind v4 + Framer Motion
- Auth: Clerk (`@clerk/react`, `@clerk/themes` — shadcn theme)
- API: Express 5
- DB: PostgreSQL + Drizzle ORM
- Validation: Zod (`zod/v4`), `drizzle-zod`
- API codegen: Orval (from OpenAPI spec)
- Build: esbuild (CJS bundle)

## Where things live

- `lib/db/src/schema/` — all Drizzle table definitions (source of truth for DB schema)
- `lib/api-spec/openapi.yaml` — OpenAPI spec (source of truth for API contract)
- `lib/api-client-react/src/generated/` — generated React Query hooks (do not edit manually)
- `artifacts/api-server/src/routes/` — Express route handlers
- `artifacts/bookwithnesto/src/pages/` — all page components
- `artifacts/bookwithnesto/src/components/` — shared UI components (layout, chat widget, etc.)

## Architecture decisions

- Contract-first API: OpenAPI spec drives codegen for both React Query hooks and Zod schemas
- Admin dashboard uses a simple token gate (`nestoAdmin2024` stored in sessionStorage), NOT Clerk — allows non-Clerk admin access
- WhatsApp negotiation: each apartment detail page has a "Negotiate on WhatsApp" button linking to `wa.me/2348000000000` with a pre-filled message
- AskNesto chat widget: floating bottom-right widget with keyword-based auto-reply on the server; no external AI dependency
- Clerk proxy: frontend uses `VITE_CLERK_PROXY_URL` so auth requests route through the API server (`/api/__clerk`)

## Product

- **Public site**: Home, Apartments listing with filters, Apartment detail with gallery + booking widget, Gallery, Blog (The Nesto Journal), About, Services, Contact
- **Auth**: Sign In / Sign Up via Clerk (email, Google, Apple)
- **Booking**: Inquiry form on apartment detail page; bookings tracked in DB
- **WhatsApp**: "Negotiate on WhatsApp" button on every apartment; "Chat on WhatsApp" in AskNesto widget
- **AskNesto**: In-app chat with keyword auto-reply (availability, price, booking inquiries)
- **Dashboard**: Protected user area showing personal bookings
- **Admin** (`/admin`, token: `nestoAdmin2024`): Stats overview, manage apartments/bookings/blog/contacts/gallery

## User preferences

- WhatsApp number: `2349040004433` (wa.me/2349040004433) — local: 09040004433
- Admin token: `nestoAdmin2024`
- Primary cities: Lagos, Abuja, Port Harcourt

## Gotchas

- After any DB schema change: run `pnpm --filter @workspace/db run push` then `pnpm run typecheck:libs` to refresh lib declarations before typechecking API server
- `@clerk/themes` must be installed separately (`pnpm --filter @workspace/bookwithnesto add @clerk/themes`)
- Vite config must use `tailwindcss({ optimize: false })` for Clerk themes to render correctly
- `index.css` must have `@layer theme, base, clerk, components, utilities;` before `@import "tailwindcss"`

## Pointers

- See the `pnpm-workspace` skill for workspace structure, TypeScript setup, and package details
- See the `clerk-auth` skill for Clerk configuration details
