17 KiB

BNKops Influence Campaign Tool

A comprehensive web application that helps Alberta residents connect with their elected representatives across all levels of government. Users can find their representatives by postal code and send direct emails to advocate for important issues.

Features

  • Representative Lookup: Find elected officials by Alberta postal code (T prefixed)
  • Multi-Level Government: Displays federal MPs, provincial MLAs, and municipal representatives
  • Contact Information: Shows photos, email addresses, phone numbers, and office locations
  • Direct Email: Built-in email composer to contact representatives
  • Campaign Management: Create and manage advocacy campaigns with customizable settings
  • Public Campaigns Grid: Homepage display of all active campaigns for easy discovery and participation
  • Response Wall: Community-driven platform for sharing and voting on representative responses
  • Email Count Display: Optional engagement metrics showing total emails sent per campaign
  • Smart Caching: Fast performance with NocoDB caching and graceful fallback to live API
  • Responsive Design: Works seamlessly on desktop and mobile devices
  • Real-time Data: Integrates with Represent OpenNorth API for up-to-date information

Technology Stack

  • Backend: Node.js with Express.js
  • Database: NocoDB (REST API)
  • External API: Represent OpenNorth Canada API
  • Frontend: Vanilla JavaScript, HTML5, CSS3
  • Email: SMTP integration
  • Deployment: Docker with docker-compose
  • Rate Limiting: Express rate limiter for API protection

Quick Start

Prerequisites

  • Docker and Docker Compose
  • Access to existing NocoDB instance
  • SMTP email configuration

Installation

  1. Clone and navigate to the project:

    cd /path/to/changemaker.lite/influence
    
  2. Configure environment:

    cp .env.example .env
    # Edit .env with your configuration
    
  3. Set up NocoDB tables:

    ./scripts/build-nocodb.sh
    
  4. Start the application:

    docker compose up --build
    
  5. Access the application:

    • Open http://localhost:3333
    • Enter an Alberta postal code (e.g., T5N4B8)
    • View your representatives and send emails

Development Mode

Email Testing with MailHog

For development and testing, the application includes MailHog integration to safely test email functionality without sending real emails to elected officials.

Quick Setup for Development

  1. Use development configuration:

    # Your .env should include these settings for development:
    NODE_ENV=development
    EMAIL_TEST_MODE=true
    SMTP_HOST=mailhog
    SMTP_PORT=1025
    SMTP_USER=test
    SMTP_PASS=test
    TEST_EMAIL_RECIPIENT=your-email@example.com
    
  2. Start with MailHog included:

    docker compose up --build
    
  3. Access development tools:

Email Testing Features

Test Mode Benefits:

  • All emails redirected to your test recipient
  • Original recipient shown in subject line: [TEST - Original: real@email.com] Subject
  • Safe testing without spamming elected officials
  • Complete email logging with test mode indicators

Email Testing Interface (/email-test.html):

  • Quick Test: Send test email with one click
  • Email Preview: See exactly how emails will look before sending
  • Custom Composition: Test with your own subject and message content
  • Email Logs: View all sent emails with test/live filtering
  • SMTP Diagnostics: Test connection and troubleshoot issues

