# GoodGo Platform AI - Next.js Frontend Exploration Report ## 1. Overall Directory Structure ### Root Layout ``` /Users/velikho/Desktop/WORKING/goodgo-platform-ai/apps/web/ ├── app/ # Next.js App Router directory ├── components/ # Reusable React components ├── lib/ # API clients, hooks, utilities, stores ├── i18n/ # Internationalization config ├── messages/ # Translation files ├── public/ # Static assets ├── node_modules/ # Dependencies └── package.json # Project metadata & dependencies ``` ### Key Dependencies (from package.json) - **Framework**: Next.js 15.5.14, React 18.3.0 - **State Management**: Zustand 5.0.12 (lightweight state), @tanstack/react-query 5.96.2 (server state) - **Forms**: react-hook-form 7.72.1, @hookform/resolvers 5.2.2, zod 4.3.6 - **Mapping**: mapbox-gl 3.21.0, @types/mapbox-gl 3.5.0 - **Charts**: recharts 3.8.1 - **UI**: Tailwind CSS 3.4.0, class-variance-authority 0.7.1 - **Icons**: lucide-react 1.7.0 - **Other**: next-intl 4.9.0, next-themes 0.4.6, socket.io-client 4.8.3, html2canvas + jspdf --- ## 2. App Router Structure (Next.js 15 App Router) ### Directory: `/app/[locale]/` Routes are organized by locale (vi/en) with multiple layout groups: ``` app/[locale]/ ├── (public)/ # Public routes (no auth required) │ ├── listings/ │ │ ├── page.tsx # Listings search/browse page │ │ └── [id]/page.tsx # Individual listing detail page │ ├── search/ # Advanced search interface │ ├── khu-cong-nghiep/ # Industrial parks (Vietnamese) │ ├── du-an/ # Projects │ ├── bao-cao/ # Reports │ ├── agents/[id]/ # Agent profiles │ └── payment/return/ # Payment callbacks ├── (auth)/ # Authentication routes │ ├── login/page.tsx │ ├── register/page.tsx │ └── auth/callback/ # OAuth callbacks (Google, Zalo) ├── (dashboard)/ # Protected routes (auth required) │ ├── dashboard/ # Main dashboard │ ├── analytics/ # Market analytics │ ├── industrial-parks/ # Industrial park management │ ├── valuation/ # Valuation service │ ├── reports/ # User's reports │ └── ... ├── (admin)/ # Admin routes │ └── admin/ │ ├── users/ │ ├── kyc/ │ ├── moderation/ │ └── ... ├── auth/callback/ # Special auth callbacks │ ├── zalo/page.tsx │ └── google/page.tsx └── [locale]/layout.tsx # Root layout wrapping all routes ``` --- ## 3. Components Directory Structure ### Organized by Domain: ``` components/ ├── listings/ # Listing-related components │ ├── listing-detail-client.tsx (39KB - main detail component) │ ├── listing-form-steps.tsx (14KB - form wizard) │ ├── ai-advice-cards.tsx (9KB - AI recommendations) │ ├── image-gallery.tsx │ ├── image-lightbox.tsx │ ├── image-upload.tsx │ ├── inquiry-modal.tsx │ ├── price-history-chart.tsx (uses recharts) │ ├── social-share.tsx │ └── sparkline.tsx │ ├── neighborhood/ # Neighborhood analysis components │ ├── neighborhood-poi-map.tsx (11KB - POI map with Mapbox) │ ├── neighborhood-radar-chart.tsx (2KB - radar chart) │ ├── neighborhood-score.tsx (2KB - score display) │ ├── types.ts # Shared types & config │ └── index.ts # Barrel export │ ├── map/ # Map components │ ├── listing-map.tsx (10KB - listings on Mapbox) │ └── location-picker.tsx (9KB - location selection) │ ├── charts/ # Recharts-based charts │ ├── price-area-chart.tsx (2KB - trend visualization) │ ├── price-trend-chart.tsx │ ├── district-bar-chart.tsx │ ├── district-heatmap.tsx (9KB - with Mapbox) │ └── agent-performance.tsx │ ├── design-system/ # Reusable UI primitives & patterns │ ├── badge.tsx │ ├── kpi-card.tsx # Key performance indicator card │ ├── stat-card.tsx # Statistics card │ ├── ticker-strip.tsx # Horizontal ticker │ ├── price-delta.tsx # Price change indicator │ ├── signal.tsx # Up/down signal display │ ├── numeric.tsx # Formatted number display │ ├── status-chip.tsx │ ├── empty-state.tsx │ ├── skeleton.tsx │ ├── data-table.tsx # @tanstack/react-table wrapper │ ├── dashboard-layout.tsx │ ├── density-provider.tsx # Density/compact mode │ └── index.ts │ ├── khu-cong-nghiep/ # Industrial park domain ├── du-an/ # Project domain ├── agents/ # Real estate agents ├── valuation/ # Valuation/AVM features ├── search/ # Search interface ├── comparison/ # Property comparison ├── leads/ # Lead management ├── inquiries/ # Inquiry management ├── reports/ # Report generation ├── chuyen-nhuong/ # Transfer/ownership change ├── notifications/ ├── auth/ ├── providers/ # React context providers │ ├── auth-provider.tsx │ ├── query-provider.tsx # React Query with error boundary │ ├── theme-provider.tsx # next-themes integration │ ├── notifications-provider.tsx │ └── web-vitals.tsx ├── seo/ # SEO components │ └── json-ld.tsx # JSON-LD schema generation ├── subscription/ ├── ui/ # Base UI components (from shadcn/ui) │ ├── badge.tsx │ ├── button.tsx │ ├── card.tsx │ ├── dialog.tsx │ └── ... (standard shadcn components) ``` --- ## 4. Existing Neighborhood Components ### Key Files: - **`components/neighborhood/types.ts`** - `NeighborhoodCategory`: score category with label, score (0-10), icon - `POIItem`: Point of Interest (school, hospital, etc.) with lat/lng - `NeighborhoodScoreData`: aggregated neighborhood data - `POI_CATEGORY_CONFIG`: config for 6 categories (school, hospital, transit, shopping, restaurant, park) - `DEFAULT_CATEGORIES`: default scoring categories - **`components/neighborhood/neighborhood-poi-map.tsx`** - Uses Mapbox GL with hardcoded SVG icons for 6 POI categories - Category filter toggles - Responsive map with custom markers - Integrated POI display - **`components/neighborhood/neighborhood-radar-chart.tsx`** - Recharts `RadarChart` component - 0-10 score scale - Badge display below chart - Responsive, themed - **`components/neighborhood/neighborhood-score.tsx`** - Small score display component - Used as quick reference ### Integration in Listing Detail: - Dynamically imported in `listing-detail-client.tsx` - Used when neighborhood data is available from API - Part of the enrichment data pipeline --- ## 5. Mapbox GL Integration ### Setup & Styling: - **`lib/mapbox-style.ts`** ```typescript export const MAPBOX_STYLE_LIGHT = 'mapbox://styles/mapbox/streets-v12'; export const MAPBOX_STYLE_DARK = 'mapbox://styles/mapbox/dark-v11'; export function useMapboxStyle(): string { const { theme } = useTheme(); return theme === 'dark' ? MAPBOX_STYLE_DARK : MAPBOX_STYLE_LIGHT; } ``` ### Map Components: 1. **`components/map/listing-map.tsx`** (10KB) - Displays multiple listings as markers - Custom markers with price popup - Click handler for marker selection - Responsive sizing - City coordinate presets for auto-centering 2. **`components/map/location-picker.tsx`** (9KB) - Interactive location selection - User-clickable map for address input - Reverse geocoding integration 3. **`components/neighborhood/neighborhood-poi-map.tsx`** (11KB) - POI visualization with category filters - SVG marker icons (6 types) - Distance display - Category toggle buttons ### Pattern: - Maps created as client components (`'use client'`) - Mapbox GL CSS imported per file - Theme-aware style selection via `useMapboxStyle()` - Responsive containers --- ## 6. API Client Setup ### Main Client: `lib/api-client.ts` (127 lines) ```typescript // Core features: - Base URL from environment: process.env.NEXT_PUBLIC_API_URL - CSRF token handling from cookies - Automatic 401 refresh-and-retry (except auth endpoints) - Concurrent refresh coalescing - Type-safe request/response with generics - Credentials: include for cookies // API methods: apiClient.get(endpoint, headers?) apiClient.post(endpoint, body?, headers?) apiClient.patch(endpoint, body?, headers?) apiClient.delete(endpoint, headers?) ``` ### Domain-Specific API Clients (in `lib/`): - `listings-api.ts` - Listing CRUD, search, recommendations - `analytics-api.ts` - Market reports, heatmaps, price trends - `agents-api.ts` - Agent profiles & stats - `valuation-api.ts` - AVM (Automated Valuation Model) estimates - `khu-cong-nghiep-api.ts` - Industrial park data - `du-an-api.ts` - Project data - `inquiries-api.ts` - Inquiry management - `leads-api.ts` - Lead data - `reports-api.ts` - Report generation - `admin-api.ts` - Admin operations - `auth-api.ts` - Auth endpoints - `payment-api.ts` - Payment processing Each API module: - Defines request/response interfaces - Uses `apiClient` helper for HTTP calls - May have both client and server implementations --- ## 7. Hooks & React Query Integration ### React Query Setup: `lib/query-client.ts` ```typescript // Creates QueryClient singleton // Provider in components/providers/query-provider.tsx // Includes QueryErrorResetBoundary error handling ``` ### Custom Hooks: `lib/hooks/` ``` use-analytics.ts - Market reports, heatmaps, trends use-khu-cong-nghiep.ts - Industrial parks use-du-an.ts - Projects use-listings.ts - Listings data use-valuation.ts - AVM valuations use-inquiries.ts - Inquiries use-leads.ts - Leads use-reports.ts - Reports use-saved-searches.ts - Saved search queries use-socket-notifications.ts - Real-time notifications ``` ### Hook Pattern (example from `use-analytics.ts`): ```typescript export const analyticsKeys = { all: ['analytics'] as const, marketReport: (city, period) => [...], // ... }; export function useMarketReport(city: string, period: string) { return useQuery({ queryKey: analyticsKeys.marketReport(city, period), queryFn: () => analyticsApi.getMarketReport(city, period), }); } ``` --- ## 8. Chart Components ### Using Recharts: 1. **`components/charts/price-area-chart.tsx`** - AreaChart with gradient fills - Up/down signal coloring - Formatted Y-axis (tr/k notation for Vietnamese) - Responsive container 2. **`components/charts/district-heatmap.tsx`** (9KB) - District-level visualization - Possibly Mapbox layer integration 3. **`components/charts/price-trend-chart.tsx`** - Historical price trends - Multi-period comparison 4. **`components/charts/district-bar-chart.tsx`** - Bar chart for district comparisons 5. **`components/charts/agent-performance.tsx`** (6KB) - Agent metrics visualization 6. **`components/listings/price-history-chart.tsx`** (2KB) - Listing-specific price history - Small inline chart ### Recharts Pattern: - `ResponsiveContainer` for responsive sizing - Custom CSS variable colors (--color-signal-up, --signal-down, etc.) - Tooltip with custom styling - Dark/light theme support via CSS variables --- ## 9. Listing Detail Page Structure ### Route: `app/[locale]/(public)/listings/[id]/page.tsx` - Server component (RSC) for metadata generation - Uses `generateMetadata()` for SEO (Open Graph, canonical URLs) - Fetches listing via `fetchListingById()` - Returns `` for interactivity ### Client Component: `components/listings/listing-detail-client.tsx` (39KB) **Core Sections:** 1. **Image Gallery** - `` 2. **KPI Strip** - Trader-style metrics (price, m², DOM, etc.) 3. **Core Details** - Address, bedrooms, furnishing, etc. 4. **Price History Chart** - `` 5. **Neighborhood Section** - Dynamically loaded: - `` (6 categories, 0-10 scores) - `` (POI layer) 6. **AI Advice Cards** - `` with personas 7. **Similar Listings** - Recommendations 8. **Agent Card** - Agent quality score & info 9. **Call-to-Action** - Inquiry modal, comparison, AI estimate ### Key Data Types: ```typescript export interface ListingDetail { id: string; status: ListingStatus; transactionType: 'SALE' | 'RENT'; priceVND: string; property: { title, address, bedrooms, areaM2, media[], ... }; valuationEstimate?: { value, confidence, ... }; neighborhoodScore?: NeighborhoodScoreData; agentQualityScore?: AgentQualityScore; similarListings?: ListingSimilarItem[]; // ... } ``` ### Dynamic Imports (performance): - `NeighborhoodRadarChart` - SSR disabled - `NeighborhoodPOIMap` - SSR disabled + loading fallback --- ## 10. State Management Patterns ### React Query (Server State): - Used for API data fetching & caching - Query keys follow convention pattern - Error boundaries handle failures - Automatic refetch intervals for live data ### Zustand Stores (Client State): - Examples: `auth-store.ts`, `comparison-store.ts`, `preferences-store.ts` - Lightweight, minimal boilerplate - Integrated with localStorage where needed ### Context (Theme, Notifications): - `ThemeProvider` (via next-themes) - `QueryProvider` (React Query) - `NotificationsProvider` - `AuthProvider` --- ## 11. Key File Patterns & Conventions ### Naming: - Pages: `page.tsx` in route directories - Layouts: `layout.tsx` - Components: PascalCase with domain prefix (e.g., `NeighborhoodPOIMap`) - API modules: `*-api.ts` for client-side, `*-server.ts` for server-side - Hooks: `use-*` pattern - Types: inline in files or `types.ts` per domain ### File Organization: - Domain-based (listings/, neighborhood/, khu-cong-nghiep/) - Shared utilities in `/lib` and `/components/design-system` - Barrel exports with `index.ts` for easy importing ### Code Structure: - 'use client' at top of client components - TypeScript strict mode - Props interfaces above component functions - Sub-components extracted for readability - Helpers defined near top-level components --- ## 12. Performance & SEO ### SEO: - Server-side metadata generation with `generateMetadata()` - JSON-LD schema generation (`components/seo/json-ld.tsx`) - Open Graph + canonical URLs - Multi-language support (vi/en) ### Performance: - Dynamic imports with code splitting (e.g., maps, heavy charts) - Lazy-loading fallbacks - Image optimization (Next.js Image component) - CSS-in-JS via Tailwind + CVA - Responsive containers for charts/maps ### Internationalization: - `next-intl` for translations - Route segments by locale: `[locale]/` - Translations in `/messages` directory --- ## Summary Table | Aspect | Technology | Key Files | |--------|-----------|-----------| | **Mapping** | Mapbox GL 3.21.0 | `components/map/`, `lib/mapbox-style.ts` | | **Charts** | Recharts 3.8.1 | `components/charts/`, `components/neighborhood/neighborhood-radar-chart.tsx` | | **API Client** | Fetch + CSRF | `lib/api-client.ts`, `lib/*-api.ts` | | **State (Server)** | React Query 5.96.2 | `lib/query-client.ts`, `lib/hooks/` | | **State (Client)** | Zustand 5.0.12 | `lib/*-store.ts` | | **Forms** | react-hook-form + Zod | `lib/validations/` | | **UI** | Tailwind + CVA | `components/design-system/`, `components/ui/` | | **Routing** | Next.js App Router | `app/[locale]/` | | **i18n** | next-intl | `/messages/`, route `[locale]/` |