WP Manifestindependent plugin directory
manifest / forms / find-my-rep-plugin

Find My Rep

A WordPress plugin that will search for your local representative and provide a templated letter to send via email service

★ 0stars

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/bones5/find-my-rep-plugin/archive/refs/heads/main.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

A WordPress plugin that creates a Gutenberg block for contacting local representatives via templated letters sent through Resend.

Plugin Frontend Preview

Features

  • Gutenberg Block: Easy-to-use block that can be inserted on any page
  • Representative Lookup: Search for local representatives by postcode via API
  • Multiple Representative Types: Supports MPs, MSs, local councillors, and PCCs
  • Customizable Campaigns: Per-block recipients, an optional question, and an editable letter template
  • Multi-recipient: Editors choose which representative types each block contacts
  • Email Integration: Sends letters via Resend API
  • Abuse Protection: Blocks abusive language, excessive link spam, and repeated rapid submissions
  • Sender Confirmation: Requires users to confirm they are personally sending the message

Installation

  1. Upload the plugin folder to /wp-content/plugins/find-my-rep-plugin/
  2. Activate the plugin through the 'Plugins' menu in WordPress
  3. Configure the plugin settings under Settings > Find My Rep

Configuration

Admin Settings

Navigate to Settings > Find My Rep to configure:

  1. Representatives API URL: Enter the API endpoint that returns representative data based on postcode

    • The API should accept a postcode query parameter
    • Should return JSON with representative details including: name, email, title or type
  2. Resend API Key: Enter your Resend API key for sending emails

  3. Letter Template: Define the default letter template

    • Use {{representative_name}} as a placeholder for the representative's name
    • Use {{representative_title}} as a placeholder for the representative's title
  • Use {{question_response}} wherever the optional visitor response should appear
  1. Test Postcode: Configure a postcode handled entirely by the plugin without calling the representatives API
  • Set the postcode to use for testing, such as ZZ999ZZ
  • Enter separate email addresses for the generated test MP, MS, PCC, and councillor
  • Each populated email creates one representative of that type with the required fields filled with test information
  • Leave a representative email blank to omit that type from the test results

Example Letter Template

Dear {{representative_name}},

I am writing to you as your constituent regarding [issue].

[Your message here]

I would appreciate your support on this matter.

