Developer Reference

SPOT Writer Web Integration Guide

Integration guide for developers who want to launch SPOT Writer from their own web site in an iframe or popup window.

SPOT Writer Web Integration Guide

This document describes how to embed SPOT Writer into a parent site. It is intended for developers implementing site-side workflows such as “Program Receiver” or “Write to SPOT”.

SPOT Writer is intentionally narrow in scope. It does not edit radio content. It accepts a SPOT JSON configuration, connects to a receiver with Web Serial, and writes that configuration to the receiver.

Overview

The web integration model is simple:

  1. Your site launches SPOT Writer in embedded mode.
  2. SPOT Writer sends a ready status back to the parent.
  3. Your site sends a SPOT JSON configuration to SPOT Writer with postMessage.
  4. SPOT Writer loads the configuration and writes it to the receiver when the user presses Write.
  5. SPOT Writer reports status changes back to the parent site with additional postMessage events.

Requirements

  • The writer page must be served from a secure context. In production this means https://. For local testing, http://localhost is acceptable.
  • The browser must support the Web Serial API.
  • The receiver must be connected by USB and powered on before the user attempts to write.
  • Your site may require allow="serial" in the iframe definition.

Launch Modes

SPOT Writer supports two site integration styles:

  • iframe: recommended when you want the writer visually contained within the parent page.
  • popup window: useful when you want the writer isolated in its own window or tab.

In both cases, embedded mode is enabled by loading the writer with ?embedded in the URL. For example:

https://spotwildlife.org/tools/spot_writer/?embedded

Parent to Writer Message

Once the writer reports that it is ready, the parent site sends a configuration message:

childWindow.postMessage(
  {
    type: "spot-writer-config",
    configText: "{...raw SPOT JSON text...}",
    configSource: "Wildlife Central",
    showReturnButton: true
  },
  targetOrigin
);

Fields

  • type: must be "spot-writer-config"
  • configText: required SPOT JSON text
  • configSource: optional source name shown in the writer UI
  • showReturnButton: optional boolean; if true, the writer shows a “Return to …” button

The parent should wait for the writer to send code: "ready" before posting the first configuration. After that, the parent may send a replacement configuration later if it wants to re-arm the same writer page for another write.

In production, use a specific targetOrigin rather than "*" when calling postMessage.

Writer to Parent Status

The writer reports its state to the parent site with spot-writer-status messages:

{
  type: "spot-writer-status",
  code: "ready" |
        "config-accepted" |
        "config-rejected" |
        "write-started" |
        "write-succeeded" |
        "write-failed",
  message: "Human-readable status text"
}

Status Codes

  • ready: the writer page is loaded and ready to receive a configuration
  • config-accepted: the supplied JSON was accepted and loaded
  • config-rejected: the supplied JSON was rejected, or a new config arrived while the writer was busy
  • write-started: writing has begun; the parent should stop sending replacement configs
  • write-succeeded: the write completed successfully
  • write-failed: the write failed, including connect failures that prevent writing from starting

If the parent supplies invalid JSON, the writer shows an error in its own status area and also sends code: "config-rejected" back to the parent.

Multiple Configurations

The writer can accept more than one parent-supplied configuration over time. Each accepted spot-writer-config message replaces the currently loaded configuration, which allows the parent to re-arm the writer for another programming pass without reloading the page.

However, if a new configuration arrives while the writer is busy loading, connecting, or writing, the writer rejects it and sends spot-writer-status with code: "config-rejected".

iframe Example

<iframe
  id="spot-writer-frame"
  src="https://spotwildlife.org/tools/spot_writer/?embedded"
  title="SPOT Writer"
></iframe>
const frame = document.getElementById("spot-writer-frame");
const writerOrigin = "https://your-host.example";
const configText = "...raw SPOT JSON text...";

window.addEventListener("message", (event) => {
  if (event.origin !== writerOrigin) {
    return;
  }

  if (event.data?.type !== "spot-writer-status") {
    return;
  }

  if (event.data.code === "ready") {
    frame.contentWindow?.postMessage(
      {
        type: "spot-writer-config",
        configText,
        configSource: "Your Site",
        showReturnButton: false
      },
      writerOrigin
    );
  }
});

In an iframe integration, the writer remains part of the parent page, so showReturnButton is usually left false.

const writerUrl = "https://spotwildlife.org/tools/spot_writer/?embedded";
const writerOrigin = "https://your-host.example";
const popup = window.open(writerUrl, "spot-writer", "popup,width=1280,height=980");
const configText = "...raw SPOT JSON text...";

window.addEventListener("message", (event) => {
  if (event.origin !== writerOrigin) {
    return;
  }

  if (event.source !== popup) {
    return;
  }

  if (event.data?.type !== "spot-writer-status") {
    return;
  }

  if (event.data.code === "ready") {
    popup?.postMessage(
      {
        type: "spot-writer-config",
        configText,
        configSource: "Your Site",
        showReturnButton: true
      },
      writerOrigin
    );
  }
});

Popup mode is useful when the writer should run in a separate window or tab. If your site wants the writer page to offer a return path, set showReturnButton: true. The writer uses browser history first and falls back to window.close() when possible.

Practical Notes

  • If the user previously chose the wrong serial port and a connection fails, the writer clears remembered serial-port permissions before the next attempt so the browser can prompt again.
  • A parent site may choose to visibly react to status messages such as write-started, write-succeeded, and write-failed, but that is a site-level policy decision rather than a requirement of the writer.
  • Sample integration pages are included with the writer distribution under /tools/spot_writer/samples/.
  • While in embedded mode, SPOT Writer trusts the JSON file sent to it by the parent. In particular, if the parent sends a JSON file with device-specific information, it will be programmed into the target device without question or warning.

Implementation Checklist

  1. In general, use the hosted SPOT Writer at https://spotwildlife.org/tools/spot_writer.
  2. Listen for spot-writer-status and wait for ready.
  3. Send a spot-writer-config message containing valid SPOT JSON text.
  4. React to config-rejected, write-started, write-succeeded, and write-failed in a way that fits your site.
  5. If you support repeated programming from the same page, only send replacement configs when the writer is not busy.

Testing

For local testing, the sample pages bundled with SPOT Writer are a useful starting point:

  • /tools/spot_writer/samples/wildlife-central.html
  • /tools/spot_writer/samples/wildlife-popup.html

These demonstrate the expected message exchange and can be used to validate a local or staging deployment before integrating with a production site.