# Car Dealer Portfolio & Listings Website — Project Plan

A portfolio + car listings website for a mixed (new & used) car dealership.
Built entirely on Cloudflare's infrastructure to minimize hosting costs.

---

## Design Direction

The reference site (mehnaztabassum.com) gives a good feel for the tone: **professional personal brand, not a marketplace**.

The car dealer site should feel the same way — the dealer's identity and trust comes first, cars come second. Visitors should feel like they're dealing with a credible professional, not browsing a classifieds page.

**Key aesthetic principles:**
- Clean, minimal layout with generous whitespace
- Strong hero section — dealer name, tagline, a quality photo
- Inventory presented as curated cards, not a cluttered grid
- Subtle, professional color palette (think dark navy or charcoal + white + one accent color)
- Simple top navigation: Home, Inventory, About, Contact
- Each car listing page should feel like a product showcase, not a spec sheet

**What makes it feel like a portfolio AND a dealership:**
- "About" section tells the dealer's story — how long in business, what they stand for
- Featured/handpicked cars on the homepage (not just "latest listings")
- Testimonials section (social proof)
- A single strong call-to-action: WhatsApp or phone number, always visible
- **Mobile-first**: most car buyers browse on their phone — the layout must work beautifully on small screens before desktop. Tap targets, readable specs, swipeable photo galleries.

---

## Goals

- Showcase the dealer as a brand (portfolio)
- List cars for sale (~20/month, mixed new & used)
- Let visitors inquire via contact form, WhatsApp, or phone
- Let 2 staff members manage listings through a simple dashboard
- Keep monthly costs as low as possible

---

## Recommended Stack

| Layer | Tool | Why |
|---|---|---|
| Frontend Framework | **SvelteKit** | Close to plain HTML/CSS/JS, easy to learn, excellent Cloudflare support |
| Hosting | **Cloudflare Pages** | Free tier, global CDN, deploy via Wrangler CLI |
| API / Backend Logic | **Cloudflare Workers** | Serverless, built into Pages, free 100K req/day |
| Database | **Cloudflare D1** | Free SQLite DB, perfect for listings & inquiries |
| File Storage | **Cloudflare R2** | Store car photos/short videos, no egress fees |
| Auth (Admin) | **Cloudflare Access** | Free for up to 50 users, Google login — zero code needed |
| Email (Contact Form) | **Resend** or **MailChannels** | Free tiers, works with Workers |
| Deployment | **Wrangler CLI** | Cloudflare's official CLI, deploy directly from your machine |

**Estimated monthly cost: $0 – $5** on Cloudflare free tiers for this scale.

> R2 free tier: 10 GB storage, 1M upload operations, 10M download operations/month.
> D1 free tier: 5M row reads/day, 100K row writes/day.
> Pages free tier: 500 builds/month, unlimited requests.

---

## Site Structure

### Public Pages

```
/                      → Home — hero, featured cars, brief about section
/inventory             → All listings — filterable by type, price, brand
/inventory/[id]        → Single car — photos, specs, price, inquiry form
/about                 → Dealer story, team, credentials
/contact               → Contact form + WhatsApp button + phone
```

### Admin Pages (password-protected)

```
/admin                 → Dashboard overview (total listings, recent inquiries)
/admin/cars            → All car listings — edit or delete
/admin/cars/new        → Add a new car listing
/admin/cars/[id]/edit  → Edit existing listing
/admin/inquiries       → View messages from the contact form
```

---

## Database Schema (Cloudflare D1 — SQLite)

### `cars`
| Column | Type | Notes |
|---|---|---|
| id | TEXT (UUID) | Primary key |
| title | TEXT | e.g. "2022 Toyota Camry" |
| make | TEXT | Toyota, Honda, etc. |
| model | TEXT | Camry, Civic, etc. |
| year | INTEGER | |
| price | INTEGER | In local currency |
| mileage | INTEGER | km or miles |
| fuel_type | TEXT | Petrol, Diesel, Electric, Hybrid |
| transmission | TEXT | Automatic, Manual |
| condition | TEXT | New or Used |
| color | TEXT | |
| description | TEXT | Full listing description |
| is_sold | INTEGER | 0 = available, 1 = sold |
| is_featured | INTEGER | 0 = no, 1 = yes (shows on homepage) |
| created_at | TEXT | ISO timestamp |

### `car_media`
| Column | Type | Notes |
|---|---|---|
| id | TEXT (UUID) | |
| car_id | TEXT | Foreign key → cars.id |
| url | TEXT | R2 public URL |
| type | TEXT | "photo" or "video" |
| sort_order | INTEGER | Controls display order |

### `inquiries`
| Column | Type | Notes |
|---|---|---|
| id | TEXT (UUID) | |
| car_id | TEXT | Nullable (can be general inquiry) |
| name | TEXT | |
| email | TEXT | |
| phone | TEXT | |
| message | TEXT | |
| created_at | TEXT | |

---

## File Storage (Cloudflare R2)

All car photos and short video clips are stored in an R2 bucket.

**Bucket structure:**
```
cars/
  {car-id}/
    photo-1.jpg
    photo-2.jpg
    photo-3.jpg
    walkaround.mp4    ← optional short clip
```

