# Database Schema ## Entity Relationship Diagram ``` ┌─────────────────────┐ ┌────────────────────────┐ │ prospects │────<│ prospect_tech_profiles │ ├─────────────────────┤ ├────────────────────────┤ │ id │ │ id │ │ channel │ │ prospect_id (FK) │ │ business_name │ │ cms, server │ │ domain_name │ │ hosting_provider │ │ status │ │ js_framework, cdn │ │ source │ │ analytics │ │ has_website │ │ ecommerce_platform │ │ uses_https │ │ tech_stack_json (JSON) │ │ ... │ └────────────────────────┘ └─────────────────────┘ │ │ ┌──────────────────────────────┐ └──────────────<│ prospect_performance_profiles │ │ ├──────────────────────────────┤ │ │ id │ │ │ prospect_id (FK) │ │ │ performance_score (0-100) │ │ │ accessibility_score │ │ │ seo_score │ │ │ FCP, LCP, TBT, CLS │ │ │ is_mobile_friendly │ │ └──────────────────────────────┘ │ │ ┌───────────────────────┐ └──────────────<│ prospect_scores │ │ ├───────────────────────┤ │ │ id │ │ │ prospect_id (FK) │ │ │ score (0-100) │ │ │ technical_health_score│ │ │ modernity_score │ │ │ business_value_score │ │ │ engagement_score │ │ │ reason_flags (JSON) │ │ │ lead_tier │ │ └───────────────────────┘ │ │ ┌───────────────────────┐ └──────────────<│ prospect_contacts │ │ ├───────────────────────┤ │ │ id │ │ │ prospect_id (FK) │ │ │ contact_type │ │ │ value │ │ │ source_url │ │ │ is_primary │ │ └───────────────────────┘ │ │ ┌───────────────────────┐ └──────────────<│ prospect_interactions │ │ ├───────────────────────┤ │ │ id │ │ │ prospect_id (FK) │ │ │ interaction_type │ │ │ subject, notes │ │ │ outcome │ │ │ next_action │ │ │ next_action_date │ │ │ created_by_user_id │ │ └───────────────────────┘ │ │ ┌───────────────────────┐ └──────────────<│ prospect_scan_jobs │ ├───────────────────────┤ │ id │ │ job_type │ │ status │ │ total_items │ │ processed_items │ │ celery_task_id │ └───────────────────────┘ ┌──────────────────────┐ ┌──────────────────┐ │ campaign_templates │────<│ campaign_sends │ ├──────────────────────┤ ├──────────────────┤ │ id │ │ id │ │ name │ │ template_id (FK) │ │ lead_type │ │ prospect_id (FK) │ │ channel │ │ channel │ │ language │ │ rendered_subject │ │ subject_template │ │ rendered_body │ │ body_template │ │ status │ │ is_active │ │ sent_at │ └──────────────────────┘ │ sent_by_user_id │ └──────────────────┘ ``` ## Tables ### prospects Central table for all leads — both digital (domain-based) and offline (in-person). | Column | Type | Description | |--------|------|-------------| | id | INTEGER PK | Auto-increment | | channel | ENUM(digital, offline) | How the lead was discovered | | business_name | VARCHAR(255) | Required for offline | | domain_name | VARCHAR(255) | Required for digital, unique | | status | ENUM | pending, active, inactive, parked, error, contacted, converted | | source | VARCHAR(100) | e.g. "domain_scan", "networking_event", "street" | | has_website | BOOLEAN | Determined by HTTP check | | uses_https | BOOLEAN | SSL status | | http_status_code | INTEGER | Last HTTP response | | address | VARCHAR(500) | Physical address (offline) | | city | VARCHAR(100) | City | | postal_code | VARCHAR(10) | Postal code | | country | VARCHAR(2) | Default "LU" | | notes | TEXT | Free-form notes | | tags | JSON | Flexible tagging | | captured_by_user_id | INTEGER FK | Who captured this lead | | location_lat / location_lng | FLOAT | GPS from mobile capture | | last_*_at | DATETIME | Timestamps for each scan type | ### prospect_tech_profiles Technology stack detection results. One per prospect. | Column | Type | Description | |--------|------|-------------| | cms | VARCHAR(100) | WordPress, Drupal, Joomla, etc. | | server | VARCHAR(100) | Nginx, Apache | | hosting_provider | VARCHAR(100) | Hosting company | | cdn | VARCHAR(100) | CDN provider | | js_framework | VARCHAR(100) | React, Vue, Angular, jQuery | | analytics | VARCHAR(200) | Google Analytics, Matomo, etc. | | ecommerce_platform | VARCHAR(100) | Shopify, WooCommerce, etc. | | tech_stack_json | JSON | Full detection results | ### prospect_performance_profiles Lighthouse audit results. One per prospect. | Column | Type | Description | |--------|------|-------------| | performance_score | INTEGER | 0-100 | | accessibility_score | INTEGER | 0-100 | | seo_score | INTEGER | 0-100 | | first_contentful_paint_ms | INTEGER | FCP | | largest_contentful_paint_ms | INTEGER | LCP | | total_blocking_time_ms | INTEGER | TBT | | cumulative_layout_shift | FLOAT | CLS | | is_mobile_friendly | BOOLEAN | Mobile test | ### prospect_scores Calculated opportunity scores. One per prospect. See [scoring.md](scoring.md) for algorithm details. ### prospect_contacts Scraped or manually entered contact info. Many per prospect. ### prospect_interactions CRM-style interaction log. Many per prospect. Types: note, call, email_sent, email_received, meeting, visit, sms, proposal_sent. ### prospect_scan_jobs Background job tracking for batch operations. ### campaign_templates / campaign_sends Marketing campaign templates and send tracking. Templates support placeholders like `{business_name}`, `{domain}`, `{score}`, `{issues}`.