Sincerely,
[User's name will be added automatically]

Usage

Adding the Block

  1. Edit any page or post
  2. Click the '+' button to add a new block
  3. Search for "Find My Rep Contact Form"
  4. Insert the block
  5. In the block, choose the representative types to contact, optionally add a required question prompt, and customize the letter template

User Experience

  1. Enter Postcode: Users enter their postcode to find representatives
  2. Answer Question: Optionally answer the campaign question when the editor has enabled one
  3. Edit Letter: Review and customize the letter template
  4. Send: Submit to all representative types configured for the block

Development

Technology Stack

  • TypeScript: Type-safe development with full type definitions
  • React: Modern component-based UI framework
  • WordPress Blocks API: Gutenberg block integration
  • @wordpress/scripts: Build tooling and linting

Requirements

  • Node.js and npm
  • WordPress 5.0+
  • PHP 7.0+
  • Docker (for running wp-env)

Building from Source

The plugin is written in TypeScript and React. To build:

npm install
npm run build

This compiles TypeScript/React code to JavaScript bundles in the build/ directory.

Creating a Plugin Release

package.json is the canonical plugin version. To increment it, synchronize the WordPress plugin header and constant, build the assets, and create an installable ZIP in one command:

npm run release -- patch

Use minor, major, or an exact version such as 1.2.3 instead of patch when needed. The command updates package.json and package-lock.json, then creates dist/find-my-rep-plugin-<version>.zip. It does not create a Git commit or tag.

To rebuild a ZIP without changing the version:

npm run package

Upload the ZIP through Plugins > Add Plugin > Upload Plugin in WordPress and confirm replacing the existing plugin. Review and commit the version changes, then create a matching Git tag after testing the ZIP.

Development Mode

For hot-reloading during development:

npm start

Code Architecture

The plugin follows a modern React/TypeScript architecture:

Source Files (src/):

  • index.tsx - Gutenberg block registration (editor view)
  • frontend.tsx - Frontend React app initialization
  • types.ts - TypeScript type definitions
  • components/ - React components for the frontend UI
    • FindMyRepApp.tsx - Main app container with state management
    • PostcodeStep.tsx - Postcode input step
    • QuestionStep.tsx - Optional campaign question step
    • LetterStep.tsx - Letter editing and submission step
    • LoadingSpinner.tsx - Loading indicator component

Build Output (build/):

  • index.tsx.js - Compiled block editor script
  • frontend.tsx.js - Compiled frontend React app
  • *.asset.php - WordPress asset files with dependencies
  • style.css - Plugin styles

Linting and Formatting

Run linting checks:

npm run lint:js

Auto-fix linting issues:

npm run lint:js -- --fix

Email Transport Modes

The plugin supports multiple email transport modes for development and production:

  1. Resend API (default for production): Uses the Resend API to send emails
  2. SMTP (wp_mail): Uses WordPress's built-in wp_mail() function (useful with MailHog for local development)
  3. Test (Log to File): Logs emails to a file for testing without sending (stored in wp-content/uploads/find-my-rep-test-mails.log)

Configure the transport mode in Settings > Find My Rep > Email Transport.

For local development with MailHog, see docs/MAILHOG-DEV.md.

Testing

The plugin includes three types of tests:

PHPUnit Tests

Run PHP unit tests for the email service:

npm run test:phpunit
# or directly: vendor/bin/phpunit

Tests include:

  • Template rendering and placeholder replacement
  • Email transport behavior (resend, smtp, test)
  • Error handling and edge cases

Jest Tests

Run React component tests:

npm run test:jest

Tests include:

  • LetterStep component validation
  • User interaction flows
  • Button states and loading indicators

E2E Tests (Playwright)

Run end-to-end tests using wp-env and Playwright.

Setup

  1. Install dependencies:
npm install
  1. Install Playwright browsers:
npx playwright install

Running Tests

  1. Start the WordPress environment:
npm run env:start
  1. Run the tests:
npm run test:e2e
  1. Run tests in headed mode (see browser):
npm run test:e2e:headed
  1. Debug tests:
npm run test:e2e:debug
  1. Stop the WordPress environment when done:
npm run env:stop

Other wp-env Commands

  • Clean all data: npm run env:clean
  • Access WordPress at: http://localhost:8888
  • Admin credentials: admin / password

API Response Format

The Representatives API should return data in the following format:

{
  "postcode": "CF10 1EP",
  "councillors": [
    {
      "id": 1,
      "name": "John Smith",
      "party": "Conservative",
      "ward": "St James's",
      "council": "Westminster City Council",
      "email": "john.smith@westminster.gov.uk"
    }
  ],
  "pcc": {
    "id": 1,
    "name": "Sir Mark Rowley",
    "force": "Metropolitan Police",
    "area": "Greater London",
    "email": "mopac@london.gov.uk"
  },
  "mp": {
    "id": 1,
    "name": "Nickie Aiken",
    "party": "Conservative",
    "constituency": "Cities of London and Westminster",
    "email": "nickie.aiken.mp@parliament.uk"
  },
  "mss": [
    {
      "id": 1,
      "name": "Joel James",
      "party": "Conservative",
      "constituency": "Cardiff Central",
      "email": "joel.james@senedd.wales"
    }
  ],
  "areaInfo": {
    "constituency": {
      "id": 65659,
      "name": "Cities of London and Westminster",
      "code": "E14000639"
    },
    "localAuthority": {
      "id": 2247,
      "name": "Westminster",
      "type": "London borough",
      "code": "E09000033"
    },
    "ward": {
      "id": 144393,
      "name": "St James's",
      "type": "London borough ward",
      "code": "E05000644"
    },
    "region": {
      "id": 2247,
      "name": "London",
      "type": "Government Office Region",
      "code": "E12000007"
    }
  }
}

The plugin automatically transforms this response into an internal format for display. Geographic information is extracted from areaInfo and displayed to users before the list of representatives. See API-INTEGRATION.md for detailed documentation.

License

GPL v2 or later