# 🧠 Hashtag Orange GMB Dashboard — Project Context (AI-Ready)

> **PURPOSE**: Paste this file as context for any AI agent (Claude, GPT, Gemini) to understand the project instantly.
> **Last Updated**: April 27, 2026 — 4:30 PM IST

## 1. Project Overview

- **Name**: Hashtag Orange GBP Dashboard
- **Owner**: Hashtag Orange (`admin@hashtagorang.in`)
- **Stack**: FastAPI + PostgreSQL + Vanilla JS + TailwindCSS CDN
- **Concept**: 3-tier SaaS (Agency → Client → Dealer) for Google Business Profile monitoring
- **Phase**: 0–5 complete (mock data). Phase 6 (real API) requires Google credentials.

## 2. Directory Structure

```text
GMB/
├── backend/
│   ├── .env                   ← DB + JWT + mock data config
│   ├── requirements.txt       ← All Python deps
│   ├── schema.sql             ← Canonical DDL
│   ├── seed_admin.py          ← Seeds agency admin
│   ├── seed_test_data.py      ← Seeds 1 client + 3 dealers + metrics
│   └── app/
│       ├── main.py            ← FastAPI entry + CORS + 5 router mounts
│       ├── config.py          ← Settings from .env
│       ├── database.py        ← pg8000 connection + init_db()
│       ├── models.py          ← Pydantic schemas
│       ├── auth/
│       │   ├── routes.py      ← POST /login, POST /change-password
│       │   ├── jwt_handler.py ← create/decode JWT (HS256, 24h)
│       │   └── google_oauth.py← GET /google, GET /google/callback (stub)
│       ├── agency/routes.py   ← GET/POST/DELETE /clients
│       ├── client/routes.py   ← GET/POST /dealers, GET /dashboard/cumulative, GET /dashboard/dealer/{id}
│       ├── dealer/routes.py   ← GET /dashboard, POST /posts/create
│       ├── google/
│       │   ├── mock_api.py    ← 8 randomized metrics incl direction_clicks
│       │   ├── gbp_api.py     ← STUB for real API
│       │   └── sync.py        ← Writes mock/real metrics to metrics_cache
│       └── middleware/auth.py ← JWT verify + require_role decorator
├── frontend/
│   ├── index.html             ← SPA: dark login + password change + 3 dashboards
│   ├── app.js                 ← State mgmt + role routing + all API calls
│   └── style.css              ← (empty, using TailwindCSS CDN)
├── walkthrough.md             ← User-facing feature guide
├── workflow.md                ← Technical data flow + dev guide
├── running_steps.md           ← How to run locally
├── phase_audit.md             ← Phase 0-5 completion audit
└── test.md                    ← Browser test screenshots
```

## 3. Database Schema (PostgreSQL — Key-Value Metrics)

- `users`: id, email, password_hash, full_name, role, parent_id, needs_password_change, is_active
- `clients`: id, agency_id, user_id, name, gbp_account_id, is_active
- `dealers`: id, client_id, user_id, location_id, name, city, state, address, is_active
- `metrics_cache`: id, location_id, metric_name, metric_value (key-value per location)

## 4. Authentication

- **Encryption**: bcrypt (12 rounds)
- **Tokens**: JWT HS256, 24-hour expiry
- **First Login**: `needs_password_change=true` → forced change-password screen
- **Google OAuth**: Stub at `/api/auth/google` — auto-activates when GOOGLE_CLIENT_ID is set

## 5. Test Credentials

```text
Agency:  admin@hashtagorang.in          / Admin@123       (no forced change)
Client:  fenesta@example.com            / Client@123      (forced change on first login)
Dealer1: dealer.gurugram@fenesta.com    / Dealer@123      (forced change)
Dealer2: dealer.noida@fenesta.com       / Dealer@123      (forced change)
Dealer3: dealer.jaipur@fenesta.com      / Dealer@123      (forced change)
```

## 6. What's Next (Phase 6)

- Set `USE_MOCK_DATA=false` in `.env`
- Add `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET` to `.env`
- Implement real API calls in `backend/app/google/gbp_api.py`
- Handle Google OAuth2 refresh tokens for persistent API access
