Run in a Browser
refkit-js loads RefKit's Rust core as WebAssembly, a compiled module executed by the browser. Install the package with npm install refkit-js, then initialize it before using the shared bibliography API.
Initialize the module
Use this example in an existing browser application built with a bundler such as Vite. Put it in the application's TypeScript entry module, for example src/main.ts, and start the application with its development command, typically npm run dev. The bundler resolves the npm import and serves the compiled module.
Use a browser with WebAssembly and FinalizationRegistry, the JavaScript facility that releases native resources when objects become unreachable.
import * as rk from "refkit-js/browser";
await rk.init();
const library = rk.Library.parseBibtex(
"@book{doe2024, author={Doe, Jane}, title={Browser Citations}, year={2024}}",
);
console.log(rk.cite(library, "doe2024").text);The browser console prints (Doe, 2024). After initialization, parsing, rendering, and editing are synchronous. Concurrent init() calls share the loading operation, and later calls reuse the initialized module.
Load on demand
Importing the browser entry loads the JavaScript API. The first init() loads the generated bindings and WebAssembly through a dynamic import. Put init() in the action that first needs bibliography processing:
import { init, Library, cite } from "refkit-js/browser";
export async function renderCitation(source: string, key: string): Promise<string> {
await init();
return cite(Library.parseBibtex(source), key).text;
}Call renderCitation(source, key) from an editor action or a file-selection handler. An application that needs RefKit immediately can await init() during startup. An application that can predict demand can call it earlier to preload the engine. Await the same initialization before processing input, and handle its rejection if loading fails. A failed WebAssembly download or compilation can be retried by calling init() again.
Keep code splitting enabled so the bundler preserves the deferred import. A build that combines dynamic imports into its entry file pays the embedded payload cost when that file loads. Vite library builds embed assets in JavaScript, so RefKit keeps its binary URL inside the deferred bindings. When publishing a library, keeping refkit-js external lets the consuming application own asset emission and caching.
Serve the WebAssembly asset
The default loader resolves the packaged .wasm file relative to its JavaScript module. Bundlers such as Vite can emit this asset and rewrite its URL. Keep the JavaScript and WebAssembly files from the same package version together.
For an explicit asset location, copy the file exported as refkit-js/refkit.wasm to your public assets and initialize with its URL:
import { init } from "refkit-js/browser";
await init(new URL("/assets/refkit.wasm", location.origin));Serve it over HTTP or HTTPS with the application/wasm media type. Cross-origin assets need an appropriate Cross-Origin Resource Sharing response from the asset server.
If the application sets a Content Security Policy, allow WebAssembly compilation with 'wasm-unsafe-eval' in script-src and allow the asset origin in connect-src. A same-origin policy can include:
script-src 'self' 'wasm-unsafe-eval'; connect-src 'self'Read user-supplied files
The File API reads a file selected by the user. Pass its text to the shared parser:
import { Library } from "refkit-js/browser";
async function readBibliography(file: File) {
return Library.parseBibtex(await file.text());
}Call this function after initialization. File.text() decodes UTF-8. RefKit's Node file helpers also handle Windows-1252-compatible bibliography files.
Use a worker for longer operations
A Web Worker runs work off the browser's main thread. Import and initialize RefKit inside each module worker, then return text or ordinary result records through postMessage:
import * as rk from "refkit-js/browser";
await rk.init();
self.onmessage = ({ data }: MessageEvent<string>) => {
const library = rk.Library.parseBibtex(data);
self.postMessage(rk.fullBibliography(library));
};Each worker has its own module and bibliography objects. Pass source text or result records between workers. Follow the shared guides for parsing, rendering, editing, and formatting.
To run the Python binding inside a browser, use Pyodide.