# PROJECT MAP: redesign/frontend (Next.js headless)

## TECH_STACK
- Next.js 16.2.10 (Turbopack disabled), TypeScript, React
- Static export (`output: "export"`) — no server runtime
- WooCommerce REST API for dynamic pricing (fetched at build time)
- WordPress as headless CMS (pages, posts, categories, menus)
- Hosted on GoDaddy (static files + PHP proxy)

## SYSTEM_FLOW
```
Client browser
    ↓
Static HTML (out/*.html)
    ↓
React hydration → "use client" components activate:
  ├── ViewItemTracker → dataLayer.push({event: 'view_item', ecommerce: {items: [...]}})
  ├── LeadSection     → user fills form → POST /submit.php
  ├── Header/Footer   → onClick → dataLayer.push({event: 'navigation', ...})
  ├── Hero/FinalCta   → onClick → dataLayer.push({event: 'cta_click', ...})
  └── GA4 / FB Pixel / Google Ads scripts fire on load

Form submission flow:
  LeadSection (React) → POST /submit.php
    → PHP proxy → WordPress σ/v1/submit-lead endpoint
    → GFAPI::submit_form(21) + duplicate email check
    → Returns {ok, duplicate, entry_id} → React fires lead_submit event
```

## ARCHITECTURE
```
redesign/frontend/
├── app/
│   ├── layout.tsx           # Root layout (GA4, FB Pixel, Google Ads, Organization schema)
│   ├── page.tsx             # Home page (server component, fetches WP)
│   ├── [...slug]/page.tsx   # Catch-all: all WP pages (products, services, comparison, etc.)
│   ├── blog/
│   │   ├── page.tsx         # Blog index — fetches all posts, client-side pagination
│   │   ├── [slug]/page.tsx  # Single blog post — Article schema
│   │   └── category/[slug]/page.tsx  # Category archive
│   └── globals.css          # Global styles
├── components/
│   ├── Tracking.tsx          # ViewItemTracker, trackEvent, trackNav
│   ├── JsonLd.tsx            # Organization, Product, Service, Article, ItemList schemas
│   ├── LeadSection.tsx       # "use client" — form with reCAPTCHA v3
│   ├── Header.tsx            # "use client" — sticky header with dropdowns
│   ├── Footer.tsx            # "use client" — 4-column footer
│   ├── Hero.tsx              # Hero section with CTA + phone
│   ├── FinalCta.tsx          # Bottom CTA section
│   ├── Packages.tsx          # Pricing packages (WooCommerce data)
│   └── icons.tsx             # SVG icon components
├── lib/
│   ├── content.ts            # Type definitions + default content fallback
│   ├── wordpress.ts          # WordPress API fetcher (pages, posts, menus, categories)
│   └── woocommerce.ts        # WooCommerce API client (getProduct, getAllProductSlugs)
├── public/                   # Static assets (img/, submit.php, .htaccess)
├── out/                      # Static export output (deploy this)
├── submit.php                # Production proxy — receives form → forwards to WP
├── .htaccess                 # Redirect rules (301s for old product/canonical URLs)
├── .env.local                # WP URL, WooCommerce keys, reCAPTCHA keys
├── next.config.ts            # trailingSlash: true, output: "export", images unoptimized
├── PROJECT_MAP.md            # This file
├── sigma-submit-endpoint.php # WP plugin (upload to WordPress — v1.1 with duplicate detection)
└── scripts/post-build.ps1    # Renames _next/ → static-assets/ in output
```

## KEY FILES

### Catch-all page (`app/[...slug]/page.tsx`)
- Server component that receives ALL WP page URIs via `generateStaticParams`
- Determines page type by URI: product (sigma-1040-*), service, comparison chart, or regular page
- **Product pages**: fetches WooCommerce price, renders `ProductJsonLd` + `ViewItemTracker`
- **Service pages**: renders `ServiceJsonLd`
- **Comparison chart**: fetches all 3 WooCommerce products, renders `ItemListJsonLd` with prices
- Excludes system pages (`/cart`, `/checkout`, etc.) and non-canonical URLs from static params
- Inline script renders Elementor HTML from WordPress page content

### Layout (`app/layout.tsx`)
- Root layout common to all pages
- Loads GA4 (`G-MVKC1C0G2P`), Google Ads (`AW-979437692`), and Facebook Pixel (`1722841821299879`)
- Renders `OrganizationJsonLd` globally

### Tracking (`components/Tracking.tsx`)
- `ViewItemTracker` — fires `view_item` with `ecommerce.items[]` via `dataLayer.push` (client-side)
- `trackEvent(eventName, params)` — generic event → `dataLayer.push({event, ...params})`
- `trackNav(origin, linkText)` — `dataLayer.push({event: 'navigation', nav_item, nav_name})`

