# CLAUDE.md - City & Business Guides Platform

## Project Overview

**Site:** GranburyGuide.com (first market in City & Business Guides network)  
**Platform:** WordPress + GeoDirectory business directory  
**Purpose:** Automated local media platform combining digital directory, voice AI (IBDA), and print publications  
**Owner:** Steve (solopreneur, 30+ years sales/marketing, GA SF web dev training)

### Core Business Model
- **C2BOI** (Consumer-to-Business Outreach Interception): Free listings show central IBDA number; paid listings show direct numbers
- **Revenue Tiers:** Free → Paid packages with increasing features and visibility
- **Target:** 3,000+ underserved US cities with 10k+ population
- **Goal:** $345K-$485K annual revenue per city at 82-95% margins, 100% automation

---

## Tech Stack

### WordPress Environment
- **WordPress Multisite:** State-based regional networks planned
- **Database Prefix:** `wpnd_`
- **PHP Version:** 8.0+
- **Key Plugins:**
  - GeoDirectory (core directory)
  - GeoDirectory Pricing Manager (packages)
  - GetPaid (payments)
  - ACF Pro (custom fields for menus)
  - UsersWP (user management)

### External Systems
- **VAPI + Twilio + ElevenLabs:** Voice AI (IBDA)
- **n8n:** Automation workflows
- **Apify:** Business data scraping
- **Airtable + Google Sheets:** CRM and analytics

---

## Directory Structure

```
/var/www/granburyguide.com/         # Or wherever WordPress lives
├── wp-content/
│   ├── plugins/
│   │   ├── cgm-directory-setup/    # Our setup automation plugin
│   │   ├── gd-phone-router/        # IBDA call routing
│   │   ├── geodirectory/           # Core directory plugin
│   │   └── geodir_pricing/         # Pricing manager
│   ├── themes/
│   └── uploads/
├── wp-config.php
└── ...
```

### CGM Directory Setup Plugin Structure
```
cgm-directory-setup/
├── cgm-directory-setup.php          # Main plugin (version in header)
├── assets/
│   ├── admin.css
│   └── admin.js
└── includes/
    ├── class-pricing-packages.php   # Step 1: Packages + exclusions
    ├── class-geodirectory-fields.php # Step 2: Custom fields
    ├── class-ibda-fields.php        # Step 3: IBDA tracking fields
    └── class-acf-fields.php         # Step 4: ACF menu structure
```

---

## Database Schema

### Key Tables

| Table | Purpose |
|-------|---------|
| `wpnd_geodir_price` | Pricing packages |
| `wpnd_geodir_pricemeta` | Package metadata (exclude_field, etc.) |
| `wpnd_geodir_custom_fields` | Field definitions per CPT |
| `wpnd_posts` | Listings (gd_place, gd_restaurant, etc.) |
| `wpnd_options` | WordPress options (cgm_package_map, etc.) |

### GeoDirectory Column Quirks
- `days` in docs → Actually `time_interval`
- `is_recurring` in docs → Actually `recurring`
- `is_active` in docs → Actually `status`

### Field Visibility (Two Methods)
1. **Field-level:** `wpnd_geodir_custom_fields.packages` = comma-separated package IDs (empty = all)
2. **Package-level:** `wpnd_geodir_pricemeta.meta_value` where `meta_key = 'exclude_field'` = comma-separated htmlvar_names

---

## Custom Post Types

| CPT | Purpose | Packages |
|-----|---------|----------|
| `gd_place` | General businesses | Standard (free), Featured ($9.99), Sponsor ($19.99) |
| `gd_restaurant` | Restaurants | Silver (free), Gold ($14.99), Platinum ($29.99) |
| `gd_service` | Home services | Free, Silver ($49), Gold ($99), Platinum ($149) |
| `gd_activity` | Things to do | Free only |
| `gd_event` | Events | Free only |
| `gd_job` | Job listings | Free only |

---

## Common Tasks

### Run CGM Setup
```
WordPress Admin → Tools → CGM Directory Setup
Step 1: Create Packages (must run first)
Step 2: Create GD Fields (requires Step 1)
Step 3: Create IBDA Fields
Step 4: Create ACF Fields (requires ACF Pro)
```

### Verify Packages
```sql
SELECT id, post_type, name, amount, time_interval, recurring, status 
FROM wpnd_geodir_price 
ORDER BY post_type, display_order;
```

### Verify Field Exclusions
```sql
SELECT pm.package_id, p.post_type, p.name, pm.meta_value
FROM wpnd_geodir_pricemeta pm
JOIN wpnd_geodir_price p ON pm.package_id = p.id
WHERE pm.meta_key = 'exclude_field'
ORDER BY p.post_type, p.name;
```

### Check Package Map
```sql
SELECT option_value FROM wpnd_options WHERE option_name = 'cgm_package_map';
```

### Debug PHP Errors
```bash
tail -f /path/to/wp-content/debug.log
```

---

## Coding Conventions

### PHP
- WordPress coding standards
- Use `$wpdb->prefix` for table names (resolves to `wpnd_`)
- Escape all SQL with `$wpdb->prepare()`
- Use `sanitize_*` functions for input
- Class-based organization with static methods for setup tasks

### Database Operations
- Always check if table exists before querying
- Use INSERT/UPDATE, not REPLACE (preserves meta_id)
- Clear caches after modifications: `geodir_pricing_clear_cache()`

### Version Numbering
- Plugin version in main file header AND constant
- Update both when making changes
- Use semantic versioning (major.minor.patch)

---

## IBDA Integration

### Package Metadata
Stored in `wp_options` as `cgm_ibda_package_{ID}`:
```php
[
    'phone_disclosed' => bool,    // Show direct number?
    'transfer_type' => string,    // 'warm' or 'blind'
    'voice_priority' => int,      // 1=highest, 4=lowest
    'referrals_allowed' => int    // For free packages
]
```

### GD Phone Router
- Free packages: Display central IBDA number with extension
- Paid packages: Display business's direct number
- Reads IBDA metadata to determine routing behavior

---

## Important References

### Project Documentation (if available locally)
- `complete-pricing-field-mapping.md` - Exact field exclusions per package
- `developer-handoff-v5.md` - Full technical spec
- `system-architecture-v4.md` - Platform architecture
- `pricing-packages-implementation-guide.md` - Package setup details

### GeoDirectory Functions
```php
geodir_custom_field_save($field_data)  // Create/update field
geodir_get_field_infoby('htmlvar_name', $key, $cpt)  // Get field info
geodir_pricing_clear_cache()  // Clear pricing cache
```

---

## Testing Checklist

After modifying packages or fields:

1. [ ] Packages appear in GeoDirectory → Pricing Manager
2. [ ] Package amounts, intervals, recurring settings correct
3. [ ] Exclude Fields populated correctly per package
4. [ ] IBDA metadata saved in wp_options
5. [ ] Custom fields have correct `packages` column values
6. [ ] Add listing form shows correct fields per package tier
7. [ ] Frontend displays correct fields per listing's package

---

## Troubleshooting

### "Table not found" errors
Check prefix - should be `wpnd_`, not `wp_`

### Fields not saving to packages
GeoDirectory may override. Set directly via SQL after using their API.

### Exclusions not appearing in UI
Check `meta_value` format - must be comma-separated htmlvar_names, not IDs.

### Package IDs changed
They're auto-increment. Always reference via `cgm_package_map` option, not hardcoded IDs.

---

## Contact

Project Owner: Steve  
First Market: Granbury, Texas  
Target Launch: March 1, 2026
