# NexDirectory Scanner (Chrome Extension)

Comprehensive documentation for the `event-plugin-wp-scanner` extension.

## Table of Contents

- [1. Overview](#1-overview)
- [2. Core Features](#2-core-features)
- [3. How It Works (Architecture)](#3-how-it-works-architecture)
- [4. Requirements](#4-requirements)
- [5. Installation (Chrome)](#5-installation-chrome)
- [6. WordPress Setup (NexDirectory)](#6-wordpress-setup-nexdirectory)
- [7. Extension Setup](#7-extension-setup)
- [8. Quick Start](#8-quick-start)
- [9. Workflows](#9-workflows)
- [10. Settings Reference](#10-settings-reference)
- [11. Field Coverage](#11-field-coverage)
- [12. Security Model](#12-security-model)
- [13. REST API Reference](#13-rest-api-reference)
- [14. Logs and Diagnostics](#14-logs-and-diagnostics)
- [15. Troubleshooting](#15-troubleshooting)
- [16. Best Practices](#16-best-practices)
- [17. FAQ](#17-faq)
- [18. File Map](#18-file-map)

## 1. Overview

NexDirectory Scanner is a Chrome side-panel extension that helps you extract event/listing data from web pages and import it directly into NexDirectory.

Button Importer documentation: [https://nexdirectory.com/importer](https://nexdirectory.com/importer)

Primary use cases:

- Import a single event from a source page in minutes.
- Run bulk imports from a URL list.
- Keep imports aligned with your plugin defaults (status, media policy, content mode).
- Optionally use AI extraction and translation.

## 2. Core Features

### Scan tab

- Scans current page content and metadata.
- Extracts title, dates, venue, description, media URLs, contact fields, and more.
- Supports required import fields (`title` and `start`).
- Supports dynamic custom/form fields returned by your plugin.

### Bulk tab

- Paste one URL per line.
- Processes sequentially (open -> scan -> import).
- Tracks progress, successes, and failures.
- Supports optional non-English -> English translation.

### Settings tab

- Connect to WordPress via site URL + Extension App Pass.
- Configure AI model and API key.
- Set defaults for import status, media policy, and content mode.
- Configure behavior toggles, timeout, and retry policy.

### Logs tab

- Local extension log viewer with copy/clear.
- Useful for support and debugging.

### Help tab

- In-panel setup reminders and doc link.

## 3. How It Works (Architecture)

Extension components:

- `sidepanel.js`
  - UI interactions, draft handling, settings persistence, modal flow.
- `background.js`
  - API calls, request signing, OpenAI calls, bulk job state, log pipeline.

NexDirectory backend endpoints:

- `POST /wp-json/eep/v1/extension/ping`
- `POST /wp-json/eep/v1/extension/import`
- `POST /wp-json/eep/v1/extension/preferences`

High-level flow:

1. Extension sends `ping` to validate connection and fetch capabilities/schema.
2. Extension scans current page (heuristics and optionally AI extraction).
3. User reviews/edits fields.
4. Extension sends signed `import` payload.
5. Plugin validates, enforces policy, creates/imports listing, and returns links/IDs.

## 4. Requirements

- Chrome with Manifest V3 support.
- NexDirectory plugin installed and active on WordPress site.
- Extension Connector enabled in NexDirectory settings.
- Extension App Pass generated and copied to the extension.
- Optional: OpenAI API key for AI extraction/translation.

## 5. Installation (Chrome)

1. Open `chrome://extensions/`.
2. Enable **Developer mode**.
3. Click **Load unpacked**.
4. Select:
   - `chrome-extension/event-plugin-wp-scanner`
5. Pin the extension (recommended).
6. Open the side panel via extension icon.

## 6. WordPress Setup (NexDirectory)

In WordPress admin, go to NexDirectory settings and open the **Advanced > Chrome Extension** area.

Configure:

1. Enable **Chrome Extension Connector** (`eep_extension_enabled = 1`).
2. Copy **Extension App Pass** into the extension settings.
3. Set defaults:
   - Default import status (`draft` or `publish`)
   - Media upload policy (`none`, `images`, `video`, `images_video`)
   - Imported text mode (`rewrite`, `verbatim`)
   - Imported listing owner
   - Mark imported listings as claimable
   - Notify potential owner default
   - Optional auto-generated disclaimer text

Important:

- If you regenerate App Pass, every connected extension must be updated.
- Extension endpoints are shown in this settings section for verification.

## 7. Extension Setup

In the extension **Settings** tab:

1. Set **Plugin Site URL** (example: `https://yourdomain.com`).
2. Paste **Extension App Pass**.
3. Optional: add OpenAI key and model (default `gpt-5.2`).
4. Click **Test Connection**.
5. Optional: click **Test OpenAI**.
6. Click **Save Settings**.

If connection test succeeds, schemas/defaults from your site become available to the extension.

## 8. Quick Start

### A. Single import (fast path)

1. Open source webpage.
2. Open extension -> **Scan** tab.
3. Click **Scan Page**.
4. Verify title/start and any key fields.
5. Click **Import Event**.
6. Open created listing using returned link.

### B. Bulk import

1. Open extension -> **Bulk** tab.
2. Paste URLs (1 per line).
3. Optional: enable translation toggle.
4. Click **Start Bulk Import**.
5. Monitor progress and review result rows.

## 9. Workflows

### 9.1 Single page scan/import workflow

- `Scan Page` collects raw page text and metadata.
- Heuristic parser and optional AI extraction build structured event data.
- You can edit all extracted values before import.
- If notify-owner setting is enabled, modal asks for per-import email decision.
- `Import Event` sends signed payload to plugin endpoint.

### 9.2 Bulk workflow

- URL list is normalized (trimmed, deduplicated, validated).
- Background worker processes each URL sequentially.
- Each URL gets scanned + imported with current defaults.
- Progress panel shows:
  - processed / total
  - success / failed
  - active URL
  - per-item result details

### 9.3 Dynamic fields workflow

The extension can render dynamic field inputs from plugin schema returned by `ping`:

- custom fields
- form fields
- submit fields
- extension-specific core meta keys

Use **Refresh Custom Fields** and **Refresh Form Fields** after changing schema server-side.

## 10. Settings Reference

| Setting | Default | Purpose |
|---|---:|---|
| `pluginBaseUrl` | empty | WordPress site base URL |
| `appPass` | empty | Shared secret for extension auth |
| `openaiApiKey` | empty | Enables AI extraction/translation |
| `openaiModel` | `gpt-5.2` | Model used for OpenAI calls |
| `importStatusDefault` | `draft` | Imported post status default |
| `importMediaPolicy` | `none` | Controls cover/gallery/video ingestion |
| `importContentMode` | `rewrite` | `rewrite` or `verbatim` behavior |
| `useAiByDefault` | `on` | AI extraction on scan by default |
| `autoOpenImportedEvent` | `on` | Open result URL after successful import |
| `rememberDraft` | `on` | Persist scan form values locally |
| `notifyPotentialOwner` | `off` | Prompt/email notify potential owner |
| `bulkTranslateNonEnglish` | `off` | Translate non-English bulk sources |
| `verboseLogs` | `off` | More detailed log output |
| `requestTimeoutSeconds` | `25` | API timeout per request (range 5-120) |
| `retryAttempts` | `1` | Retry count (range 0-3) |

## 11. Field Coverage

The scan/import form covers a wide range of listing data.

Core examples:

- `title`, `start`, `end`, `timezone`
- `excerpt`, `description`
- `meta_title`, `meta_description`
- `venue`, `address`, `city`, `country`
- `event_type`, `event_mode`, `event_price_range`, `event_tags`
- `capacity`, `price`, `ticket_sales_enabled`, `ticket_price`, `ticket_button_label`
- `contact_name`, `contact_email`, `contact_phone`
- `cover_image_url`, `gallery_urls[]`, `video_urls[]`, `supporting_docs_urls[]`
- `sessions[]` JSON
- `key_speakers[]` JSON
- `recurrence`, `recurrence_until`

Import requirements:

- `title` and `start` are required.

## 12. Security Model

Authentication and integrity are handled with custom headers and HMAC signing.

### Headers used

- `X-EEP-App-Pass`
- `X-EEP-Timestamp`
- `X-EEP-Signature`

Signature input:

- message: `"<timestamp>.<raw_json_body>"`
- algorithm: `HMAC-SHA256`
- key: `appPass`

### Server-side checks

- Connector must be enabled.
- App Pass must match saved value.
- Signature required for `/extension/import` and `/extension/preferences`.
- Timestamp window must be valid (clock skew protected).
- Signature must match the exact request body.

### Security recommendations

- Treat App Pass like a password.
- Regenerate immediately if leaked.
- Keep user/device clocks correct.
- Prefer HTTPS only.

## 13. REST API Reference

### 13.1 `POST /wp-json/eep/v1/extension/ping`

Purpose:

- Connection handshake.
- Returns defaults, capabilities, and dynamic schema.

Typical outputs include:

- plugin/site identity
- extension defaults
- feature flags (duplicate detection, claims, etc.)
- dynamic custom/form fields

### 13.2 `POST /wp-json/eep/v1/extension/preferences`

Purpose:

- Sync selected extension defaults to plugin options.

Common fields:

- `import_status`
- `media_upload_policy`
- `notify_potential_owner_default`
- `content_mode`

### 13.3 `POST /wp-json/eep/v1/extension/import`

Purpose:

- Create/import listing from extension payload.

Behavior highlights:

- Validates required fields.
- Enforces media policy.
- Applies content mode logic.
- Runs duplicate checks if enabled.
- Applies claimable/default ownership metadata.
- Optionally sends owner notification email.

Typical success response:

- `post_id`
- `status`
- `permalink`
- `edit_url`
- flags/details about duplicate handling/import state

## 14. Logs and Diagnostics

### Extension logs (local)

- Available in **Logs** tab.
- Can refresh, copy, and clear.
- Useful for diagnosing:
  - connection errors
  - AI call errors
  - bulk failures
  - import response problems

### Plugin-side runtime logs

NexDirectory runtime logging may also include:

- invalid credentials/signature events
- import created/skipped details
- app-pass regeneration events
- owner-notification send/failure events

## 15. Troubleshooting

### Test Connection fails

- Verify `Plugin Site URL` includes protocol (`https://...`).
- Ensure connector is enabled in WordPress settings.
- Check App Pass value (copy fresh if needed).

### Invalid credentials/signature

- Confirm App Pass exactly matches WordPress setting.
- Ensure request time is accurate on local machine.
- Re-save settings and retry.

### Import fails: missing title/start

- Edit fields manually before import.
- Re-run scan and verify source page actually contains start date.

### OpenAI test fails

- Check API key and model.
- Confirm outbound network access.
- Increase timeout if needed.

### Bulk import appears stuck

- Check browser tab permissions/navigation restrictions.
- Inspect Logs tab for current URL error.
- Stop and restart with a smaller URL set.

### Notify owner email not delivered

- Verify recipient email in modal/settings.
- Verify WordPress email delivery (SMTP/wp_mail).

## 16. Best Practices

- Use `draft` status for QA-first import workflow.
- Keep duplicate detection enabled in plugin settings.
- Review first few imports before running large bulk batches.
- Use `verbatim` if source text fidelity matters.
- Use `rewrite` only when server-side AI is configured and desired.
- Keep timeout/retry conservative unless network is unstable.

## 17. FAQ

### Does this require OpenAI?

No. Scanning works without OpenAI using heuristic extraction. AI improves structure/quality.

### Can I use this across multiple WordPress sites?

Yes. Update `Plugin Site URL` and `App Pass` for the target site.

### What happens if I regenerate App Pass?

Existing extension credentials become invalid immediately. Re-paste new pass in extension settings.

### Where do imported events go?

They are created in your NexDirectory event/listing post type per plugin defaults.

### Can I notify ownership contacts only for some imports?

Yes. Enable notify setting, then decide per import in the modal before submission.

## 18. File Map

- `manifest.json` - extension manifest (MV3)
- `sidepanel.html` - side panel UI
- `sidepanel.css` - panel styling
- `sidepanel.js` - panel interactions, settings, draft, import actions
- `background.js` - service worker, API calls, signing, bulk engine, logs
- `images/` - extension assets/icons

---

If you want a second document for non-technical clients (short onboarding only), create `USER-QUICKSTART.md` and keep this README as the technical reference.
