JS / Qiskit projects

Build interactive, visual quantum projects in JavaScript: the Qiskit API in the browser, your own HTML and CSS for output, and Python files when you want them.

In a JS / Qiskit project, you write JavaScript that calls the Qiskit API, and you render the results into your own HTML and CSS. The project runs entirely in the browser, in a sandboxed iframe, which means it has no browser storage and keeps nothing between runs; see Saving data between runs. Build one when you want a widget, an animation, or a custom chart rather than plain text output. For standard, textual quantum work, use Python / Qiskit instead.

The files

A project with index.html and main.js at the top level runs as a JS project. The runtime environment explains how the files decide. index.html and the optional main.css define the page your results are drawn on, and main.js runs the circuit and updates that page. The page appears above the console when you run the project.

main.js can import your other JavaScript files with ./ paths, and your Python files by their dotted module name, so the quantum work can live in Python while JavaScript draws the page:

import * as bell from 'quantum.bell';   // your quantum/bell.py

const counts = (await bell.run_bell.callPromising(backend, 1000)).toJs();

Call the functions in your own Python files through .callPromising, as above, or .callPromisingKwargs when you pass keyword arguments. On IonQ backends, a plain call such as bell.run_bell(backend, 1000) stops the run with a ConnectionError that says XHR is not supported.

Use named imports or import * as; a default import of a Python module gives undefined. Importing your own files has the details.

The Code tab of a JS project: a file tree with quantum and ui folders beside index.html, main.css and main.js, and main.js open in the editor.
A JS project in the file tree view: main.js imports ui/chart.js and the Python module quantum/bell.py.

The API

The API is the Python Qiskit 2.x API made available to JavaScript, so it looks close to Python, with a few conventions:

  • Import from qiskit. For example import { QuantumCircuit } from 'qiskit', or import { JobStatus } from 'qiskit.providers.jobstatus'.
  • No new. Create objects by calling the constructor directly, just like Python: const circuit = QuantumCircuit(2, 2). Methods match Qiskit too, such as circuit.h(0) and circuit.measure([0, 1], [0, 1]).
  • Named arguments use .callKwargs. Where Python takes keyword arguments, pass them as a trailing object through callKwargs: circuit.draw.callKwargs({ output: 'mpl' }).
  • Unpack Python values with .toJs(). Return values arrive as proxies to Python objects. Call .toJs() to use one as plain JavaScript data, for example result.get_counts().toJs().
  • backend is pre-created, and running is async. Submit with const job = await backend.run(circuit, { shots: 100 }). The code runs in an async context, so top-level await works, and the injected setTimeout returns a promise you can await while polling job.status() against JobStatus.DONE and JobStatus.ERROR.

A minimal example

import { QuantumCircuit } from 'qiskit';

// No `new`: call the constructor like the Python API
const circuit = QuantumCircuit(2, 2);
circuit.h(0);
circuit.cx(0, 1);
circuit.measure([0, 1], [0, 1]);

// `backend` is pre-created; run() is async and returns a job
const job = await backend.run(circuit, { shots: 100 });

// Python objects come back as proxies; .toJs() unpacks them
const counts = (await job.result()).get_counts().toJs();

// Render into the HTML you defined
document.getElementById('legend').textContent = JSON.stringify(counts);

Drawing circuits

circuit.draw.callKwargs({ output: 'mpl' }) returns a Matplotlib figure. The call needs Qiskit Visualizations turned on first, in the Libraries list. Pass the figure to URL.createObjectURL(figure) to get a URL you can drop into an <img>; the runtime turns the figure into an SVG.

Stay in the loop.

Get the latest tutorials, demos, and project showcases straight to your inbox. No noise, just the good stuff.