Bulk Messaging System

An Electron Desktop app for marketing campaign & broadcast management, using either whatsapp, gmail or a SMTP server

Pyodide runtime integration

Introduction#

Pyodide loads a bundled Python parser in the renderer so manual number entry can run without a live Flask server.

Project structure#

The Pyodide integration is primarily implemented in the Electron renderer process. The key elements are:

  • A utility module that dynamically loads Pyodide and executes Python scripts
  • A Python script that parses manual phone numbers and returns structured results
  • React components that trigger the parsing workflow
  • Electron main/preload processes that manage IPC and application lifecycle

Core components#

  • Pyodide loader and executor: Dynamically loads the Pyodide runtime from a CDN, initializes it with a specific index URL, and runs a Python script to register functions in the Python namespace.
  • Python parser: Implements phone number cleaning and parsing logic, returning a structured result compatible with JSON serialization.
  • React UI integration: Provides manual number input and triggers parsing via the Pyodide utility, displaying results and errors in the UI.
  • IPC bridge: Exposes Electron APIs to the renderer process and manages WhatsApp-related IPC channels.

Key responsibilities:

  • Pyodide loader: Loads the runtime once, initializes it, and injects the Python script into the interpreter.
  • Python parser: Validates and formats phone numbers, splits name-number pairs, and returns a normalized contact list.
  • UI integration: Handles user input, error reporting, and updates the contact list upon successful parsing.
  • IPC bridge: Enables secure communication between the renderer and main process for non-Python tasks (e.g., WhatsApp operations).

Architecture overview#

The system uses a hybrid architecture:

  • Electron renderer (React) handles UI and user interactions.
  • Pyodide runtime runs inside the renderer to execute Python code for contact parsing.
  • Electron main/preload manage IPC for non-Python tasks (e.g., WhatsApp client).
  • Build pipeline places Python scripts into the renderer’s static assets so they can be fetched and executed by Pyodide.

Detailed component analysis#

Pyodide loader and executor#

The loader checks that the Pyodide runtime is available, initializes it with a specific index URL, and injects the Python script into the interpreter. It also provides a convenience function to parse manual numbers by escaping special characters and invoking the Python function, returning a structured result.

Implementation highlights:

  • Dynamic script injection for Pyodide runtime from a CDN
  • Initialization with a specific index URL for WebAssembly assets
  • Fetching and executing the Python script once per session
  • Safe string escaping for triple-quoted Python strings
  • Returning JSON-parsed results to the caller

Python parser implementation#

The Python script implements phone number cleaning and parsing logic:

  • Cleans phone numbers by removing separators and validating length
  • Supports name-number pairs separated by colon, dash, or pipe
  • Normalizes numbers and assigns default names when missing
  • Returns a structured dictionary with success status, contacts, count, and message

React UI integration#

The UI components orchestrate the user experience:

  • Manual number input and validation
  • Triggering the Pyodide-based parsing
  • Updating contact lists and logs
  • Handling errors and displaying feedback

IPC communication bridge#

The preload script exposes a controlled API to the renderer, enabling secure IPC with the main process. While Pyodide runs in the renderer, other features (e.g., WhatsApp client) communicate via IPC channels.

Dependency analysis#

  • Build-time dependencies: Vite builds the React app and outputs to dist-react, placing Python scripts alongside the built assets.
  • Runtime dependencies: The renderer dynamically loads Pyodide from a CDN and fetches the Python script from the built assets.
  • IPC dependencies: The preload bridge exposes Electron APIs to the renderer, while Pyodide remains isolated within the renderer.

Performance considerations#

  • Pyodide initialization cost: The first-time load of the Pyodide runtime and the Python script incurs network latency and initialization overhead. Subsequent calls reuse the initialized interpreter.
  • Memory footprint: WebAssembly-based Python has memory constraints in browsers. Large input sets may increase memory pressure; consider batching or streaming input.
  • Network reliability: Loading from a CDN introduces potential failures; implement retries and offline fallbacks where feasible.
  • JSON serialization overhead: Converting between Python and JavaScript via JSON adds CPU overhead; minimize unnecessary conversions.
  • Regex complexity: Phone number parsing uses multiple regex operations; keep input sizes reasonable to avoid long processing times.
  • UI responsiveness: Long-running parsing should be offloaded to worker threads or scheduled to avoid blocking the UI thread.

Troubleshooting guide#

Common issues and resolutions:

  • Pyodide not loaded: Ensure the CDN URL is reachable and the script injection completes successfully.
  • Python script not found: Verify the path to the Python script in the built assets matches the fetch URL.
  • JSON serialization errors: Confirm the Python function returns a serializable structure and that the result is parsed correctly in JavaScript.
  • CORS or asset serving: Confirm the built assets are served correctly by the development server or production static hosting.
  • Error handling in UI: Wrap parsing calls in try/catch blocks and display clear messages.

Conclusion#

If manual parse fails only offline, check that the Pyodide assets and parser script were copied into the renderer build.

Appendices#

Build process for embedding Python scripts#

  • Vite configuration outputs the React app to dist-react with a base path suitable for Electron packaging.
  • Python scripts are placed under dist-react/py and public/py.
  • The loader fetches the script from the built assets path, so it is bundled with the renderer.

Distribution of pyodide runtime assets#

  • The loader initializes Pyodide with a specific index URL pointing to the CDN-hosted runtime assets.
  • Ensure the CDN endpoint is accessible and the index URL matches the intended runtime version.

Error handling and debugging approaches#

  • Wrap Pyodide calls in try/catch blocks and surface meaningful error messages to users.
  • Use the Electron DevTools for debugging the renderer process and inspect network requests for asset loading.
  • Validate input before passing to Python to reduce runtime errors.
  • Monitor memory usage and consider chunking large inputs to prevent excessive memory consumption.