Code playground visualizations

I'm a big fan of interactive code snippets in all kinds of technical writing, from product docs to online courses to blog posts. Like this one:

def greet(name):
    print(f"Hello, {name}!")

greet("World")

And while having plain text output is fine in many cases, sometimes it's better to present results in a more visual way. Let me show you some examples, and then move on to the implementation.

Plotting with Python

Everyone knows Python's matplotlib and its pyplot module, popularized by Jupyter notebooks. But wouldn't it be nice to visualize the data in any article, not just notebooks?

Using some random data:

import numpy as np
import matplotlib.pyplot as plt

data = {
    "a": np.arange(50),
    "c": np.random.randint(0, 50, 50),
    "d": np.random.randn(50)
}
data["b"] = data["a"] + 10 * np.random.randn(50)
data["d"] = np.abs(data["d"]) * 100

plt.scatter("a", "b", c="c", s="d", data=data)
plt.xlabel("alice")
plt.ylabel("bob")
plt.title("Alice vs. Bob")
plt.tight_layout()
plt.show()

Or a dataset (employees.json):

import json
import seaborn as sns

employees = json.load(open("employees.json"))
salaries = {"hr": 0, "it": 0, "sales": 0}
for empl in employees:
    salaries[empl["department"]] += empl["salary"]

fig, ax = plt.subplots(figsize=(3.5, 3.5))
ax.pie(
    salaries.values(), labels=salaries.keys(),
    colors=sns.color_palette('Set2'),
    autopct='%1d%%',
)
plt.title("Salary by department")
plt.tight_layout()
plt.show()

Sumulations with JavaScript

We can also use JavaScript to display data (here using Chart.js):

const resp = await fetch("employees.json");
const employees = await resp.json();
const names = employees.map((empl) => empl.name);
const salaries = employees.map((empl) => empl.salary);

const data = {
    labels: names,
    datasets: [
        {
            label: "Salaries",
            data: salaries,
            borderWidth: 1,
        },
    ],
};

const el = document.createElement("canvas");
new Chart(el, { type: "bar", data: data });
return el;

But we've already tried that with Python. I'm thinking of something else. How about a dynamic simulation? A bouncing ball is a classic example, so let's go for it:

const canvas = document.createElement("canvas");
canvas.width = 340;
canvas.style.border = "1px solid #ccc";

// Ball class definition hidden for brevity
const ball = new Ball({
    canvas: canvas,
    x: canvas.width / 2,
    y: canvas.height / 2,
    dx: 2,
    dy: 2,
});
ball.bounce();

return canvas;

Try changing dx or dy to increase speed and re-run the snippet (by the way, you can use Ctrl+Enter or Cmd+Enter to run the code while editing).

Full code

Drawing with Go

Who said we should limit ourselves to "conventional" dataviz languages like Python or JavaScript? Go can be fun too!

// Circle definition hidden for brevity
circles := []Circle{
    {100, "#babeee"},
    {75, "#7573b6"},
    {50, "#70acb4"},
    {25, "#90d2c3"},
    {5, "#ecf4be"},
}

// SVG definition hidden for brevity
svg := SVG{200, 200}

svg.printHeader()
for _, c := range circles {
    svg.printCircle(c, 100, 100)
}
svg.printFooter()

Try changing the radius and color in circles and re-run the snippet.

Full code

Charting with SQL

How about drawing a bar chart for our employees dataset right in SQL? A little crazy, maybe, but doable:

with data as (
  select
    row_number() over w as rnum,
    name, salary
  from employees
  window w as (order by id)
)
-- chart rendering query part hidden for brevity

Try changing the order by clause from id to salary desc or name and re-run the snippet.

Full query

Combining playgrounds

Suppose we have an SQL playground that selects employees according to some criteria:

select id, name, salary
from employees
where department = 'it';

What I'd like to do is to take the query results and feed them into the Python playground:

import json
import seaborn as sns

employees = json.load(open("employees.json"))
names = [empl["name"] for empl in employees]
salaries = [empl["salary"] for empl in employees]

plt.figure(figsize=(5, 3))
plt.barh(names, salaries)
plt.title("Employee salaries")
plt.tight_layout()
plt.show()

Voilà! Try changing the department in the SQL playground to hr or sales, re-run the SQL playground, then re-run the Python playground, and see how the bar graph reflects the SQL results.

Implementation

Did I already told you I'm a big fan of interactive code snippets in all kinds of technical writing? I even built an open source tool called Codapi for embedding such snippets.

Suppose you have a static code example in your documentation:

```python
def greet(name):
    print(f"Hello, {name}!")

greet("World")
```

To make it interactive, add a codapi-snippet widget directly below:

<codapi-snippet sandbox="python" editor="basic">
</codapi-snippet>

The widget attaches itself to the preceding code block, allowing the reader to run and edit the code:

def greet(name):
    print(f"Hello, {name}!")

greet("World")

The code runs on the sandbox server or (for some playgrounds) directly in the browser using browser APIs or WebAssembly.

Previously, the widget only supported text output. Now it supports different output modes: text, SVG images, custom HTML, and even interactive DOM.

SVG images

To display an image, set the output-mode attribute to svg and print the image as an SVG string from your code snippet.

Code snippet (Python + matplotlib):

import io
import numpy as np
import matplotlib.pyplot as plt

data = {"a": np.arange(50), "c": np.random.randint(0, 50, 50), "d": np.random.randn(50)}
data["b"] = data["a"] + 10 * np.random.randn(50)
data["d"] = np.abs(data["d"]) * 100

plt.scatter("a", "b", c="c", s="d", data=data)
plt.xlabel("entry a")
plt.ylabel("entry b")
plt.show()

stream = io.StringIO()
plt.savefig(stream, format="svg")
print(stream.getvalue())

Widget:

<codapi-snippet sandbox="python" output-mode="svg">
</codapi-snippet>

Output when run:

SVG chart

HTML fragments

To display HTML content, set the output-mode attribute to html and print an HTML string from your code snippet.

Code snippet (Python):

html = """<blockquote>
    I am <em>so</em> <strong>excited</strong>!
</blockquote>"""
print(html)

Widget:

<codapi-snippet sandbox="python" output-mode="html">
</codapi-snippet>

Output when run:

I am so excited!

Interactive DOM

When using the JavaScript playground (engine=browser, sandbox=javascript), you can render a DOM node as an output. To do so, set the output-mode attribute to dom and return a DOM node from your code snippet.

Code snippet (JavaScript + Chart.js):

const el = document.createElement("canvas");

new Chart(el, {
    type: "bar",
    data: {
        labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
        datasets: [
            {
                label: "# of Votes",
                data: [12, 19, 3, 5, 2, 3],
                borderWidth: 1,
            },
        ],
    },
});

return el;

Widget:

<codapi-snippet engine="browser" sandbox="javascript" output-mode="dom">
</codapi-snippet>

Output when run:

Summary

Interactive code snippets are a great addition to tutorials, how-to guides, and reference documentation. Playgrounds with visual output are even better: they help readers to make sense of the data, preview an interface, or see a process simulation.

With the latest Codapi release, you can easily create visual interactive examples using the output-mode attribute.

If you are interested — try using Codapi in your product docs, blog or online course. You can start with the widget and add the sandbox server as needed (or use the cloud instance).

Let's make the world of technical documentation a little better!

 Subscribe to keep up with new posts.