**Notes:**
- Photos should be compressed before upload (use Squoosh or similar — free web tool)
- Short video clips (under 2 min walkarounds) can be stored directly in R2
- For longer or high-quality video, consider Cloudflare Stream ($5/month per 1000 min stored) — optional upgrade later
- R2 files are served via a public URL attached to your Cloudflare domain — no extra CDN needed

---

## Admin Authentication (Cloudflare Access)

Cloudflare Access protects the `/admin` route with zero code changes.

**How to set it up (no coding required):**
1. Go to Cloudflare Zero Trust dashboard (free)
2. Create an application → Self-hosted → set path to `/admin`
3. Add a policy: allow specific email addresses (your two staff emails)
4. Staff log in with their Google account — done

**Cost:** Free for up to 50 users.

---

## Contact & Inquiry Flow

1. Visitor fills in the contact form on `/contact` or `/inventory/[id]`
2. A Cloudflare Worker saves the inquiry to D1
3. An email notification is sent to the dealer via **MailChannels** (free, no account needed) or **Resend** (free 3000 emails/month)
4. The dealer can also view all inquiries in the `/admin/inquiries` dashboard

**WhatsApp button:** A simple `wa.me/` link with the dealer's number — no integration needed.

---

## Deployment Flow

No GitHub needed. Deploy directly from your machine using the **Wrangler CLI**.

```
You write/edit code locally
          ↓
npm run build        ← compiles the site
          ↓
wrangler pages deploy ./build    ← pushes to Cloudflare Pages
          ↓
Live site updated in ~30 seconds
```

**One-time setup:**
```bash
npm install -g wrangler     # install Wrangler globally
wrangler login              # opens browser, log in with your Cloudflare account
```

After that, every deploy is just two commands: `npm run build` then `wrangler pages deploy ./build`.

> **Alternative (no CLI at all):** Cloudflare Pages also supports drag-and-drop upload of your build folder via the dashboard — useful for occasional one-off deploys, but the CLI is faster for regular updates.

---

## Development Phases

### Phase 1 — Foundation
- [ ] Set up SvelteKit project with Cloudflare Pages adapter
- [ ] Connect D1 database, create tables
- [ ] Set up R2 bucket for media
- [ ] Deploy skeleton to Cloudflare Pages via Wrangler CLI

### Phase 2 — Public Site
- [ ] Home page (hero, featured listings, about snippet)
- [ ] Inventory page with filter/search (by type, price range, make)
- [ ] Single car listing page (photo gallery, specs, inquiry form)
- [ ] About page
- [ ] Contact page with form + WhatsApp button

### Phase 3 — Admin Dashboard
- [ ] Protect `/admin` with Cloudflare Access
- [ ] Add/edit/delete car listings
- [ ] Photo upload → R2
- [ ] View inquiries
- [ ] Mark car as sold / featured

### Phase 4 — Polish
- [ ] Mobile-first responsive design (most car buyers browse on phone — priority, not afterthought)
- [ ] SEO meta tags per listing (title, description, OG image)
- [ ] Financing calculator (client-side, no backend needed)
- [ ] Appointment booking (simple form, stores in D1)

---

## What You Can Do Without Coding

| Task | Where |
|---|---|
| Set up Cloudflare Access (admin login) | Cloudflare Zero Trust dashboard |
| Create R2 bucket | Cloudflare R2 dashboard |
| Create D1 database | Cloudflare D1 dashboard |
| Deploy site to Pages | `wrangler pages deploy ./build` in terminal |
| Add/manage car listings | Your own `/admin` dashboard (once built) |
| View inquiries | Your own `/admin` dashboard |

---

## What Needs Code Written

- SvelteKit pages and components
- API routes (Workers functions) for the contact form, listings CRUD
- Admin dashboard UI
- R2 upload logic
- D1 query logic

> Since you're not a developer, consider using Claude Code (this tool) or a developer to write the code. The architecture above is designed to be buildable in stages — each phase is independent.

---

## Estimated Costs at This Scale (~20 cars/month)

| Service | Free Tier Limit | Expected Usage | Cost |
|---|---|---|---|
| Cloudflare Pages | 500 builds/month | ~10/month | **$0** |
| Cloudflare Workers | 100K req/day | ~500/day | **$0** |
| Cloudflare D1 | 5M reads/day | ~1K/day | **$0** |
| Cloudflare R2 | 10 GB storage | ~2–3 GB | **$0** |
| Cloudflare Access | 50 users | 2 users | **$0** |
| Email (MailChannels) | Free via Workers | ~50/month | **$0** |
| Domain (future) | — | — | ~$10/year |
| **Total** | | | **$0/month** |

You would only start paying if you exceed R2's 10 GB (at $0.015/GB after), or add Cloudflare Stream for video hosting ($5/month).

---

## Future Upgrade Path

- **Cloudflare Stream** — if video walkarounds become important
- **Cloudflare Images** — $5/month for automatic image resizing/optimization
- **Cloudflare Queues** — if inquiry volume grows and you need async processing
- **Custom domain** — connect via Cloudflare DNS, free SSL included
- **Analytics** — Cloudflare Web Analytics (free, privacy-friendly, no cookies)

---

## Notes

- All data lives inside Cloudflare's network — no third-party database, no AWS, no Vercel
- The stack scales automatically; no need to provision servers
- If Cloudflare ever becomes a constraint, SvelteKit can be moved to any Node host
- Video: short walkaround clips (< 2 min) store fine in R2. Only upgrade to Stream if you need streaming, chapters, or thumbnails
