WordInk GitHub

Quickstart: plain HTML

No build step. One script tag, one element.

1. Add the element

<textarea id="message"></textarea>
<wordink-mic for="message" endpoint="/api/wordink"></wordink-mic>

<script
  type="module"
  src="https://cdn.jsdelivr.net/npm/@wordink/web@0.1.0/dist/wordink-web.cdn.js"
  integrity="sha384-lWbge/8tkdUwVOrb/hLdE3Paghx10JgJo4H3WEhznZWbZpd0ur7kOP9MFCRI/kUI"
  crossorigin="anonymous"
></script>

for is the id of the field to dictate into: an <input>, a <textarea> or a contenteditable. Hold the button, speak, release, and the text is inserted at the cursor.

The pinned version and the integrity hash

The script URL pins an exact version (@wordink/web@0.1.0), and integrity is the Subresource Integrity hash of that exact file, so the browser refuses to run it if the CDN ever serves different bytes. SRI on a cross-origin script needs crossorigin="anonymous". The hash on this page is generated from the release build when the docs are published. To compute or check it yourself:

curl -sL https://cdn.jsdelivr.net/npm/@wordink/web@0.1.0/dist/wordink-web.cdn.js \
  | openssl dgst -sha384 -binary | openssl base64 -A

Prefix the output with sha384-. When you upgrade, change the version and the hash together.

The CDN build is one ES module (about 11 KB gzipped) with @wordink/core bundled in. It fetches the core WebAssembly file (wordink_core_bg.wasm, about 35 KB gzipped) from beside itself. The integrity attribute covers the script, not that .wasm fetch. If you want both under your control, self-host them: copy dist/wordink-web.cdn.js and dist/wordink_core_bg.wasm from the @wordink/web package into one directory on your site and point src at it.

2. Point it at your relay

endpoint="/api/wordink" is the URL of your @wordink/server relay. The relay holds your provider key, so the key never reaches the page. It takes a few lines on Cloudflare Workers or Node; the relay guide has the setup, including the authorize check it requires.

To switch providers, change one attribute: provider="groq" (the default), "openai" or "deepgram". See the provider comparison.

Trying it before you have a relay

On localhost you can skip the relay and give the element a provider key directly:

<script type="module">
  document.querySelector("wordink-mic").devKey = "gsk_…"; // localhost only
</script>

Remove the endpoint attribute when you do: the element takes one or the other. A dev key only works when the page is served from localhost, 127.0.0.1 or [::1], and anyone who can open the page can read it. Read the dev key warning before using one.

No key at all: the local engine

@wordink/local runs speech recognition in the browser, so it needs no key and no relay. Its model runs in a Web Worker, and browsers only start workers from your own origin, so serve its two files from your site. Make them once:

npm install @wordink/local@1.0.0 esbuild
npx esbuild node_modules/@wordink/local/dist/index.js node_modules/@wordink/local/dist/worker.js --bundle --format=esm --outdir=wordink-local

That writes wordink-local/index.js and wordink-local/worker.js. Next to them, create index.html:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Dictation</title>
  </head>
  <body>
    <textarea id="message" rows="5"></textarea>
    <wordink-mic for="message"></wordink-mic>

    <script
      type="module"
      src="https://cdn.jsdelivr.net/npm/@wordink/web@0.1.0/dist/wordink-web.cdn.js"
      integrity="sha384-lWbge/8tkdUwVOrb/hLdE3Paghx10JgJo4H3WEhznZWbZpd0ur7kOP9MFCRI/kUI"
      crossorigin="anonymous"
    ></script>
    <script type="module">
      import { createLocalProvider } from "./wordink-local/index.js";
      document.querySelector("wordink-mic").provider = createLocalProvider();
    </script>
  </body>
</html>

Serve the directory (for example npx serve . or python3 -m http.server 8000) and open it at http://localhost:…. The first press downloads the model (about 32 MB); later visits load it from the browser cache, and dictation then works offline. The page has to be a secure context (HTTPS or localhost) because the model files are checksum-verified with WebCrypto.

Next