### Tracking events supported
| Event | Where | Fields |
|---|---|---|
| `view_item` | Product pages (via ViewItemTracker) | `ecommerce: {currency, items: [{item_id, item_name, price, category}]}` |
| `navigation` | Header.tsx, Footer.tsx (nav links) | `nav_item: "Header"|"Footer"`, `nav_name: string` |
| `cta_click` | Hero, FinalCta, Packages, Header phone/cta | `click_text`, `click_url` |
| `form_start` | LeadSection.tsx (on first field focus) | `form_name: "Home Form" \| document.title` |
| `form_submit` | LeadSection.tsx (on submit response) | `form_name: lead.formTitle`, `status`, `message` |
| `lead_submit` | LeadSection.tsx (success only) | `entry_id`, `is_duplicate: boolean` |

### JsonLd (`components/JsonLd.tsx`)
- `OrganizationJsonLd` — global schema in layout
- `ProductJsonLd` — individual product pages (name, description, sku, price, image)
- `ServiceJsonLd` — service pages (name, description)
- `ArticleJsonLd` — blog posts (headline, description, datePublished, author)
- `ItemListJsonLd` — comparison chart, renders `ListItem > Product > Offer` for each

### LeadSection (`components/LeadSection.tsx`)
- "use client" form: firstName, lastName, company, email, phone, smsConsent
- Loads reCAPTCHA v3 via dynamic script injection
- On submit: POSTs to `/submit.php`, handles `{ok, duplicate, entry_id}` response
- Fires `form_submit` + `lead_submit` on success
- Fires `fbq('track', 'Lead')` + Google Ads conversion on success

### submit.php (`public/submit.php`)
- Standalone PHP proxy (no WordPress dependency)
- reCAPTCHA v3 server-side verification
- POSTs to `dashstp.sigmataxpro.com/wp-json/sigma/v1/submit-lead`
- Returns `{ok, duplicate?, entry_id?, message?}` to frontend
- Handles mixed HTML+JSON response from WP (strips GTM script injections)

### WordPress plugin (`sigma-submit-endpoint.php`)
- REST endpoint `sigma/v1/submit-lead`
- Maps fields: firstName→6.3, lastName→6.6, company→5, email→7, phone→8
- Calls `GFAPI::submit_form(21, ...)` then `GFAPI::get_entries` for duplicate email check
- Returns `{ok, duplicate, entry_id}`

### WooCommerce (`lib/woocommerce.ts`)
- `getProduct(slug)` — fetches single product by slug (sale_price / regular_price / price)
- `getAllProductSlugs()` — returns slugs for sigma-1040-* products
- Used at build time by `[...slug]/page.tsx` for pricing data

### Blog (`app/blog/`)
- `page.tsx` — fetches all posts (up to 100), renders grid with client-side pagination (9/page)
- `[slug]/page.tsx` — single post with `ArticleJsonLd`
- `category/[slug]/page.tsx` — category archive filtered by `categories_slug`

### Build constraints
- `output: "export"` — no `generateStaticParams` can return empty arrays (removed `product/[slug]` route)
- Turbopack disabled (`--no-turbo` in build script)
- `next.config.ts`: `images.unoptimized: true`, `trailingSlash: true`

## ENVIRONMENT VARIABLES (`.env.local`)
```
WORDPRESS_URL=https://dashstp.sigmataxpro.com
WORDPRESS_HOME_ID=180
NEXT_PUBLIC_RECAPTCHA_SITE_KEY=6LcdlkotAAAAAKOd6_HIOgxD1Ad5wppDYJATfSpi
RECAPTCHA_SECRET_KEY=6LcdlkotAAAAAFWig82ongsqzW4NWo8uNwzOWN7s
WOOCOMMERCE_CONSUMER_KEY=ck_...
WOOCOMMERCE_CONSUMER_SECRET=cs_...
WOOCOMMERCE_URL=https://dashstp.sigmataxpro.com
```

## BUILD & DEPLOY
```bash
npm run build    # Static export → out/ (runs post-build.ps1 to rename _next/)
npm run dev      # Dev server on localhost:3000
```
Deploy: upload contents of `out/` + `public/.htaccess` + `public/submit.php` to web root.

## PENDING
- Google Ads conversion labels in `LeadSection.tsx:73` — replace `"AW-979437692/form-complete"` with actual labels from legacy snippets
- reCAPTCHA keys may need domain update for production
- Send confirmation email — requires Gravity Forms notification setup in WP admin
- Add `generateStaticParams` for deeper blog pagination if posts exceed 100
- Blog category filter UI