MailHog Web Interface (http://localhost:8025):

  • View all emails caught during development
  • Inspect email content, headers, and formatting
  • Search and filter caught emails
  • No emails leave your local environment

Development Workflow

  1. Safe Development:

    # Ensure test mode is enabled
    EMAIL_TEST_MODE=true
    
    # Start development environment
    docker compose up --build
    
  2. Test Email Functionality:

    • Use the main app to send emails (they'll be redirected)
    • Check MailHog UI to see the actual email content
    • Use /email-test.html for advanced testing and preview
  3. Production Deployment:

    # Switch to production SMTP settings
    EMAIL_TEST_MODE=false
    SMTP_HOST=smtp.your-provider.com
    SMTP_USER=your-real-email@domain.com
    SMTP_PASS=your-real-password
    
    # Restart application
    docker compose restart
    

Development Environment Variables

# Development Mode Configuration
NODE_ENV=development
EMAIL_TEST_MODE=true

# MailHog SMTP (for development)
SMTP_HOST=mailhog
SMTP_PORT=1025
SMTP_SECURE=false
SMTP_USER=test
SMTP_PASS=test
SMTP_FROM_EMAIL=dev@albertainfluence.local
SMTP_FROM_NAME="BNKops Influence Campaign (DEV)"

# Email Testing
TEST_EMAIL_RECIPIENT=developer@example.com

# Production SMTP (commented out for dev)
# SMTP_HOST=smtp.protonmail.ch
# SMTP_PORT=587
# SMTP_USER=your-production-email@domain.com
# SMTP_PASS=your-production-password

Configuration

Environment Variables (.env)

# Server Configuration
NODE_ENV=production
PORT=3333

# NocoDB Configuration
NOCODB_API_URL=https://db.cmlite.org
NOCODB_API_TOKEN=your_nocodb_token
NOCODB_PROJECT_ID=your_project_id

# Email Configuration (SMTP)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=your_email@gmail.com
SMTP_PASS=your_app_password
SMTP_FROM_NAME=BNKops Influence Campaign
SMTP_FROM_EMAIL=your_email@gmail.com

# Rate Limiting
RATE_LIMIT_WINDOW_MS=900000
RATE_LIMIT_MAX_REQUESTS=100

Campaign Management Guide

Creating a Campaign

  1. Access Admin Panel: Navigate to /admin.html and log in with admin credentials

  2. Create New Campaign: Click "Create Campaign" button

  3. Configure Basic Settings:

    • Campaign Title: Short, descriptive name (becomes the URL slug)
    • Description: Brief overview shown on the campaign landing page
    • Call to Action: Motivational message encouraging participation
  4. Set Email Template:

    • Email Subject: Pre-filled subject line for emails
    • Email Body: Default message template (users may edit if allowed)
  5. Upload Cover Photo (Optional):

    • Click "Choose File" to upload a hero image
    • Supported formats: JPEG, PNG, GIF, WebP
    • Maximum size: 5MB
    • Image displays as campaign page banner
  6. Configure Campaign Settings:

    • 📧 Allow SMTP Email: Enable server-side email sending
    • 🔗 Allow Mailto Link: Enable browser-based mailto: links
    • 👤 Collect User Info: Request user name and email
    • 📊 Show Email Count: Display total emails sent (engagement metric)
    • ✏️ Allow Email Editing: Let users customize email template
    • 🎯 Target Government Levels: Select Federal, Provincial, Municipal, School Board
  7. Set Campaign Status:

    • Draft: Hidden from public, testing mode
    • Active: Visible to public on main page
    • Paused: Temporarily disabled
    • Archived: Completed campaigns
  8. Save Campaign: Click "Create Campaign" to publish

Public Campaigns Display

The homepage automatically displays all active campaigns in a responsive grid below the representative lookup section.

Features:

  • Automatic Display: Only active campaigns (status="active") are shown publicly
  • Campaign Cards: Each campaign displays as an attractive card with:
    • Cover photo (if uploaded) or gradient background
    • Campaign title and truncated description
    • Target government level badges (Federal, Provincial, Municipal, etc.)
    • Email count badge (if enabled via campaign settings)
    • "Learn More & Participate" call-to-action
  • Responsive Grid: Automatically adjusts columns based on screen size
    • Desktop: 3-4 columns
    • Tablet: 2 columns
    • Mobile: 1 column
  • Click Navigation: Users can click any campaign card to visit the full campaign page
  • Smart Loading: Shows loading state while fetching campaigns, gracefully hides section if no active campaigns exist
  • Security: HTML content is escaped to prevent XSS attacks
  • Sorting: Campaigns display newest first by creation date

Public API Endpoint: /api/public/campaigns (no authentication required)

  • Returns only campaigns with status='active'
  • Includes email counts when show_email_count=true
  • Optimized for performance with minimal data transfer

Email Count Display Feature

The Show Email Count setting controls whether campaign pages display total engagement metrics.

When Enabled ( checked):

  • Campaign page shows: "X Albertans have sent emails through this campaign"
  • Provides social proof and encourages participation
  • Updates in real-time as users send emails
  • Displays prominently above the call-to-action

When Disabled ( unchecked):

  • Email count section is hidden
  • Useful for sensitive campaigns or privacy concerns
  • Engagement metrics still tracked in admin panel

Best Practices:

  • Enable for public awareness campaigns to show momentum
  • Enable for volunteer recruitment to demonstrate support
  • Disable for personal advocacy or sensitive issues
  • Disable for new campaigns until participation grows

Technical Details:

  • Count includes all successfully sent emails via campaign
  • Tracks both SMTP-sent and mailto-initiated emails (if logged)
  • Admin panel always shows counts regardless of public display setting
  • Database field: show_email_count (checkbox, default: true)

Editing Campaigns

  1. Navigate to Admin Panel → "Campaigns" tab
  2. Find campaign card and click "Edit"
  3. Modify any settings including the email count display toggle
  4. Save changes - updates apply immediately to public-facing page

Campaign Analytics

Access campaign performance metrics in the Admin Panel:

  • Total emails sent per campaign
  • User participation rates
  • Email delivery status
  • Representative contact distribution

API Endpoints

Representatives

  • GET /api/representatives/by-postal/:postalCode - Get representatives by postal code
  • POST /api/representatives/refresh-postal/:postalCode - Refresh cached data

Email

  • POST /api/emails/send - Send email to representative
  • GET /api/emails/logs - Get email sending logs (with filters)

Email Testing (Development)

  • POST /api/emails/preview - Preview email without sending (admin only)
  • POST /api/emails/test - Send test email to configured recipient (admin only)
  • GET /api/test-smtp - Test SMTP connection (admin only)

Health

  • GET /api/health - Application health check
  • GET /api/test-represent - Test Represent API connection

Database Schema

Campaigns Table

  • slug, title, description
  • email_subject, email_body
  • call_to_action, cover_photo
  • status (draft/active/paused/archived)
  • allow_smtp_email, allow_mailto_link
  • collect_user_info, show_email_count
  • allow_email_editing
  • target_government_levels (MultiSelect)
  • created_by_user_id, created_by_user_email, created_by_user_name

Campaign Emails Table

  • campaign_id, user_name, user_email, user_postal_code
  • recipient_name, recipient_email, recipient_level
  • subject, message, status, sent_at

Representatives Table

  • postal_code, name, email, district_name
  • elected_office, party_name, representative_set_name
  • url, photo_url, cached_at

Email Logs Table

  • recipient_email, recipient_name, sender_email
  • subject, message, status, sent_at

Postal Codes Table

  • postal_code, city, province
  • centroid_lat, centroid_lng, last_updated

Users Table

  • email, password_hash, name
  • role (admin/user), status (active/temporary)
  • expires_at, last_login

Development

Project Structure

influence/
├── app/
│   ├── controllers/     # Business logic
│   ├── routes/         # API routes
│   ├── services/       # External integrations
│   ├── utils/          # Helper functions
│   ├── middleware/     # Express middleware
│   ├── public/         # Frontend assets
│   └── server.js       # Express app entry point
├── scripts/
│   └── build-nocodb.sh # Database setup
├── docker-compose.yml  # Container orchestration
├── Dockerfile         # Container definition
└── .env              # Environment configuration

Key Components

  • RepresentativesController: Handles postal code lookups and caching
  • EmailController: Manages email composition, sending, and testing
  • NocoDBService: Database operations with error handling
  • RepresentAPI: Integration with OpenNorth Represent API
  • EmailService: SMTP email functionality with test mode support
  • Email Testing System: Preview, test, and log email functionality for development

Features in Detail

Smart Caching System

  • First request fetches from Represent API and caches in NocoDB
  • Subsequent requests served from cache for fast performance
  • Graceful fallback to API when NocoDB is unavailable
  • Automatic error recovery and retry logic

Representative Display

  • Shows photo with fallback to initials
  • Contact information including phone and address
  • Party affiliation and government level
  • Direct links to official profiles

Campaign System

  • Campaign Creation: Create advocacy campaigns with custom titles, descriptions, and email templates
  • Cover Photos: Upload hero images for campaign landing pages (JPEG/PNG/GIF/WebP, max 5MB)
  • Flexible Email Methods: Choose between SMTP email or mailto links for user convenience
  • User Info Collection: Optional name/email collection for campaign tracking
  • Email Count Display: Show total engagement metrics on campaign pages (toggle on/off)
  • Email Editing: Allow users to customize campaign email templates (optional)
  • Target Levels: Select which government levels to target (Federal/Provincial/Municipal/School Board)
  • Campaign Status: Draft, Active, Paused, or Archived workflow states

Response Wall Feature

The Response Wall creates transparency and accountability by allowing campaign participants to share responses they receive from elected representatives.

Key Features:

  • Public Response Sharing: Constituents can post responses received via email, letter, phone, meetings, or social media
  • Community Voting: Upvote system highlights helpful and representative responses
  • Verification System: Admin-moderated verification badges for authentic responses
  • Screenshot Support: Upload visual proof of responses (images up to 5MB)
  • Anonymous Posting: Option to share responses without revealing identity
  • Filtering & Sorting: Filter by government level, sort by recent/upvotes/verified
  • Engagement Statistics: Track total responses, verified count, and community upvotes
  • Moderation Queue: Admin panel for approving, rejecting, or verifying submitted responses
  • Campaign Integration: Response walls linked to specific campaigns for contextualized feedback

Access Response Wall:

  • Via campaign page: Add ?campaign=your-campaign-slug parameter to /response-wall.html
  • Admin moderation: Navigate to "Response Moderation" tab in admin panel
  • Public viewing: All approved responses visible to encourage participation

Moderation Workflow:

  1. Users submit responses with required details (representative name, level, type, response text)
  2. Submissions enter "pending" status in moderation queue
  3. Admins review and approve/reject from admin panel
  4. Approved responses appear on public Response Wall
  5. Admins can mark verified responses with special badge
  6. Community upvotes highlight most impactful responses

Email Integration

  • Modal-based email composer
  • Pre-filled recipient information
  • SMTP sending with delivery confirmation
  • Email history and logging

Error Handling

  • Comprehensive error logging
  • User-friendly error messages
  • API fallback mechanisms
  • Rate limiting protection

Production Deployment

Docker Production

# Build and start in production mode
docker compose -f docker-compose.yml up -d --build

# View logs
docker compose logs -f app

# Scale if needed
docker compose up --scale app=2

Monitoring

  • Health check endpoint: /api/health
  • Application logs via Docker
  • NocoDB integration status monitoring
  • Email delivery tracking

Troubleshooting

Common Issues

  1. NocoDB Connection Errors:

    • Check API URL and token in .env
    • Run ./scripts/build-nocodb.sh to setup tables
    • Application works without NocoDB (API fallback)
  2. Email Not Sending:

    • Verify SMTP credentials in .env
    • Check spam/junk folders
    • Review email logs via API endpoint
    • In development: Check MailHog UI at http://localhost:8025
    • Use email testing interface at /email-test.html for diagnostics
  3. No Representatives Found:

    • Ensure postal code starts with 'T' (Alberta)
    • Check Represent API status
    • Try different postal code format

Log Analysis

# View application logs
docker compose logs app

# Follow logs in real-time
docker compose logs -f app

# Check specific errors
docker compose logs app | grep ERROR

Contributing

This is part of the larger changemaker.lite project. Follow the established patterns for:

  • Error handling and logging
  • API response formats
  • Database integration
  • Frontend component structure

License

Part of the changemaker.lite project ecosystem.