Installation
Auto-mount (one script + one div)
Paste these two lines wherever you want the widget to appear. The script attaches on DOMContentLoaded and mounts every element that carries data-glyphward-embed.
<div data-glyphward-embed></div>
<script async src="https://glyphward.com/embed.js"></script>
Programmatic mount
If you control mounting (SPA, late-rendered modal, multiple instances), call Glyphward.mount() after the script loads. It returns an instance with an unmount() method.
<script async src="https://glyphward.com/embed.js"
onload="
const w = Glyphward.mount('#scanner', { theme: 'dark', variant: 'compact' });
/* later: w.unmount() */
"></script>
Configuration
Configure each mount with data attributes (auto-mount path) or with the second argument to mount() (programmatic path). Both routes accept the same option names.
| Option | Values | Default | What it does |
|---|---|---|---|
theme | light · dark | light | Surface colour scheme for the widget card. |
variant | full · compact | full | compact trims padding and max-width for sidebars and cards. |
accept | image · audio · any | any | Restrict the file picker — hides the irrelevant MIME types from the OS dialog. |
What the widget does
On click or drop, the widget reads the file bytes locally, computes a SHA-256 of the payload, and combines a deterministic content-derived random with filename and MIME heuristics drawn from the public FigStep, AgentTypo, and WhisperInject literature to produce a 0–100 risk score and a verdict band (clean / low / suspicious / high). A visible “Demo scoring” chip in the header makes it explicit that this is the v0 client-side scorer; nothing is sent off-device.
When the production /v1/scan API ships with Pro, the widget switches transparently — the same embed, same UI, same daily quota chip. If the API call fails, it falls back to the local heuristic so the demo keeps working under flaky networks.
Quota and rate limits
The widget enforces 10 scans per UTC day per browser via localStorage (key: glyphward.embed.v1). The remaining quota is shown in the footer of every mount and resets at 00:00 UTC. Because storage is per-origin, multiple mounts on the same page share the same daily counter.
This is the same free-tier ceiling as the hosted scanner at glyphward.com — Pro and Team raise the cap and switch the scoring to the real /v1/scan API.
Privacy
Until the /v1/scan API ships, files never leave the visitor's machine. The widget reads bytes via FileReader.arrayBuffer(), hashes them with the WebCrypto API, and renders the verdict locally. No telemetry, no third-party analytics, no cookies — only the localStorage entry that holds the daily scan count. The single outbound link is the “Powered by Glyphward” footer anchor, which carries UTM parameters so you can attribute referrals if you wire it into your analytics.
Browser support
Modern Chromium (Chrome, Edge, Brave), Firefox, and Safari 14+. The widget needs fetch, FileReader, Shadow DOM, and (ideally) SubtleCrypto.digest. On browsers without WebCrypto it falls back to a fast non-cryptographic hash so the demo still scores; the production API path will not.
Where to next
- FigStep detection — the canonical attack the widget heuristics target.
- WhisperInject detection — the audio-side equivalent the widget also accepts.
- The multimodal prompt-injection threat model (2026) — the long-form context for why this widget exists.
- Pricing — when you outgrow the free tier.